From d0de0f776c1a712ef4b4e0b4d529cadcb85f2677 Mon Sep 17 00:00:00 2001 From: Robert Ing Date: Wed, 18 Oct 2023 10:41:31 -0400 Subject: [PATCH] passes firefox 39 but not chrome 40 --- package-lock.json | 141 +- package.json | 4 +- rollup.config.js | 24 - rollup.test.config.js | 3 +- test/cross-browser-testing/CBT-tests-es5.js | 25144 ++++- test/cross-browser-testing/CBT-tests.js | 84289 +++++++++++++--- .../browserstack.karma.config.js | 32 +- .../rollup.CBT.config.js | 2 +- test/karma.config.js | 2 +- test/src/tests-batchUploader.ts | 142 +- test/src/tests-beaconUpload.ts | 7 +- test/src/tests-consent.ts | 10 +- test/src/tests-cookie-syncing.js | 2 +- test/src/tests-core-sdk.js | 85 +- test/src/tests-eCommerce.js | 75 +- test/src/tests-event-logging.js | 162 +- test/src/tests-forwarders.js | 60 +- test/src/tests-identities-attributes.js | 176 +- test/src/tests-identity.js | 43 +- test/src/tests-main.js | 52 +- test/src/tests-mparticle-instance-manager.js | 61 +- test/src/tests-persistence.ts | 7 +- test/src/tests-self-hosting-specific.js | 14 +- 23 files changed, 93834 insertions(+), 16703 deletions(-) diff --git a/package-lock.json b/package-lock.json index eacce33d..3b6da0e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.23.4", "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.6.0", + "@babel/runtime": "^7.23.2", "core-js": "^3.33.0", "slugify": "^1.3.6" }, @@ -46,7 +46,7 @@ "eslint": "^8.36.0", "eslint-config-prettier": "9.0.0", "eslint-plugin-prettier": "3.4.1", - "fetch-mock": "^7.5.1", + "fetch-mock": "9.1.1", "gts": "^5.0.1", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", @@ -5168,31 +5168,6 @@ "integrity": "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==", "dev": true }, - "node_modules/babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, - "node_modules/babel-polyfill/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true - }, - "node_modules/babel-polyfill/node_modules/regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true - }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -7826,9 +7801,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.555", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.555.tgz", - "integrity": "sha512-k1wGC7UXDTyCWcONkEMRG/w6Jvrxi+SVEU+IeqUKUKjv2lGJ1b+jf1mqrloyxVTG5WYYjNQ+F6+Cb1fGrLvNcA==", + "version": "1.4.556", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz", + "integrity": "sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ==", "dev": true }, "node_modules/elliptic": { @@ -8810,22 +8785,28 @@ } }, "node_modules/fetch-mock": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-7.7.3.tgz", - "integrity": "sha512-I4OkK90JFQnjH8/n3HDtWxH/I6D1wrxoAM2ri+nb444jpuH3RTcgvXx2el+G20KO873W727/66T7QhOvFxNHPg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.1.1.tgz", + "integrity": "sha512-v216/fXpLttuXZloT22T5mkOTmvHIHSienp3bCuUIN6QrBfw0Bdke4O6GFAHxPKRmUMwCKPgHI2jVJBzVndlDw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "babel-polyfill": "^6.26.0", - "core-js": "^2.6.9", + "babel-runtime": "^6.26.0", + "core-js": "^3.0.0", + "debug": "^4.1.1", "glob-to-regexp": "^0.4.0", + "is-subset": "^0.1.1", "lodash.isequal": "^4.5.0", "path-to-regexp": "^2.2.1", + "querystring": "^0.2.0", "whatwg-url": "^6.5.0" }, "engines": { "node": ">=4.0.0" }, + "funding": { + "type": "charity", + "url": "https://www.justgiving.com/refugee-support-europe" + }, "peerDependencies": { "node-fetch": "*" }, @@ -8835,14 +8816,6 @@ } } }, - "node_modules/fetch-mock/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true - }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -10569,6 +10542,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true + }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -18436,6 +18415,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -25795,31 +25784,6 @@ "integrity": "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==", "dev": true }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true - } - } - }, "babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -27882,9 +27846,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.555", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.555.tgz", - "integrity": "sha512-k1wGC7UXDTyCWcONkEMRG/w6Jvrxi+SVEU+IeqUKUKjv2lGJ1b+jf1mqrloyxVTG5WYYjNQ+F6+Cb1fGrLvNcA==", + "version": "1.4.556", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz", + "integrity": "sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ==", "dev": true }, "elliptic": { @@ -28609,25 +28573,20 @@ } }, "fetch-mock": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-7.7.3.tgz", - "integrity": "sha512-I4OkK90JFQnjH8/n3HDtWxH/I6D1wrxoAM2ri+nb444jpuH3RTcgvXx2el+G20KO873W727/66T7QhOvFxNHPg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.1.1.tgz", + "integrity": "sha512-v216/fXpLttuXZloT22T5mkOTmvHIHSienp3bCuUIN6QrBfw0Bdke4O6GFAHxPKRmUMwCKPgHI2jVJBzVndlDw==", "dev": true, "requires": { - "babel-polyfill": "^6.26.0", - "core-js": "^2.6.9", + "babel-runtime": "^6.26.0", + "core-js": "^3.0.0", + "debug": "^4.1.1", "glob-to-regexp": "^0.4.0", + "is-subset": "^0.1.1", "lodash.isequal": "^4.5.0", "path-to-regexp": "^2.2.1", + "querystring": "^0.2.0", "whatwg-url": "^6.5.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - } } }, "figures": { @@ -29867,6 +29826,12 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true + }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -35800,6 +35765,12 @@ "side-channel": "^1.0.4" } }, + "querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "dev": true + }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", diff --git a/package.json b/package.json index b1fff630..8f3639a4 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "eslint": "^8.36.0", "eslint-config-prettier": "9.0.0", "eslint-plugin-prettier": "3.4.1", - "fetch-mock": "^7.5.1", + "fetch-mock": "9.1.1", "gts": "^5.0.1", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", @@ -139,7 +139,7 @@ "webpack-cli": "^5.0.2" }, "dependencies": { - "@babel/runtime": "^7.6.0", + "@babel/runtime": "^7.23.2", "core-js": "^3.33.0", "slugify": "^1.3.6" } diff --git a/rollup.config.js b/rollup.config.js index 4b50d026..3db87649 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,14 +20,6 @@ const defaultBabel = babel({ babelHelpers: 'runtime', }); -const testBabel = babel({ - ...babelSettings, - // extensions, - // include: ['src/**/*'], - babelHelpers: 'runtime', - plugins: ['@babel/plugin-transform-runtime'], -}); - const babelMinify = babel({ extensions, include: ['src/**/*'], @@ -64,22 +56,6 @@ const builds = { json(), ], }, - tests: { - input: 'test/cross-browser-testing/test-cross-browser.js', - output: { - ...defaultOutputOptions, - file: 'dist/CBT.js', - format: 'iife', - name: 'mParticle', - }, - plugins: [ - resolve(), - commonjs({ - // include: 'node_modules/**', - }), - testBabel, - ], - }, cjs: { input: 'src/mparticle-instance-manager.js', output: { diff --git a/rollup.test.config.js b/rollup.test.config.js index 380f1e3c..efbd17a8 100644 --- a/rollup.test.config.js +++ b/rollup.test.config.js @@ -15,13 +15,14 @@ const builds = { file: 'test/test-bundle.js', format: 'iife', name: 'mParticleTests', + globals: 'browser_global', sourcemap: ENVIRONMENT !== 'prod', }, plugins: [ resolve(), commonjs({ include: 'node_modules/**', - namedExports: { chai: ['expect'] }, + // namedExports: { chai: ['expect'] }, }), babel({ extensions, diff --git a/test/cross-browser-testing/CBT-tests-es5.js b/test/cross-browser-testing/CBT-tests-es5.js index 52da6626..3746e823 100644 --- a/test/cross-browser-testing/CBT-tests-es5.js +++ b/test/cross-browser-testing/CBT-tests-es5.js @@ -4,22 +4,139 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mParticleTests = factory()); })(this, (function () { 'use strict'; - function _typeof(o) { + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + return self; + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + Object.defineProperty(subClass, "prototype", { + writable: false + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _typeof$1(o) { "@babel/helpers - typeof"; - return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; - }, _typeof(o); + }, _typeof$1(o); + } + + function _possibleConstructorReturn(self, call) { + if (call && (_typeof$1(call) === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + return _assertThisInitialized(self); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _isNativeFunction(fn) { + try { + return Function.toString.call(fn).indexOf("[native code]") !== -1; + } catch (e) { + return typeof fn === "function"; + } + } + + function _isNativeReflectConstruct$1() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct$1()) { + _construct = Reflect.construct.bind(); + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + return _construct.apply(null, arguments); + } + + function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + _cache.set(Class, Wrapper); + } + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + return _wrapNativeSuper(Class); + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } } function _toPrimitive(input, hint) { - if (_typeof(input) !== "object" || input === null) return input; + if (_typeof$1(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); - if (_typeof(res) !== "object") return res; + if (_typeof$1(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); @@ -27,7 +144,87 @@ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); - return _typeof(key) === "symbol" ? key : String(key); + return _typeof$1(key) === "symbol" ? key : String(key); + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + + function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + _next(undefined); + }); + }; + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _defineProperty(obj, key, value) { @@ -77,21 +274,6 @@ } } - function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; - } - - function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); - } - function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } @@ -106,174 +288,15895 @@ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } - function commonjsRequire(path) { - throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); + var regeneratorRuntime$1 = {exports: {}}; + + var _typeof = {exports: {}}; + + _typeof.exports; + + (function (module) { + function _typeof(o) { + "@babel/helpers - typeof"; + + return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(o); + } + module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports; + } (_typeof)); + + var _typeofExports = _typeof.exports; + + regeneratorRuntime$1.exports; + + (function (module) { + var _typeof = _typeofExports["default"]; + function _regeneratorRuntime() { + module.exports = _regeneratorRuntime = function _regeneratorRuntime() { + return e; + }, module.exports.__esModule = true, module.exports["default"] = module.exports; + var t, + e = {}, + r = Object.prototype, + n = r.hasOwnProperty, + o = Object.defineProperty || function (t, e, r) { + t[e] = r.value; + }, + i = "function" == typeof Symbol ? Symbol : {}, + a = i.iterator || "@@iterator", + c = i.asyncIterator || "@@asyncIterator", + u = i.toStringTag || "@@toStringTag"; + function define(t, e, r) { + return Object.defineProperty(t, e, { + value: r, + enumerable: !0, + configurable: !0, + writable: !0 + }), t[e]; + } + try { + define({}, ""); + } catch (t) { + define = function define(t, e, r) { + return t[e] = r; + }; + } + function wrap(t, e, r, n) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype), + c = new Context(n || []); + return o(a, "_invoke", { + value: makeInvokeMethod(t, r, c) + }), a; + } + function tryCatch(t, e, r) { + try { + return { + type: "normal", + arg: t.call(e, r) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + e.wrap = wrap; + var h = "suspendedStart", + l = "suspendedYield", + f = "executing", + s = "completed", + y = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var p = {}; + define(p, a, function () { + return this; + }); + var d = Object.getPrototypeOf, + v = d && d(d(values([]))); + v && v !== r && n.call(v, a) && (p = v); + var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); + function defineIteratorMethods(t) { + ["next", "throw", "return"].forEach(function (e) { + define(t, e, function (t) { + return this._invoke(e, t); + }); + }); + } + function AsyncIterator(t, e) { + function invoke(r, o, i, a) { + var c = tryCatch(t[r], t, o); + if ("throw" !== c.type) { + var u = c.arg, + h = u.value; + return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { + invoke("next", t, i, a); + }, function (t) { + invoke("throw", t, i, a); + }) : e.resolve(h).then(function (t) { + u.value = t, i(u); + }, function (t) { + return invoke("throw", t, i, a); + }); + } + a(c.arg); + } + var r; + o(this, "_invoke", { + value: function value(t, n) { + function callInvokeWithMethodAndArg() { + return new e(function (e, r) { + invoke(t, n, e, r); + }); + } + return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); + } + }); + } + function makeInvokeMethod(e, r, n) { + var o = h; + return function (i, a) { + if (o === f) throw new Error("Generator is already running"); + if (o === s) { + if ("throw" === i) throw a; + return { + value: t, + done: !0 + }; + } + for (n.method = i, n.arg = a;;) { + var c = n.delegate; + if (c) { + var u = maybeInvokeDelegate(c, n); + if (u) { + if (u === y) continue; + return u; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (o === h) throw o = s, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = f; + var p = tryCatch(e, r, n); + if ("normal" === p.type) { + if (o = n.done ? s : l, p.arg === y) continue; + return { + value: p.arg, + done: n.done + }; + } + "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); + } + }; + } + function maybeInvokeDelegate(e, r) { + var n = r.method, + o = e.iterator[n]; + if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; + var i = tryCatch(o, e.iterator, r.arg); + if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; + var a = i.arg; + return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); + } + function pushTryEntry(t) { + var e = { + tryLoc: t[0] + }; + 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); + } + function resetTryEntry(t) { + var e = t.completion || {}; + e.type = "normal", delete e.arg, t.completion = e; + } + function Context(t) { + this.tryEntries = [{ + tryLoc: "root" + }], t.forEach(pushTryEntry, this), this.reset(!0); + } + function values(e) { + if (e || "" === e) { + var r = e[a]; + if (r) return r.call(e); + if ("function" == typeof e.next) return e; + if (!isNaN(e.length)) { + var o = -1, + i = function next() { + for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; + return next.value = t, next.done = !0, next; + }; + return i.next = i; + } + } + throw new TypeError(_typeof(e) + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { + value: GeneratorFunctionPrototype, + configurable: !0 + }), o(GeneratorFunctionPrototype, "constructor", { + value: GeneratorFunction, + configurable: !0 + }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { + var e = "function" == typeof t && t.constructor; + return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); + }, e.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; + }, e.awrap = function (t) { + return { + __await: t + }; + }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { + return this; + }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(wrap(t, r, n, o), i); + return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { + return this; + }), define(g, "toString", function () { + return "[object Generator]"; + }), e.keys = function (t) { + var e = Object(t), + r = []; + for (var n in e) r.push(n); + return r.reverse(), function next() { + for (; r.length;) { + var t = r.pop(); + if (t in e) return next.value = t, next.done = !1, next; + } + return next.done = !0, next; + }; + }, e.values = values, Context.prototype = { + constructor: Context, + reset: function reset(e) { + if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); + }, + stop: function stop() { + this.done = !0; + var t = this.tryEntries[0].completion; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function dispatchException(e) { + if (this.done) throw e; + var r = this; + function handle(n, o) { + return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; + } + for (var o = this.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i.completion; + if ("root" === i.tryLoc) return handle("end"); + if (i.tryLoc <= this.prev) { + var c = n.call(i, "catchLoc"), + u = n.call(i, "finallyLoc"); + if (c && u) { + if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); + if (this.prev < i.finallyLoc) return handle(i.finallyLoc); + } else if (c) { + if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); + } else { + if (!u) throw new Error("try statement without catch or finally"); + if (this.prev < i.finallyLoc) return handle(i.finallyLoc); + } + } + } + }, + abrupt: function abrupt(t, e) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var o = this.tryEntries[r]; + if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { + var i = o; + break; + } + } + i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); + var a = i ? i.completion : {}; + return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); + }, + complete: function complete(t, e) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; + }, + finish: function finish(t) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var r = this.tryEntries[e]; + if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; + } + }, + "catch": function _catch(t) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var r = this.tryEntries[e]; + if (r.tryLoc === t) { + var n = r.completion; + if ("throw" === n.type) { + var o = n.arg; + resetTryEntry(r); + } + return o; + } + } + throw new Error("illegal catch attempt"); + }, + delegateYield: function delegateYield(e, r, n) { + return this.delegate = { + iterator: values(e), + resultName: r, + nextLoc: n + }, "next" === this.method && (this.arg = t), y; + } + }, e; + } + module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports; + } (regeneratorRuntime$1)); + + var regeneratorRuntimeExports = regeneratorRuntime$1.exports; + + // TODO(Babel 8): Remove this file. + + var runtime = regeneratorRuntimeExports(); + var regenerator = runtime; + + // Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736= + try { + regeneratorRuntime = runtime; + } catch (accidentalStrictMode) { + if (typeof globalThis === "object") { + globalThis.regeneratorRuntime = runtime; + } else { + Function("r", "regeneratorRuntime = r")(runtime); + } } - var CBTTests$1 = {}; + var _regeneratorRuntime = /*@__PURE__*/getDefaultExportFromCjs(regenerator); - function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray2(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return {s:F,n:function n(){if(i>=o.length)return {done:true};return {done:false,value:o[i++]};},e:function e(_e){throw _e;},f:F};}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}var normalCompletion=true,didErr=false,err;return {s:function s(){it=it.call(o);},n:function n(){var step=it.next();normalCompletion=step.done;return step;},e:function e(_e2){didErr=true;err=_e2;},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]();}finally{if(didErr)throw err;}}};}function _unsupportedIterableToArray2(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray2(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray2(o,minLen);}function _arrayLikeToArray2(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i=0){return args[callArgAt];}var argumentList;if(callArgAt===useLeftMostCallback){argumentList=args;}if(callArgAt===useRightMostCallback){argumentList=reverse(slice(args));}var callArgProp=behavior.callArgProp;for(var i=0,l=argumentList.length;i0){msg+=" Received [".concat(join(args,", "),"]");}return msg;}return "argument at index ".concat(behavior.callArgAt," is not a function: ").concat(func);}function ensureArgs(name,behavior,args){// map function name to internal property - // callsArg => callArgAt - var property=name.replace(/sArg/,"ArgAt");var index=behavior[property];if(index>=args.length){throw new TypeError("".concat(name," failed: ").concat(index+1," arguments required but only ").concat(args.length," present"));}}function callCallback(behavior,args){if(typeof behavior.callArgAt==="number"){ensureArgs("callsArg",behavior,args);var func=getCallback(behavior,args);if(typeof func!=="function"){throw new TypeError(getCallbackError(behavior,func,args));}if(behavior.callbackAsync){nextTick(function(){func.apply(behavior.callbackContext,behavior.callbackArguments);});}else {return func.apply(behavior.callbackContext,behavior.callbackArguments);}}return undefined;}var proto={create:function create(stub){var behavior=extend({},proto);delete behavior.create;delete behavior.addBehavior;delete behavior.createBehavior;behavior.stub=stub;if(stub.defaultBehavior&&stub.defaultBehavior.promiseLibrary){behavior.promiseLibrary=stub.defaultBehavior.promiseLibrary;}return behavior;},isPresent:function isPresent(){return typeof this.callArgAt==="number"||this.exception||this.exceptionCreator||typeof this.returnArgAt==="number"||this.returnThis||typeof this.resolveArgAt==="number"||this.resolveThis||typeof this.throwArgAt==="number"||this.fakeFn||this.returnValueDefined;},/*eslint complexity: ["error", 20]*/invoke:function invoke(context,args){/* - * callCallback (conditionally) calls ensureArgs - * - * Note: callCallback intentionally happens before - * everything else and cannot be moved lower - */var returnValue=callCallback(this,args);if(this.exception){throw this.exception;}else if(this.exceptionCreator){this.exception=this.exceptionCreator();this.exceptionCreator=undefined;throw this.exception;}else if(typeof this.returnArgAt==="number"){ensureArgs("returnsArg",this,args);return args[this.returnArgAt];}else if(this.returnThis){return context;}else if(typeof this.throwArgAt==="number"){ensureArgs("throwsArg",this,args);throw args[this.throwArgAt];}else if(this.fakeFn){return this.fakeFn.apply(context,args);}else if(typeof this.resolveArgAt==="number"){ensureArgs("resolvesArg",this,args);return (this.promiseLibrary||Promise).resolve(args[this.resolveArgAt]);}else if(this.resolveThis){return (this.promiseLibrary||Promise).resolve(context);}else if(this.resolve){return (this.promiseLibrary||Promise).resolve(this.returnValue);}else if(this.reject){return (this.promiseLibrary||Promise).reject(this.returnValue);}else if(this.callsThrough){var wrappedMethod=this.effectiveWrappedMethod();return wrappedMethod.apply(context,args);}else if(this.callsThroughWithNew){// Get the original method (assumed to be a constructor in this case) - var WrappedClass=this.effectiveWrappedMethod();// Turn the arguments object into a normal array - var argsArray=slice(args);// Call the constructor - var F=WrappedClass.bind.apply(WrappedClass,concat([null],argsArray));return new F();}else if(typeof this.returnValue!=="undefined"){return this.returnValue;}else if(typeof this.callArgAt==="number"){return returnValue;}return this.returnValue;},effectiveWrappedMethod:function effectiveWrappedMethod(){for(var stubb=this.stub;stubb;stubb=stubb.parent){if(stubb.wrappedMethod){return stubb.wrappedMethod;}}throw new Error("Unable to find wrapped method");},onCall:function onCall(index){return this.stub.onCall(index);},onFirstCall:function onFirstCall(){return this.stub.onFirstCall();},onSecondCall:function onSecondCall(){return this.stub.onSecondCall();},onThirdCall:function onThirdCall(){return this.stub.onThirdCall();},withArgs:function withArgs(/* arguments */){throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" '+'is not supported. Use "stub.withArgs(...).onCall(...)" '+"to define sequential behavior for calls with certain arguments.");}};function createBehavior(behaviorMethod){return function(){this.defaultBehavior=this.defaultBehavior||proto.create(this);this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior,arguments);return this;};}function addBehavior(stub,name,fn){proto[name]=function(){fn.apply(this,concat([this],slice(arguments)));return this.stub||this;};stub[name]=createBehavior(name);}proto.addBehavior=addBehavior;proto.createBehavior=createBehavior;var asyncBehaviors=exportAsyncBehaviors(proto);module.exports=extend.nonEnum({},proto,asyncBehaviors);},{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/next-tick":34,"@sinonjs/commons":48}],5:[function(require,module,exports){var walk=require("./util/core/walk");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var push=require("@sinonjs/commons").prototypes.array.push;function collectMethod(methods,object,prop,propOwner){if(typeof getPropertyDescriptor(propOwner,prop).value==="function"&&hasOwnProperty(object,prop)){push(methods,object[prop]);}}// This function returns an array of all the own methods on the passed object - function collectOwnMethods(object){var methods=[];walk(object,collectMethod.bind(null,methods,object));return methods;}module.exports=collectOwnMethods;},{"./util/core/get-property-descriptor":29,"./util/core/walk":39,"@sinonjs/commons":48}],6:[function(require,module,exports){var supportsColor=require("supports-color");function colorize(str,color){if(supportsColor.stdout===false){return str;}return "\x1B[".concat(color,"m").concat(str,"\x1B[0m");}exports.red=function(str){return colorize(str,31);};exports.green=function(str){return colorize(str,32);};exports.cyan=function(str){return colorize(str,96);};exports.white=function(str){return colorize(str,39);};exports.bold=function(str){return colorize(str,1);};},{"supports-color":150}],7:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var Sandbox=require("./sandbox");var forEach=arrayProto.forEach;var push=arrayProto.push;function prepareSandboxFromConfig(config){var sandbox=new Sandbox();if(config.useFakeServer){if(_typeof(config.useFakeServer)==="object"){sandbox.serverPrototype=config.useFakeServer;}sandbox.useFakeServer();}if(config.useFakeTimers){if(_typeof(config.useFakeTimers)==="object"){sandbox.useFakeTimers(config.useFakeTimers);}else {sandbox.useFakeTimers();}}return sandbox;}function exposeValue(sandbox,config,key,value){if(!value){return;}if(config.injectInto&&!(key in config.injectInto)){config.injectInto[key]=value;push(sandbox.injectedKeys,key);}else {push(sandbox.args,value);}}function createSandbox(config){if(!config){return new Sandbox();}var configuredSandbox=prepareSandboxFromConfig(config);configuredSandbox.args=configuredSandbox.args||[];configuredSandbox.injectedKeys=[];configuredSandbox.injectInto=config.injectInto;var exposed=configuredSandbox.inject({});if(config.properties){forEach(config.properties,function(prop){var value=exposed[prop]||prop==="sandbox"&&configuredSandbox;exposeValue(configuredSandbox,config,prop,value);});}else {exposeValue(configuredSandbox,config,"sandbox");}return configuredSandbox;}module.exports=createSandbox;},{"./sandbox":19,"@sinonjs/commons":48}],8:[function(require,module,exports){var stub=require("./stub");var sinonType=require("./util/core/sinon-type");var forEach=require("@sinonjs/commons").prototypes.array.forEach;function isStub(value){return sinonType.get(value)==="stub";}module.exports=function createStubInstance(constructor,overrides){if(typeof constructor!=="function"){throw new TypeError("The constructor should be a function.");}var stubInstance=Object.create(constructor.prototype);sinonType.set(stubInstance,"stub-instance");var stubbedObject=stub(stubInstance);forEach(Object.keys(overrides||{}),function(propertyName){if(propertyName in stubbedObject){var value=overrides[propertyName];if(isStub(value)){stubbedObject[propertyName]=value;}else {stubbedObject[propertyName].returns(value);}}else {throw new Error("Cannot stub ".concat(propertyName,". Property does not exist!"));}});return stubbedObject;};},{"./stub":22,"./util/core/sinon-type":35,"@sinonjs/commons":48}],9:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var isPropertyConfigurable=require("./util/core/is-property-configurable");var exportAsyncBehaviors=require("./util/core/export-async-behaviors");var extend=require("./util/core/extend");var slice=arrayProto.slice;var useLeftMostCallback=-1;var useRightMostCallback=-2;function throwsException(fake,error,message){if(typeof error==="function"){fake.exceptionCreator=error;}else if(typeof error==="string"){fake.exceptionCreator=function(){var newException=new Error(message||"Sinon-provided ".concat(error));newException.name=error;return newException;};}else if(!error){fake.exceptionCreator=function(){return new Error("Error");};}else {fake.exception=error;}}var defaultBehaviors={callsFake:function callsFake(fake,fn){fake.fakeFn=fn;fake.exception=undefined;fake.exceptionCreator=undefined;},callsArg:function callsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOn:function callsArgOn(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgWith:function callsArgWith(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOnWith:function callsArgWith(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},usingPromise:function usingPromise(fake,promiseLibrary){fake.promiseLibrary=promiseLibrary;},yields:function yields(fake){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsRight:function yieldsRight(fake){fake.callArgAt=useRightMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsOn:function yieldsOn(fake,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsTo:function yieldsTo(fake,prop){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsToOn:function yieldsToOn(fake,prop,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},"throws":throwsException,throwsException:throwsException,returns:function returns(fake,value){fake.returnValue=value;fake.resolve=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},returnsArg:function returnsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.returnArgAt=index;},throwsArg:function throwsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.throwArgAt=index;},returnsThis:function returnsThis(fake){fake.returnThis=true;},resolves:function resolves(fake,value){fake.returnValue=value;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},resolvesArg:function resolvesArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.resolveArgAt=index;fake.returnValue=undefined;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},rejects:function rejects(fake,error,message){var reason;if(typeof error==="string"){reason=new Error(message||"");reason.name=error;}else if(!error){reason=new Error("Error");}else {reason=error;}fake.returnValue=reason;fake.resolve=false;fake.resolveThis=false;fake.reject=true;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;return fake;},resolvesThis:function resolvesThis(fake){fake.returnValue=undefined;fake.resolve=false;fake.resolveThis=true;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},callThrough:function callThrough(fake){fake.callsThrough=true;},callThroughWithNew:function callThroughWithNew(fake){fake.callsThroughWithNew=true;},get:function get(fake,getterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{get:getterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},set:function set(fake,setterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,// eslint-disable-next-line accessor-pairs - {set:setterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},value:function value(fake,newVal){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{value:newVal,enumerable:true,writable:true,configurable:rootStub.shadowsPropOnPrototype||isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;}};var asyncBehaviors=exportAsyncBehaviors(defaultBehaviors);module.exports=extend({},defaultBehaviors,asyncBehaviors);},{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/is-property-configurable":32,"@sinonjs/commons":48}],10:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var createProxy=require("./proxy");var nextTick=require("./util/core/next-tick");var slice=arrayProto.slice;var promiseLib=Promise;module.exports=fake;/** - * Returns a `fake` that records all calls, arguments and return values. - * - * When an `f` argument is supplied, this implementation will be used. - * - * @example - * // create an empty fake - * var f1 = sinon.fake(); - * - * f1(); - * - * f1.calledOnce() - * // true - * - * @example - * function greet(greeting) { - * console.log(`Hello ${greeting}`); - * } - * - * // create a fake with implementation - * var f2 = sinon.fake(greet); - * - * // Hello world - * f2("world"); - * - * f2.calledWith("world"); - * // true - * - * @param {Function|undefined} f - * @returns {Function} - * @namespace - */function fake(f){if(arguments.length>0&&typeof f!=="function"){throw new TypeError("Expected f argument to be a Function");}return wrapFunc(f);}/** - * Creates a `fake` that returns the provided `value`, as well as recording all - * calls, arguments and return values. - * - * @example - * var f1 = sinon.fake.returns(42); - * - * f1(); - * // 42 - * - * @memberof fake - * @param {*} value - * @returns {Function} - */fake.returns=function returns(value){// eslint-disable-next-line jsdoc/require-jsdoc - function f(){return value;}return wrapFunc(f);};/** - * Creates a `fake` that throws an Error. - * If the `value` argument does not have Error in its prototype chain, it will - * be used for creating a new error. - * - * @example - * var f1 = sinon.fake.throws("hello"); - * - * f1(); - * // Uncaught Error: hello - * - * @example - * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); - * - * f2(); - * // Uncaught TypeError: Invalid argument - * - * @memberof fake - * @param {*|Error} value - * @returns {Function} - */fake["throws"]=function _throws(value){// eslint-disable-next-line jsdoc/require-jsdoc - function f(){throw getError(value);}return wrapFunc(f);};/** - * Creates a `fake` that returns a promise that resolves to the passed `value` - * argument. - * - * @example - * var f1 = sinon.fake.resolves("apple pie"); - * - * await f1(); - * // "apple pie" - * - * @memberof fake - * @param {*} value - * @returns {Function} - */fake.resolves=function resolves(value){// eslint-disable-next-line jsdoc/require-jsdoc - function f(){return promiseLib.resolve(value);}return wrapFunc(f);};/** - * Creates a `fake` that returns a promise that rejects to the passed `value` - * argument. When `value` does not have Error in its prototype chain, it will be - * wrapped in an Error. - * - * @example - * var f1 = sinon.fake.rejects(":("); - * - * try { - * await ft(); - * } catch (error) { - * console.log(error); - * // ":(" - * } - * - * @memberof fake - * @param {*} value - * @returns {Function} - */fake.rejects=function rejects(value){// eslint-disable-next-line jsdoc/require-jsdoc - function f(){return promiseLib.reject(getError(value));}return wrapFunc(f);};/** - * Causes `fake` to use a custom Promise implementation, instead of the native - * Promise implementation. - * - * @example - * const bluebird = require("bluebird"); - * sinon.fake.usingPromise(bluebird); - * - * @memberof fake - * @param {*} promiseLibrary - * @returns {Function} - */fake.usingPromise=function usingPromise(promiseLibrary){promiseLib=promiseLibrary;return fake;};/** - * Returns a `fake` that calls the callback with the defined arguments. - * - * @example - * function callback() { - * console.log(arguments.join("*")); - * } - * - * const f1 = sinon.fake.yields("apple", "pie"); - * - * f1(callback); - * // "apple*pie" - * - * @memberof fake - * @returns {Function} - */fake.yields=function yields(){var values=slice(arguments);// eslint-disable-next-line jsdoc/require-jsdoc - function f(){var callback=arguments[arguments.length-1];if(typeof callback!=="function"){throw new TypeError("Expected last argument to be a function");}callback.apply(null,values);}return wrapFunc(f);};/** - * Returns a `fake` that calls the callback **asynchronously** with the - * defined arguments. - * - * @example - * function callback() { - * console.log(arguments.join("*")); - * } - * - * const f1 = sinon.fake.yields("apple", "pie"); - * - * f1(callback); - * + var check = function (it) { + return it && it.Math === Math && it; + }; + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global$O = + // eslint-disable-next-line es/no-global-this -- safe + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + // eslint-disable-next-line no-restricted-globals -- safe + check(typeof self == 'object' && self) || + check(typeof commonjsGlobal == 'object' && commonjsGlobal) || + // eslint-disable-next-line no-new-func -- fallback + (function () { return this; })() || commonjsGlobal || Function('return this')(); + + var objectGetOwnPropertyDescriptor = {}; + + var fails$_ = function (exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + + var fails$Z = fails$_; + + // Detect IE8's incomplete defineProperty implementation + var descriptors = !fails$Z(function () { + // eslint-disable-next-line es/no-object-defineproperty -- required for testing + return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7; + }); + + var fails$Y = fails$_; + + var functionBindNative = !fails$Y(function () { + // eslint-disable-next-line es/no-function-prototype-bind -- safe + var test = (function () { /* empty */ }).bind(); + // eslint-disable-next-line no-prototype-builtins -- safe + return typeof test != 'function' || test.hasOwnProperty('prototype'); + }); + + var NATIVE_BIND$4 = functionBindNative; + + var call$x = Function.prototype.call; + + var functionCall = NATIVE_BIND$4 ? call$x.bind(call$x) : function () { + return call$x.apply(call$x, arguments); + }; + + var objectPropertyIsEnumerable = {}; + + var $propertyIsEnumerable$2 = {}.propertyIsEnumerable; + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var getOwnPropertyDescriptor$7 = Object.getOwnPropertyDescriptor; + + // Nashorn ~ JDK8 bug + var NASHORN_BUG = getOwnPropertyDescriptor$7 && !$propertyIsEnumerable$2.call({ 1: 2 }, 1); + + // `Object.prototype.propertyIsEnumerable` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable + objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor$7(this, V); + return !!descriptor && descriptor.enumerable; + } : $propertyIsEnumerable$2; + + var createPropertyDescriptor$7 = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + + var NATIVE_BIND$3 = functionBindNative; + + var FunctionPrototype$4 = Function.prototype; + var call$w = FunctionPrototype$4.call; + var uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$4.bind.bind(call$w, call$w); + + var functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function (fn) { + return function () { + return call$w.apply(fn, arguments); + }; + }; + + var uncurryThis$_ = functionUncurryThis; + + var toString$p = uncurryThis$_({}.toString); + var stringSlice$e = uncurryThis$_(''.slice); + + var classofRaw$2 = function (it) { + return stringSlice$e(toString$p(it), 8, -1); + }; + + var uncurryThis$Z = functionUncurryThis; + var fails$X = fails$_; + var classof$j = classofRaw$2; + + var $Object$5 = Object; + var split$3 = uncurryThis$Z(''.split); + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var indexedObject = fails$X(function () { + // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 + // eslint-disable-next-line no-prototype-builtins -- safe + return !$Object$5('z').propertyIsEnumerable(0); + }) ? function (it) { + return classof$j(it) === 'String' ? split$3(it, '') : $Object$5(it); + } : $Object$5; + + // we can't use just `it == null` since of `document.all` special case + // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec + var isNullOrUndefined$c = function (it) { + return it === null || it === undefined; + }; + + var isNullOrUndefined$b = isNullOrUndefined$c; + + var $TypeError$l = TypeError; + + // `RequireObjectCoercible` abstract operation + // https://tc39.es/ecma262/#sec-requireobjectcoercible + var requireObjectCoercible$f = function (it) { + if (isNullOrUndefined$b(it)) throw new $TypeError$l("Can't call method on " + it); + return it; + }; + + // toObject with fallback for non-array-like ES3 strings + var IndexedObject$4 = indexedObject; + var requireObjectCoercible$e = requireObjectCoercible$f; + + var toIndexedObject$e = function (it) { + return IndexedObject$4(requireObjectCoercible$e(it)); + }; + + var documentAll$2 = typeof document == 'object' && document.all; + + // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot + // eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing + var IS_HTMLDDA = typeof documentAll$2 == 'undefined' && documentAll$2 !== undefined; + + var documentAll_1 = { + all: documentAll$2, + IS_HTMLDDA: IS_HTMLDDA + }; + + var $documentAll$1 = documentAll_1; + + var documentAll$1 = $documentAll$1.all; + + // `IsCallable` abstract operation + // https://tc39.es/ecma262/#sec-iscallable + var isCallable$w = $documentAll$1.IS_HTMLDDA ? function (argument) { + return typeof argument == 'function' || argument === documentAll$1; + } : function (argument) { + return typeof argument == 'function'; + }; + + var isCallable$v = isCallable$w; + var $documentAll = documentAll_1; + + var documentAll = $documentAll.all; + + var isObject$t = $documentAll.IS_HTMLDDA ? function (it) { + return typeof it == 'object' ? it !== null : isCallable$v(it) || it === documentAll; + } : function (it) { + return typeof it == 'object' ? it !== null : isCallable$v(it); + }; + + var global$N = global$O; + var isCallable$u = isCallable$w; + + var aFunction = function (argument) { + return isCallable$u(argument) ? argument : undefined; + }; + + var getBuiltIn$c = function (namespace, method) { + return arguments.length < 2 ? aFunction(global$N[namespace]) : global$N[namespace] && global$N[namespace][method]; + }; + + var uncurryThis$Y = functionUncurryThis; + + var objectIsPrototypeOf = uncurryThis$Y({}.isPrototypeOf); + + var engineUserAgent = typeof navigator != 'undefined' && String(navigator.userAgent) || ''; + + var global$M = global$O; + var userAgent$5 = engineUserAgent; + + var process$4 = global$M.process; + var Deno$1 = global$M.Deno; + var versions = process$4 && process$4.versions || Deno$1 && Deno$1.version; + var v8 = versions && versions.v8; + var match, version; + + if (v8) { + match = v8.split('.'); + // in old Chrome, versions of V8 isn't V8 = Chrome / 10 + // but their correct versions are not interesting for us + version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); + } + + // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0` + // so check `userAgent` even if `.v8` exists, but 0 + if (!version && userAgent$5) { + match = userAgent$5.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = userAgent$5.match(/Chrome\/(\d+)/); + if (match) version = +match[1]; + } + } + + var engineV8Version = version; + + /* eslint-disable es/no-symbol -- required for testing */ + var V8_VERSION$3 = engineV8Version; + var fails$W = fails$_; + var global$L = global$O; + + var $String$6 = global$L.String; + + // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing + var symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$W(function () { + var symbol = Symbol('symbol detection'); + // Chrome 38 Symbol has incorrect toString conversion + // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances + // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will, + // of course, fail. + return !$String$6(symbol) || !(Object(symbol) instanceof Symbol) || + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + !Symbol.sham && V8_VERSION$3 && V8_VERSION$3 < 41; + }); + + /* eslint-disable es/no-symbol -- required for testing */ + var NATIVE_SYMBOL$6 = symbolConstructorDetection; + + var useSymbolAsUid = NATIVE_SYMBOL$6 + && !Symbol.sham + && typeof Symbol.iterator == 'symbol'; + + var getBuiltIn$b = getBuiltIn$c; + var isCallable$t = isCallable$w; + var isPrototypeOf$9 = objectIsPrototypeOf; + var USE_SYMBOL_AS_UID$1 = useSymbolAsUid; + + var $Object$4 = Object; + + var isSymbol$6 = USE_SYMBOL_AS_UID$1 ? function (it) { + return typeof it == 'symbol'; + } : function (it) { + var $Symbol = getBuiltIn$b('Symbol'); + return isCallable$t($Symbol) && isPrototypeOf$9($Symbol.prototype, $Object$4(it)); + }; + + var $String$5 = String; + + var tryToString$7 = function (argument) { + try { + return $String$5(argument); + } catch (error) { + return 'Object'; + } + }; + + var isCallable$s = isCallable$w; + var tryToString$6 = tryToString$7; + + var $TypeError$k = TypeError; + + // `Assert: IsCallable(argument) is true` + var aCallable$c = function (argument) { + if (isCallable$s(argument)) return argument; + throw new $TypeError$k(tryToString$6(argument) + ' is not a function'); + }; + + var aCallable$b = aCallable$c; + var isNullOrUndefined$a = isNullOrUndefined$c; + + // `GetMethod` abstract operation + // https://tc39.es/ecma262/#sec-getmethod + var getMethod$8 = function (V, P) { + var func = V[P]; + return isNullOrUndefined$a(func) ? undefined : aCallable$b(func); + }; + + var call$v = functionCall; + var isCallable$r = isCallable$w; + var isObject$s = isObject$t; + + var $TypeError$j = TypeError; + + // `OrdinaryToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-ordinarytoprimitive + var ordinaryToPrimitive$2 = function (input, pref) { + var fn, val; + if (pref === 'string' && isCallable$r(fn = input.toString) && !isObject$s(val = call$v(fn, input))) return val; + if (isCallable$r(fn = input.valueOf) && !isObject$s(val = call$v(fn, input))) return val; + if (pref !== 'string' && isCallable$r(fn = input.toString) && !isObject$s(val = call$v(fn, input))) return val; + throw new $TypeError$j("Can't convert object to primitive value"); + }; + + var shared$7 = {exports: {}}; + + var isPure = false; + + var global$K = global$O; + + // eslint-disable-next-line es/no-object-defineproperty -- safe + var defineProperty$b = Object.defineProperty; + + var defineGlobalProperty$3 = function (key, value) { + try { + defineProperty$b(global$K, key, { value: value, configurable: true, writable: true }); + } catch (error) { + global$K[key] = value; + } return value; + }; + + var global$J = global$O; + var defineGlobalProperty$2 = defineGlobalProperty$3; + + var SHARED = '__core-js_shared__'; + var store$3 = global$J[SHARED] || defineGlobalProperty$2(SHARED, {}); + + var sharedStore = store$3; + + var store$2 = sharedStore; + + (shared$7.exports = function (key, value) { + return store$2[key] || (store$2[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: '3.33.0', + mode: 'global', + copyright: '© 2014-2023 Denis Pushkarev (zloirock.ru)', + license: 'https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE', + source: 'https://github.com/zloirock/core-js' + }); + + var sharedExports = shared$7.exports; + + var requireObjectCoercible$d = requireObjectCoercible$f; + + var $Object$3 = Object; + + // `ToObject` abstract operation + // https://tc39.es/ecma262/#sec-toobject + var toObject$h = function (argument) { + return $Object$3(requireObjectCoercible$d(argument)); + }; + + var uncurryThis$X = functionUncurryThis; + var toObject$g = toObject$h; + + var hasOwnProperty = uncurryThis$X({}.hasOwnProperty); + + // `HasOwnProperty` abstract operation + // https://tc39.es/ecma262/#sec-hasownproperty + // eslint-disable-next-line es/no-object-hasown -- safe + var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) { + return hasOwnProperty(toObject$g(it), key); + }; + + var uncurryThis$W = functionUncurryThis; + + var id$2 = 0; + var postfix = Math.random(); + var toString$o = uncurryThis$W(1.0.toString); + + var uid$5 = function (key) { + return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$o(++id$2 + postfix, 36); + }; + + var global$I = global$O; + var shared$6 = sharedExports; + var hasOwn$q = hasOwnProperty_1; + var uid$4 = uid$5; + var NATIVE_SYMBOL$5 = symbolConstructorDetection; + var USE_SYMBOL_AS_UID = useSymbolAsUid; + + var Symbol$3 = global$I.Symbol; + var WellKnownSymbolsStore$1 = shared$6('wks'); + var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$3['for'] || Symbol$3 : Symbol$3 && Symbol$3.withoutSetter || uid$4; + + var wellKnownSymbol$x = function (name) { + if (!hasOwn$q(WellKnownSymbolsStore$1, name)) { + WellKnownSymbolsStore$1[name] = NATIVE_SYMBOL$5 && hasOwn$q(Symbol$3, name) + ? Symbol$3[name] + : createWellKnownSymbol('Symbol.' + name); + } return WellKnownSymbolsStore$1[name]; + }; + + var call$u = functionCall; + var isObject$r = isObject$t; + var isSymbol$5 = isSymbol$6; + var getMethod$7 = getMethod$8; + var ordinaryToPrimitive$1 = ordinaryToPrimitive$2; + var wellKnownSymbol$w = wellKnownSymbol$x; + + var $TypeError$i = TypeError; + var TO_PRIMITIVE$1 = wellKnownSymbol$w('toPrimitive'); + + // `ToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-toprimitive + var toPrimitive$4 = function (input, pref) { + if (!isObject$r(input) || isSymbol$5(input)) return input; + var exoticToPrim = getMethod$7(input, TO_PRIMITIVE$1); + var result; + if (exoticToPrim) { + if (pref === undefined) pref = 'default'; + result = call$u(exoticToPrim, input, pref); + if (!isObject$r(result) || isSymbol$5(result)) return result; + throw new $TypeError$i("Can't convert object to primitive value"); + } + if (pref === undefined) pref = 'number'; + return ordinaryToPrimitive$1(input, pref); + }; + + var toPrimitive$3 = toPrimitive$4; + var isSymbol$4 = isSymbol$6; + + // `ToPropertyKey` abstract operation + // https://tc39.es/ecma262/#sec-topropertykey + var toPropertyKey$5 = function (argument) { + var key = toPrimitive$3(argument, 'string'); + return isSymbol$4(key) ? key : key + ''; + }; + + var global$H = global$O; + var isObject$q = isObject$t; + + var document$3 = global$H.document; + // typeof document.createElement is 'object' in old IE + var EXISTS$1 = isObject$q(document$3) && isObject$q(document$3.createElement); + + var documentCreateElement$2 = function (it) { + return EXISTS$1 ? document$3.createElement(it) : {}; + }; + + var DESCRIPTORS$u = descriptors; + var fails$V = fails$_; + var createElement$1 = documentCreateElement$2; + + // Thanks to IE8 for its funny defineProperty + var ie8DomDefine = !DESCRIPTORS$u && !fails$V(function () { + // eslint-disable-next-line es/no-object-defineproperty -- required for testing + return Object.defineProperty(createElement$1('div'), 'a', { + get: function () { return 7; } + }).a !== 7; + }); + + var DESCRIPTORS$t = descriptors; + var call$t = functionCall; + var propertyIsEnumerableModule$2 = objectPropertyIsEnumerable; + var createPropertyDescriptor$6 = createPropertyDescriptor$7; + var toIndexedObject$d = toIndexedObject$e; + var toPropertyKey$4 = toPropertyKey$5; + var hasOwn$p = hasOwnProperty_1; + var IE8_DOM_DEFINE$1 = ie8DomDefine; + + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var $getOwnPropertyDescriptor$2 = Object.getOwnPropertyDescriptor; + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + objectGetOwnPropertyDescriptor.f = DESCRIPTORS$t ? $getOwnPropertyDescriptor$2 : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject$d(O); + P = toPropertyKey$4(P); + if (IE8_DOM_DEFINE$1) try { + return $getOwnPropertyDescriptor$2(O, P); + } catch (error) { /* empty */ } + if (hasOwn$p(O, P)) return createPropertyDescriptor$6(!call$t(propertyIsEnumerableModule$2.f, O, P), O[P]); + }; + + var objectDefineProperty = {}; + + var DESCRIPTORS$s = descriptors; + var fails$U = fails$_; + + // V8 ~ Chrome 36- + // https://bugs.chromium.org/p/v8/issues/detail?id=3334 + var v8PrototypeDefineBug = DESCRIPTORS$s && fails$U(function () { + // eslint-disable-next-line es/no-object-defineproperty -- required for testing + return Object.defineProperty(function () { /* empty */ }, 'prototype', { + value: 42, + writable: false + }).prototype !== 42; + }); + + var isObject$p = isObject$t; + + var $String$4 = String; + var $TypeError$h = TypeError; + + // `Assert: Type(argument) is Object` + var anObject$p = function (argument) { + if (isObject$p(argument)) return argument; + throw new $TypeError$h($String$4(argument) + ' is not an object'); + }; + + var DESCRIPTORS$r = descriptors; + var IE8_DOM_DEFINE = ie8DomDefine; + var V8_PROTOTYPE_DEFINE_BUG$1 = v8PrototypeDefineBug; + var anObject$o = anObject$p; + var toPropertyKey$3 = toPropertyKey$5; + + var $TypeError$g = TypeError; + // eslint-disable-next-line es/no-object-defineproperty -- safe + var $defineProperty$1 = Object.defineProperty; + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor; + var ENUMERABLE = 'enumerable'; + var CONFIGURABLE$1 = 'configurable'; + var WRITABLE = 'writable'; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + objectDefineProperty.f = DESCRIPTORS$r ? V8_PROTOTYPE_DEFINE_BUG$1 ? function defineProperty(O, P, Attributes) { + anObject$o(O); + P = toPropertyKey$3(P); + anObject$o(Attributes); + if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) { + var current = $getOwnPropertyDescriptor$1(O, P); + if (current && current[WRITABLE]) { + O[P] = Attributes.value; + Attributes = { + configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1], + enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE], + writable: false + }; + } + } return $defineProperty$1(O, P, Attributes); + } : $defineProperty$1 : function defineProperty(O, P, Attributes) { + anObject$o(O); + P = toPropertyKey$3(P); + anObject$o(Attributes); + if (IE8_DOM_DEFINE) try { + return $defineProperty$1(O, P, Attributes); + } catch (error) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw new $TypeError$g('Accessors not supported'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + + var DESCRIPTORS$q = descriptors; + var definePropertyModule$7 = objectDefineProperty; + var createPropertyDescriptor$5 = createPropertyDescriptor$7; + + var createNonEnumerableProperty$a = DESCRIPTORS$q ? function (object, key, value) { + return definePropertyModule$7.f(object, key, createPropertyDescriptor$5(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + + var makeBuiltIn$4 = {exports: {}}; + + var DESCRIPTORS$p = descriptors; + var hasOwn$o = hasOwnProperty_1; + + var FunctionPrototype$3 = Function.prototype; + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var getDescriptor = DESCRIPTORS$p && Object.getOwnPropertyDescriptor; + + var EXISTS = hasOwn$o(FunctionPrototype$3, 'name'); + // additional protection from minified / mangled / dropped function names + var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something'; + var CONFIGURABLE = EXISTS && (!DESCRIPTORS$p || (DESCRIPTORS$p && getDescriptor(FunctionPrototype$3, 'name').configurable)); + + var functionName = { + EXISTS: EXISTS, + PROPER: PROPER, + CONFIGURABLE: CONFIGURABLE + }; + + var uncurryThis$V = functionUncurryThis; + var isCallable$q = isCallable$w; + var store$1 = sharedStore; + + var functionToString$1 = uncurryThis$V(Function.toString); + + // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper + if (!isCallable$q(store$1.inspectSource)) { + store$1.inspectSource = function (it) { + return functionToString$1(it); + }; + } + + var inspectSource$3 = store$1.inspectSource; + + var global$G = global$O; + var isCallable$p = isCallable$w; + + var WeakMap$2 = global$G.WeakMap; + + var weakMapBasicDetection = isCallable$p(WeakMap$2) && /native code/.test(String(WeakMap$2)); + + var shared$5 = sharedExports; + var uid$3 = uid$5; + + var keys$2 = shared$5('keys'); + + var sharedKey$4 = function (key) { + return keys$2[key] || (keys$2[key] = uid$3(key)); + }; + + var hiddenKeys$6 = {}; + + var NATIVE_WEAK_MAP$1 = weakMapBasicDetection; + var global$F = global$O; + var isObject$o = isObject$t; + var createNonEnumerableProperty$9 = createNonEnumerableProperty$a; + var hasOwn$n = hasOwnProperty_1; + var shared$4 = sharedStore; + var sharedKey$3 = sharedKey$4; + var hiddenKeys$5 = hiddenKeys$6; + + var OBJECT_ALREADY_INITIALIZED = 'Object already initialized'; + var TypeError$7 = global$F.TypeError; + var WeakMap$1 = global$F.WeakMap; + var set$2, get$2, has; + + var enforce = function (it) { + return has(it) ? get$2(it) : set$2(it, {}); + }; + + var getterFor = function (TYPE) { + return function (it) { + var state; + if (!isObject$o(it) || (state = get$2(it)).type !== TYPE) { + throw new TypeError$7('Incompatible receiver, ' + TYPE + ' required'); + } return state; + }; + }; + + if (NATIVE_WEAK_MAP$1 || shared$4.state) { + var store = shared$4.state || (shared$4.state = new WeakMap$1()); + /* eslint-disable no-self-assign -- prototype methods protection */ + store.get = store.get; + store.has = store.has; + store.set = store.set; + /* eslint-enable no-self-assign -- prototype methods protection */ + set$2 = function (it, metadata) { + if (store.has(it)) throw new TypeError$7(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + store.set(it, metadata); + return metadata; + }; + get$2 = function (it) { + return store.get(it) || {}; + }; + has = function (it) { + return store.has(it); + }; + } else { + var STATE = sharedKey$3('state'); + hiddenKeys$5[STATE] = true; + set$2 = function (it, metadata) { + if (hasOwn$n(it, STATE)) throw new TypeError$7(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + createNonEnumerableProperty$9(it, STATE, metadata); + return metadata; + }; + get$2 = function (it) { + return hasOwn$n(it, STATE) ? it[STATE] : {}; + }; + has = function (it) { + return hasOwn$n(it, STATE); + }; + } + + var internalState = { + set: set$2, + get: get$2, + has: has, + enforce: enforce, + getterFor: getterFor + }; + + var uncurryThis$U = functionUncurryThis; + var fails$T = fails$_; + var isCallable$o = isCallable$w; + var hasOwn$m = hasOwnProperty_1; + var DESCRIPTORS$o = descriptors; + var CONFIGURABLE_FUNCTION_NAME$2 = functionName.CONFIGURABLE; + var inspectSource$2 = inspectSource$3; + var InternalStateModule$b = internalState; + + var enforceInternalState$4 = InternalStateModule$b.enforce; + var getInternalState$6 = InternalStateModule$b.get; + var $String$3 = String; + // eslint-disable-next-line es/no-object-defineproperty -- safe + var defineProperty$a = Object.defineProperty; + var stringSlice$d = uncurryThis$U(''.slice); + var replace$a = uncurryThis$U(''.replace); + var join$5 = uncurryThis$U([].join); + + var CONFIGURABLE_LENGTH = DESCRIPTORS$o && !fails$T(function () { + return defineProperty$a(function () { /* empty */ }, 'length', { value: 8 }).length !== 8; + }); + + var TEMPLATE = String(String).split('String'); + + var makeBuiltIn$3 = makeBuiltIn$4.exports = function (value, name, options) { + if (stringSlice$d($String$3(name), 0, 7) === 'Symbol(') { + name = '[' + replace$a($String$3(name), /^Symbol\(([^)]*)\)/, '$1') + ']'; + } + if (options && options.getter) name = 'get ' + name; + if (options && options.setter) name = 'set ' + name; + if (!hasOwn$m(value, 'name') || (CONFIGURABLE_FUNCTION_NAME$2 && value.name !== name)) { + if (DESCRIPTORS$o) defineProperty$a(value, 'name', { value: name, configurable: true }); + else value.name = name; + } + if (CONFIGURABLE_LENGTH && options && hasOwn$m(options, 'arity') && value.length !== options.arity) { + defineProperty$a(value, 'length', { value: options.arity }); + } + try { + if (options && hasOwn$m(options, 'constructor') && options.constructor) { + if (DESCRIPTORS$o) defineProperty$a(value, 'prototype', { writable: false }); + // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable + } else if (value.prototype) value.prototype = undefined; + } catch (error) { /* empty */ } + var state = enforceInternalState$4(value); + if (!hasOwn$m(state, 'source')) { + state.source = join$5(TEMPLATE, typeof name == 'string' ? name : ''); + } return value; + }; + + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + // eslint-disable-next-line no-extend-native -- required + Function.prototype.toString = makeBuiltIn$3(function toString() { + return isCallable$o(this) && getInternalState$6(this).source || inspectSource$2(this); + }, 'toString'); + + var makeBuiltInExports = makeBuiltIn$4.exports; + + var isCallable$n = isCallable$w; + var definePropertyModule$6 = objectDefineProperty; + var makeBuiltIn$2 = makeBuiltInExports; + var defineGlobalProperty$1 = defineGlobalProperty$3; + + var defineBuiltIn$i = function (O, key, value, options) { + if (!options) options = {}; + var simple = options.enumerable; + var name = options.name !== undefined ? options.name : key; + if (isCallable$n(value)) makeBuiltIn$2(value, name, options); + if (options.global) { + if (simple) O[key] = value; + else defineGlobalProperty$1(key, value); + } else { + try { + if (!options.unsafe) delete O[key]; + else if (O[key]) simple = true; + } catch (error) { /* empty */ } + if (simple) O[key] = value; + else definePropertyModule$6.f(O, key, { + value: value, + enumerable: false, + configurable: !options.nonConfigurable, + writable: !options.nonWritable + }); + } return O; + }; + + var objectGetOwnPropertyNames = {}; + + var ceil$1 = Math.ceil; + var floor$7 = Math.floor; + + // `Math.trunc` method + // https://tc39.es/ecma262/#sec-math.trunc + // eslint-disable-next-line es/no-math-trunc -- safe + var mathTrunc = Math.trunc || function trunc(x) { + var n = +x; + return (n > 0 ? floor$7 : ceil$1)(n); + }; + + var trunc = mathTrunc; + + // `ToIntegerOrInfinity` abstract operation + // https://tc39.es/ecma262/#sec-tointegerorinfinity + var toIntegerOrInfinity$a = function (argument) { + var number = +argument; + // eslint-disable-next-line no-self-compare -- NaN check + return number !== number || number === 0 ? 0 : trunc(number); + }; + + var toIntegerOrInfinity$9 = toIntegerOrInfinity$a; + + var max$5 = Math.max; + var min$8 = Math.min; + + // Helper for a popular repeating case of the spec: + // Let integer be ? ToInteger(index). + // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). + var toAbsoluteIndex$8 = function (index, length) { + var integer = toIntegerOrInfinity$9(index); + return integer < 0 ? max$5(integer + length, 0) : min$8(integer, length); + }; + + var toIntegerOrInfinity$8 = toIntegerOrInfinity$a; + + var min$7 = Math.min; + + // `ToLength` abstract operation + // https://tc39.es/ecma262/#sec-tolength + var toLength$c = function (argument) { + return argument > 0 ? min$7(toIntegerOrInfinity$8(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 + }; + + var toLength$b = toLength$c; + + // `LengthOfArrayLike` abstract operation + // https://tc39.es/ecma262/#sec-lengthofarraylike + var lengthOfArrayLike$g = function (obj) { + return toLength$b(obj.length); + }; + + var toIndexedObject$c = toIndexedObject$e; + var toAbsoluteIndex$7 = toAbsoluteIndex$8; + var lengthOfArrayLike$f = lengthOfArrayLike$g; + + // `Array.prototype.{ indexOf, includes }` methods implementation + var createMethod$6 = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIndexedObject$c($this); + var length = lengthOfArrayLike$f(O); + var index = toAbsoluteIndex$7(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare -- NaN check + if (IS_INCLUDES && el !== el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare -- NaN check + if (value !== value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + + var arrayIncludes = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod$6(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod$6(false) + }; + + var uncurryThis$T = functionUncurryThis; + var hasOwn$l = hasOwnProperty_1; + var toIndexedObject$b = toIndexedObject$e; + var indexOf$2 = arrayIncludes.indexOf; + var hiddenKeys$4 = hiddenKeys$6; + + var push$b = uncurryThis$T([].push); + + var objectKeysInternal = function (object, names) { + var O = toIndexedObject$b(object); + var i = 0; + var result = []; + var key; + for (key in O) !hasOwn$l(hiddenKeys$4, key) && hasOwn$l(O, key) && push$b(result, key); + // Don't enum bug & hidden keys + while (names.length > i) if (hasOwn$l(O, key = names[i++])) { + ~indexOf$2(result, key) || push$b(result, key); + } + return result; + }; + + // IE8- don't enum bug keys + var enumBugKeys$3 = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + var internalObjectKeys$1 = objectKeysInternal; + var enumBugKeys$2 = enumBugKeys$3; + + var hiddenKeys$3 = enumBugKeys$2.concat('length', 'prototype'); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + // eslint-disable-next-line es/no-object-getownpropertynames -- safe + objectGetOwnPropertyNames.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return internalObjectKeys$1(O, hiddenKeys$3); + }; + + var objectGetOwnPropertySymbols = {}; + + // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe + objectGetOwnPropertySymbols.f = Object.getOwnPropertySymbols; + + var getBuiltIn$a = getBuiltIn$c; + var uncurryThis$S = functionUncurryThis; + var getOwnPropertyNamesModule$2 = objectGetOwnPropertyNames; + var getOwnPropertySymbolsModule$3 = objectGetOwnPropertySymbols; + var anObject$n = anObject$p; + + var concat$3 = uncurryThis$S([].concat); + + // all object keys, includes non-enumerable and symbols + var ownKeys$2 = getBuiltIn$a('Reflect', 'ownKeys') || function ownKeys(it) { + var keys = getOwnPropertyNamesModule$2.f(anObject$n(it)); + var getOwnPropertySymbols = getOwnPropertySymbolsModule$3.f; + return getOwnPropertySymbols ? concat$3(keys, getOwnPropertySymbols(it)) : keys; + }; + + var hasOwn$k = hasOwnProperty_1; + var ownKeys$1 = ownKeys$2; + var getOwnPropertyDescriptorModule$4 = objectGetOwnPropertyDescriptor; + var definePropertyModule$5 = objectDefineProperty; + + var copyConstructorProperties$3 = function (target, source, exceptions) { + var keys = ownKeys$1(source); + var defineProperty = definePropertyModule$5.f; + var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$4.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!hasOwn$k(target, key) && !(exceptions && hasOwn$k(exceptions, key))) { + defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + } + }; + + var fails$S = fails$_; + var isCallable$m = isCallable$w; + + var replacement = /#|\.prototype\./; + + var isForced$5 = function (feature, detection) { + var value = data[normalize(feature)]; + return value === POLYFILL ? true + : value === NATIVE ? false + : isCallable$m(detection) ? fails$S(detection) + : !!detection; + }; + + var normalize = isForced$5.normalize = function (string) { + return String(string).replace(replacement, '.').toLowerCase(); + }; + + var data = isForced$5.data = {}; + var NATIVE = isForced$5.NATIVE = 'N'; + var POLYFILL = isForced$5.POLYFILL = 'P'; + + var isForced_1 = isForced$5; + + var global$E = global$O; + var getOwnPropertyDescriptor$6 = objectGetOwnPropertyDescriptor.f; + var createNonEnumerableProperty$8 = createNonEnumerableProperty$a; + var defineBuiltIn$h = defineBuiltIn$i; + var defineGlobalProperty = defineGlobalProperty$3; + var copyConstructorProperties$2 = copyConstructorProperties$3; + var isForced$4 = isForced_1; + + /* + options.target - name of the target object + options.global - target is the global object + options.stat - export as static methods of target + options.proto - export as prototype methods of target + options.real - real prototype method for the `pure` version + options.forced - export even if the native feature is available + options.bind - bind methods to the target, required for the `pure` version + options.wrap - wrap constructors to preventing global pollution, required for the `pure` version + options.unsafe - use the simple assignment of property instead of delete + defineProperty + options.sham - add a flag to not completely full polyfills + options.enumerable - export as enumerable property + options.dontCallGetSet - prevent calling a getter on target + options.name - the .name of the function if it does not match the key + */ + var _export = function (options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = global$E; + } else if (STATIC) { + target = global$E[TARGET] || defineGlobalProperty(TARGET, {}); + } else { + target = (global$E[TARGET] || {}).prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.dontCallGetSet) { + descriptor = getOwnPropertyDescriptor$6(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced$4(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); + // contained in target + if (!FORCED && targetProperty !== undefined) { + if (typeof sourceProperty == typeof targetProperty) continue; + copyConstructorProperties$2(sourceProperty, targetProperty); + } + // add a flag to not completely full polyfills + if (options.sham || (targetProperty && targetProperty.sham)) { + createNonEnumerableProperty$8(sourceProperty, 'sham', true); + } + defineBuiltIn$h(target, key, sourceProperty, options); + } + }; + + var wellKnownSymbol$v = wellKnownSymbol$x; + + var TO_STRING_TAG$4 = wellKnownSymbol$v('toStringTag'); + var test$2 = {}; + + test$2[TO_STRING_TAG$4] = 'z'; + + var toStringTagSupport = String(test$2) === '[object z]'; + + var TO_STRING_TAG_SUPPORT$2 = toStringTagSupport; + var isCallable$l = isCallable$w; + var classofRaw$1 = classofRaw$2; + var wellKnownSymbol$u = wellKnownSymbol$x; + + var TO_STRING_TAG$3 = wellKnownSymbol$u('toStringTag'); + var $Object$2 = Object; + + // ES3 wrong here + var CORRECT_ARGUMENTS = classofRaw$1(function () { return arguments; }()) === 'Arguments'; + + // fallback for IE11 Script Access Denied error + var tryGet = function (it, key) { + try { + return it[key]; + } catch (error) { /* empty */ } + }; + + // getting tag from ES6+ `Object.prototype.toString` + var classof$i = TO_STRING_TAG_SUPPORT$2 ? classofRaw$1 : function (it) { + var O, tag, result; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (tag = tryGet(O = $Object$2(it), TO_STRING_TAG$3)) == 'string' ? tag + // builtinTag case + : CORRECT_ARGUMENTS ? classofRaw$1(O) + // ES3 arguments fallback + : (result = classofRaw$1(O)) === 'Object' && isCallable$l(O.callee) ? 'Arguments' : result; + }; + + var classof$h = classof$i; + + var $String$2 = String; + + var toString$n = function (argument) { + if (classof$h(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string'); + return $String$2(argument); + }; + + var anObject$m = anObject$p; + + // `RegExp.prototype.flags` getter implementation + // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags + var regexpFlags$1 = function () { + var that = anObject$m(this); + var result = ''; + if (that.hasIndices) result += 'd'; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.dotAll) result += 's'; + if (that.unicode) result += 'u'; + if (that.unicodeSets) result += 'v'; + if (that.sticky) result += 'y'; + return result; + }; + + var fails$R = fails$_; + var global$D = global$O; + + // babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError + var $RegExp$2 = global$D.RegExp; + + var UNSUPPORTED_Y$3 = fails$R(function () { + var re = $RegExp$2('a', 'y'); + re.lastIndex = 2; + return re.exec('abcd') !== null; + }); + + // UC Browser bug + // https://github.com/zloirock/core-js/issues/1008 + var MISSED_STICKY$1 = UNSUPPORTED_Y$3 || fails$R(function () { + return !$RegExp$2('a', 'y').sticky; + }); + + var BROKEN_CARET = UNSUPPORTED_Y$3 || fails$R(function () { + // https://bugzilla.mozilla.org/show_bug.cgi?id=773687 + var re = $RegExp$2('^r', 'gy'); + re.lastIndex = 2; + return re.exec('str') !== null; + }); + + var regexpStickyHelpers = { + BROKEN_CARET: BROKEN_CARET, + MISSED_STICKY: MISSED_STICKY$1, + UNSUPPORTED_Y: UNSUPPORTED_Y$3 + }; + + var objectDefineProperties = {}; + + var internalObjectKeys = objectKeysInternal; + var enumBugKeys$1 = enumBugKeys$3; + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + // eslint-disable-next-line es/no-object-keys -- safe + var objectKeys$4 = Object.keys || function keys(O) { + return internalObjectKeys(O, enumBugKeys$1); + }; + + var DESCRIPTORS$n = descriptors; + var V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug; + var definePropertyModule$4 = objectDefineProperty; + var anObject$l = anObject$p; + var toIndexedObject$a = toIndexedObject$e; + var objectKeys$3 = objectKeys$4; + + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + // eslint-disable-next-line es/no-object-defineproperties -- safe + objectDefineProperties.f = DESCRIPTORS$n && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) { + anObject$l(O); + var props = toIndexedObject$a(Properties); + var keys = objectKeys$3(Properties); + var length = keys.length; + var index = 0; + var key; + while (length > index) definePropertyModule$4.f(O, key = keys[index++], props[key]); + return O; + }; + + var getBuiltIn$9 = getBuiltIn$c; + + var html$2 = getBuiltIn$9('document', 'documentElement'); + + /* global ActiveXObject -- old IE, WSH */ + var anObject$k = anObject$p; + var definePropertiesModule$1 = objectDefineProperties; + var enumBugKeys = enumBugKeys$3; + var hiddenKeys$2 = hiddenKeys$6; + var html$1 = html$2; + var documentCreateElement$1 = documentCreateElement$2; + var sharedKey$2 = sharedKey$4; + + var GT = '>'; + var LT = '<'; + var PROTOTYPE$2 = 'prototype'; + var SCRIPT = 'script'; + var IE_PROTO$1 = sharedKey$2('IE_PROTO'); + + var EmptyConstructor = function () { /* empty */ }; + + var scriptTag = function (content) { + return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT; + }; + + // Create object with fake `null` prototype: use ActiveX Object with cleared prototype + var NullProtoObjectViaActiveX = function (activeXDocument) { + activeXDocument.write(scriptTag('')); + activeXDocument.close(); + var temp = activeXDocument.parentWindow.Object; + activeXDocument = null; // avoid memory leak + return temp; + }; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var NullProtoObjectViaIFrame = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = documentCreateElement$1('iframe'); + var JS = 'java' + SCRIPT + ':'; + var iframeDocument; + iframe.style.display = 'none'; + html$1.appendChild(iframe); + // https://github.com/zloirock/core-js/issues/475 + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag('document.F=Object')); + iframeDocument.close(); + return iframeDocument.F; + }; + + // Check for document.domain and active x support + // No need to use active x approach when document.domain is not set + // see https://github.com/es-shims/es5-shim/issues/150 + // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 + // avoid IE GC bug + var activeXDocument; + var NullProtoObject = function () { + try { + activeXDocument = new ActiveXObject('htmlfile'); + } catch (error) { /* ignore */ } + NullProtoObject = typeof document != 'undefined' + ? document.domain && activeXDocument + ? NullProtoObjectViaActiveX(activeXDocument) // old IE + : NullProtoObjectViaIFrame() + : NullProtoObjectViaActiveX(activeXDocument); // WSH + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE$2][enumBugKeys[length]]; + return NullProtoObject(); + }; + + hiddenKeys$2[IE_PROTO$1] = true; + + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + // eslint-disable-next-line es/no-object-create -- safe + var objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + EmptyConstructor[PROTOTYPE$2] = anObject$k(O); + result = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE$2] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO$1] = O; + } else result = NullProtoObject(); + return Properties === undefined ? result : definePropertiesModule$1.f(result, Properties); + }; + + var fails$Q = fails$_; + var global$C = global$O; + + // babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError + var $RegExp$1 = global$C.RegExp; + + var regexpUnsupportedDotAll = fails$Q(function () { + var re = $RegExp$1('.', 's'); + return !(re.dotAll && re.test('\n') && re.flags === 's'); + }); + + var fails$P = fails$_; + var global$B = global$O; + + // babel-minify and Closure Compiler transpiles RegExp('(?b)', 'g') -> /(?b)/g and it causes SyntaxError + var $RegExp = global$B.RegExp; + + var regexpUnsupportedNcg = fails$P(function () { + var re = $RegExp('(?b)', 'g'); + return re.exec('b').groups.a !== 'b' || + 'b'.replace(re, '$c') !== 'bc'; + }); + + /* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */ + /* eslint-disable regexp/no-useless-quantifier -- testing */ + var call$s = functionCall; + var uncurryThis$R = functionUncurryThis; + var toString$m = toString$n; + var regexpFlags = regexpFlags$1; + var stickyHelpers$2 = regexpStickyHelpers; + var shared$3 = sharedExports; + var create$7 = objectCreate; + var getInternalState$5 = internalState.get; + var UNSUPPORTED_DOT_ALL$1 = regexpUnsupportedDotAll; + var UNSUPPORTED_NCG$1 = regexpUnsupportedNcg; + + var nativeReplace = shared$3('native-string-replace', String.prototype.replace); + var nativeExec = RegExp.prototype.exec; + var patchedExec = nativeExec; + var charAt$9 = uncurryThis$R(''.charAt); + var indexOf$1 = uncurryThis$R(''.indexOf); + var replace$9 = uncurryThis$R(''.replace); + var stringSlice$c = uncurryThis$R(''.slice); + + var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/; + var re2 = /b*/g; + call$s(nativeExec, re1, 'a'); + call$s(nativeExec, re2, 'a'); + return re1.lastIndex !== 0 || re2.lastIndex !== 0; + })(); + + var UNSUPPORTED_Y$2 = stickyHelpers$2.BROKEN_CARET; + + // nonparticipating capturing group, copied from es5-shim's String#split patch. + var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + + var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$2 || UNSUPPORTED_DOT_ALL$1 || UNSUPPORTED_NCG$1; + + if (PATCH) { + patchedExec = function exec(string) { + var re = this; + var state = getInternalState$5(re); + var str = toString$m(string); + var raw = state.raw; + var result, reCopy, lastIndex, match, i, object, group; + + if (raw) { + raw.lastIndex = re.lastIndex; + result = call$s(patchedExec, raw, str); + re.lastIndex = raw.lastIndex; + return result; + } + + var groups = state.groups; + var sticky = UNSUPPORTED_Y$2 && re.sticky; + var flags = call$s(regexpFlags, re); + var source = re.source; + var charsAdded = 0; + var strCopy = str; + + if (sticky) { + flags = replace$9(flags, 'y', ''); + if (indexOf$1(flags, 'g') === -1) { + flags += 'g'; + } + + strCopy = stringSlice$c(str, re.lastIndex); + // Support anchored sticky behavior. + if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt$9(str, re.lastIndex - 1) !== '\n')) { + source = '(?: ' + source + ')'; + strCopy = ' ' + strCopy; + charsAdded++; + } + // ^(? + rx + ) is needed, in combination with some str slicing, to + // simulate the 'y' flag. + reCopy = new RegExp('^(?:' + source + ')', flags); + } + + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + source + '$(?!\\s)', flags); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex; + + match = call$s(nativeExec, sticky ? reCopy : re, strCopy); + + if (sticky) { + if (match) { + match.input = stringSlice$c(match.input, charsAdded); + match[0] = stringSlice$c(match[0], charsAdded); + match.index = re.lastIndex; + re.lastIndex += match[0].length; + } else re.lastIndex = 0; + } else if (UPDATES_LAST_INDEX_WRONG && match) { + re.lastIndex = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn't work for /(.?)?/ + call$s(nativeReplace, match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; + } + }); + } + + if (match && groups) { + match.groups = object = create$7(null); + for (i = 0; i < groups.length; i++) { + group = groups[i]; + object[group[0]] = match[group[1]]; + } + } + + return match; + }; + } + + var regexpExec$3 = patchedExec; + + var $$1f = _export; + var exec$7 = regexpExec$3; + + // `RegExp.prototype.exec` method + // https://tc39.es/ecma262/#sec-regexp.prototype.exec + $$1f({ target: 'RegExp', proto: true, forced: /./.exec !== exec$7 }, { + exec: exec$7 + }); + + var NATIVE_BIND$2 = functionBindNative; + + var FunctionPrototype$2 = Function.prototype; + var apply$9 = FunctionPrototype$2.apply; + var call$r = FunctionPrototype$2.call; + + // eslint-disable-next-line es/no-reflect -- safe + var functionApply = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND$2 ? call$r.bind(apply$9) : function () { + return call$r.apply(apply$9, arguments); + }); + + var classofRaw = classofRaw$2; + var uncurryThis$Q = functionUncurryThis; + + var functionUncurryThisClause = function (fn) { + // Nashorn bug: + // https://github.com/zloirock/core-js/issues/1128 + // https://github.com/zloirock/core-js/issues/1130 + if (classofRaw(fn) === 'Function') return uncurryThis$Q(fn); + }; + + // TODO: Remove from `core-js@4` since it's moved to entry points + + var uncurryThis$P = functionUncurryThisClause; + var defineBuiltIn$g = defineBuiltIn$i; + var regexpExec$2 = regexpExec$3; + var fails$O = fails$_; + var wellKnownSymbol$t = wellKnownSymbol$x; + var createNonEnumerableProperty$7 = createNonEnumerableProperty$a; + + var SPECIES$6 = wellKnownSymbol$t('species'); + var RegExpPrototype$4 = RegExp.prototype; + + var fixRegexpWellKnownSymbolLogic = function (KEY, exec, FORCED, SHAM) { + var SYMBOL = wellKnownSymbol$t(KEY); + + var DELEGATES_TO_SYMBOL = !fails$O(function () { + // String methods call symbol-named RegEp methods + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) !== 7; + }); + + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails$O(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + + if (KEY === 'split') { + // We can't use real regex here since it causes deoptimization + // and serious performance degradation in V8 + // https://github.com/zloirock/core-js/issues/306 + re = {}; + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES$6] = function () { return re; }; + re.flags = ''; + re[SYMBOL] = /./[SYMBOL]; + } + + re.exec = function () { + execCalled = true; + return null; + }; + + re[SYMBOL](''); + return !execCalled; + }); + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + FORCED + ) { + var uncurriedNativeRegExpMethod = uncurryThis$P(/./[SYMBOL]); + var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) { + var uncurriedNativeMethod = uncurryThis$P(nativeMethod); + var $exec = regexp.exec; + if ($exec === regexpExec$2 || $exec === RegExpPrototype$4.exec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: uncurriedNativeRegExpMethod(regexp, str, arg2) }; + } + return { done: true, value: uncurriedNativeMethod(str, regexp, arg2) }; + } + return { done: false }; + }); + + defineBuiltIn$g(String.prototype, KEY, methods[0]); + defineBuiltIn$g(RegExpPrototype$4, SYMBOL, methods[1]); + } + + if (SHAM) createNonEnumerableProperty$7(RegExpPrototype$4[SYMBOL], 'sham', true); + }; + + var uncurryThis$O = functionUncurryThis; + var toIntegerOrInfinity$7 = toIntegerOrInfinity$a; + var toString$l = toString$n; + var requireObjectCoercible$c = requireObjectCoercible$f; + + var charAt$8 = uncurryThis$O(''.charAt); + var charCodeAt$3 = uncurryThis$O(''.charCodeAt); + var stringSlice$b = uncurryThis$O(''.slice); + + var createMethod$5 = function (CONVERT_TO_STRING) { + return function ($this, pos) { + var S = toString$l(requireObjectCoercible$c($this)); + var position = toIntegerOrInfinity$7(pos); + var size = S.length; + var first, second; + if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined; + first = charCodeAt$3(S, position); + return first < 0xD800 || first > 0xDBFF || position + 1 === size + || (second = charCodeAt$3(S, position + 1)) < 0xDC00 || second > 0xDFFF + ? CONVERT_TO_STRING + ? charAt$8(S, position) + : first + : CONVERT_TO_STRING + ? stringSlice$b(S, position, position + 2) + : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000; + }; + }; + + var stringMultibyte = { + // `String.prototype.codePointAt` method + // https://tc39.es/ecma262/#sec-string.prototype.codepointat + codeAt: createMethod$5(false), + // `String.prototype.at` method + // https://github.com/mathiasbynens/String.prototype.at + charAt: createMethod$5(true) + }; + + var charAt$7 = stringMultibyte.charAt; + + // `AdvanceStringIndex` abstract operation + // https://tc39.es/ecma262/#sec-advancestringindex + var advanceStringIndex$3 = function (S, index, unicode) { + return index + (unicode ? charAt$7(S, index).length : 1); + }; + + var uncurryThis$N = functionUncurryThis; + var toObject$f = toObject$h; + + var floor$6 = Math.floor; + var charAt$6 = uncurryThis$N(''.charAt); + var replace$8 = uncurryThis$N(''.replace); + var stringSlice$a = uncurryThis$N(''.slice); + // eslint-disable-next-line redos/no-vulnerable -- safe + var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g; + var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g; + + // `GetSubstitution` abstract operation + // https://tc39.es/ecma262/#sec-getsubstitution + var getSubstitution$2 = function (matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = toObject$f(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return replace$8(replacement, symbols, function (match, ch) { + var capture; + switch (charAt$6(ch, 0)) { + case '$': return '$'; + case '&': return matched; + case '`': return stringSlice$a(str, 0, position); + case "'": return stringSlice$a(str, tailPos); + case '<': + capture = namedCaptures[stringSlice$a(ch, 1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return match; + if (n > m) { + var f = floor$6(n / 10); + if (f === 0) return match; + if (f <= m) return captures[f - 1] === undefined ? charAt$6(ch, 1) : captures[f - 1] + charAt$6(ch, 1); + return match; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + }; + + var call$q = functionCall; + var anObject$j = anObject$p; + var isCallable$k = isCallable$w; + var classof$g = classofRaw$2; + var regexpExec$1 = regexpExec$3; + + var $TypeError$f = TypeError; + + // `RegExpExec` abstract operation + // https://tc39.es/ecma262/#sec-regexpexec + var regexpExecAbstract = function (R, S) { + var exec = R.exec; + if (isCallable$k(exec)) { + var result = call$q(exec, R, S); + if (result !== null) anObject$j(result); + return result; + } + if (classof$g(R) === 'RegExp') return call$q(regexpExec$1, R, S); + throw new $TypeError$f('RegExp#exec called on incompatible receiver'); + }; + + var apply$8 = functionApply; + var call$p = functionCall; + var uncurryThis$M = functionUncurryThis; + var fixRegExpWellKnownSymbolLogic$3 = fixRegexpWellKnownSymbolLogic; + var fails$N = fails$_; + var anObject$i = anObject$p; + var isCallable$j = isCallable$w; + var isNullOrUndefined$9 = isNullOrUndefined$c; + var toIntegerOrInfinity$6 = toIntegerOrInfinity$a; + var toLength$a = toLength$c; + var toString$k = toString$n; + var requireObjectCoercible$b = requireObjectCoercible$f; + var advanceStringIndex$2 = advanceStringIndex$3; + var getMethod$6 = getMethod$8; + var getSubstitution$1 = getSubstitution$2; + var regExpExec$3 = regexpExecAbstract; + var wellKnownSymbol$s = wellKnownSymbol$x; + + var REPLACE$1 = wellKnownSymbol$s('replace'); + var max$4 = Math.max; + var min$6 = Math.min; + var concat$2 = uncurryThis$M([].concat); + var push$a = uncurryThis$M([].push); + var stringIndexOf$3 = uncurryThis$M(''.indexOf); + var stringSlice$9 = uncurryThis$M(''.slice); + + var maybeToString = function (it) { + return it === undefined ? it : String(it); + }; + + // IE <= 11 replaces $0 with the whole match, as if it was $& + // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0 + var REPLACE_KEEPS_$0 = (function () { + // eslint-disable-next-line regexp/prefer-escape-replacement-dollar-char -- required for testing + return 'a'.replace(/./, '$0') === '$0'; + })(); + + // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string + var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () { + if (/./[REPLACE$1]) { + return /./[REPLACE$1]('a', '$0') === ''; + } + return false; + })(); + + var REPLACE_SUPPORTS_NAMED_GROUPS = !fails$N(function () { + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + // eslint-disable-next-line regexp/no-useless-dollar-replacements -- false positive + return ''.replace(re, '$') !== '7'; + }); + + // @@replace logic + fixRegExpWellKnownSymbolLogic$3('replace', function (_, nativeReplace, maybeCallNative) { + var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0'; + + return [ + // `String.prototype.replace` method + // https://tc39.es/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = requireObjectCoercible$b(this); + var replacer = isNullOrUndefined$9(searchValue) ? undefined : getMethod$6(searchValue, REPLACE$1); + return replacer + ? call$p(replacer, searchValue, O, replaceValue) + : call$p(nativeReplace, toString$k(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace + function (string, replaceValue) { + var rx = anObject$i(this); + var S = toString$k(string); + + if ( + typeof replaceValue == 'string' && + stringIndexOf$3(replaceValue, UNSAFE_SUBSTITUTE) === -1 && + stringIndexOf$3(replaceValue, '$<') === -1 + ) { + var res = maybeCallNative(nativeReplace, rx, S, replaceValue); + if (res.done) return res.value; + } + + var functionalReplace = isCallable$j(replaceValue); + if (!functionalReplace) replaceValue = toString$k(replaceValue); + + var global = rx.global; + var fullUnicode; + if (global) { + fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + + var results = []; + var result; + while (true) { + result = regExpExec$3(rx, S); + if (result === null) break; + + push$a(results, result); + if (!global) break; + + var matchStr = toString$k(result[0]); + if (matchStr === '') rx.lastIndex = advanceStringIndex$2(S, toLength$a(rx.lastIndex), fullUnicode); + } + + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + + var matched = toString$k(result[0]); + var position = max$4(min$6(toIntegerOrInfinity$6(result.index), S.length), 0); + var captures = []; + var replacement; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) push$a(captures, maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = concat$2([matched], captures, position, S); + if (namedCaptures !== undefined) push$a(replacerArgs, namedCaptures); + replacement = toString$k(apply$8(replaceValue, undefined, replacerArgs)); + } else { + replacement = getSubstitution$1(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += stringSlice$9(S, nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + + return accumulatedResult + stringSlice$9(S, nextSourcePosition); + } + ]; + }, !REPLACE_SUPPORTS_NAMED_GROUPS || !REPLACE_KEEPS_$0 || REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE); + + var isObject$n = isObject$t; + var classof$f = classofRaw$2; + var wellKnownSymbol$r = wellKnownSymbol$x; + + var MATCH$2 = wellKnownSymbol$r('match'); + + // `IsRegExp` abstract operation + // https://tc39.es/ecma262/#sec-isregexp + var isRegexp = function (it) { + var isRegExp; + return isObject$n(it) && ((isRegExp = it[MATCH$2]) !== undefined ? !!isRegExp : classof$f(it) === 'RegExp'); + }; + + var call$o = functionCall; + var hasOwn$j = hasOwnProperty_1; + var isPrototypeOf$8 = objectIsPrototypeOf; + var regExpFlags$1 = regexpFlags$1; + + var RegExpPrototype$3 = RegExp.prototype; + + var regexpGetFlags = function (R) { + var flags = R.flags; + return flags === undefined && !('flags' in RegExpPrototype$3) && !hasOwn$j(R, 'flags') && isPrototypeOf$8(RegExpPrototype$3, R) + ? call$o(regExpFlags$1, R) : flags; + }; + + var $$1e = _export; + var call$n = functionCall; + var uncurryThis$L = functionUncurryThis; + var requireObjectCoercible$a = requireObjectCoercible$f; + var isCallable$i = isCallable$w; + var isNullOrUndefined$8 = isNullOrUndefined$c; + var isRegExp$3 = isRegexp; + var toString$j = toString$n; + var getMethod$5 = getMethod$8; + var getRegExpFlags$2 = regexpGetFlags; + var getSubstitution = getSubstitution$2; + var wellKnownSymbol$q = wellKnownSymbol$x; + + var REPLACE = wellKnownSymbol$q('replace'); + var $TypeError$e = TypeError; + var indexOf = uncurryThis$L(''.indexOf); + uncurryThis$L(''.replace); + var stringSlice$8 = uncurryThis$L(''.slice); + var max$3 = Math.max; + + var stringIndexOf$2 = function (string, searchValue, fromIndex) { + if (fromIndex > string.length) return -1; + if (searchValue === '') return fromIndex; + return indexOf(string, searchValue, fromIndex); + }; + + // `String.prototype.replaceAll` method + // https://tc39.es/ecma262/#sec-string.prototype.replaceall + $$1e({ target: 'String', proto: true }, { + replaceAll: function replaceAll(searchValue, replaceValue) { + var O = requireObjectCoercible$a(this); + var IS_REG_EXP, flags, replacer, string, searchString, functionalReplace, searchLength, advanceBy, replacement; + var position = 0; + var endOfLastMatch = 0; + var result = ''; + if (!isNullOrUndefined$8(searchValue)) { + IS_REG_EXP = isRegExp$3(searchValue); + if (IS_REG_EXP) { + flags = toString$j(requireObjectCoercible$a(getRegExpFlags$2(searchValue))); + if (!~indexOf(flags, 'g')) throw new $TypeError$e('`.replaceAll` does not allow non-global regexes'); + } + replacer = getMethod$5(searchValue, REPLACE); + if (replacer) { + return call$n(replacer, searchValue, O, replaceValue); + } + } + string = toString$j(O); + searchString = toString$j(searchValue); + functionalReplace = isCallable$i(replaceValue); + if (!functionalReplace) replaceValue = toString$j(replaceValue); + searchLength = searchString.length; + advanceBy = max$3(1, searchLength); + position = stringIndexOf$2(string, searchString, 0); + while (position !== -1) { + replacement = functionalReplace + ? toString$j(replaceValue(searchString, position, string)) + : getSubstitution(searchString, string, position, [], undefined, replaceValue); + result += stringSlice$8(string, endOfLastMatch, position) + replacement; + endOfLastMatch = position + searchLength; + position = stringIndexOf$2(string, searchString, position + advanceBy); + } + if (endOfLastMatch < string.length) { + result += stringSlice$8(string, endOfLastMatch); + } + return result; + } + }); + + var objectGetOwnPropertyNamesExternal = {}; + + var toPropertyKey$2 = toPropertyKey$5; + var definePropertyModule$3 = objectDefineProperty; + var createPropertyDescriptor$4 = createPropertyDescriptor$7; + + var createProperty$6 = function (object, key, value) { + var propertyKey = toPropertyKey$2(key); + if (propertyKey in object) definePropertyModule$3.f(object, propertyKey, createPropertyDescriptor$4(0, value)); + else object[propertyKey] = value; + }; + + var toAbsoluteIndex$6 = toAbsoluteIndex$8; + var lengthOfArrayLike$e = lengthOfArrayLike$g; + var createProperty$5 = createProperty$6; + + var $Array$4 = Array; + var max$2 = Math.max; + + var arraySliceSimple = function (O, start, end) { + var length = lengthOfArrayLike$e(O); + var k = toAbsoluteIndex$6(start, length); + var fin = toAbsoluteIndex$6(end === undefined ? length : end, length); + var result = $Array$4(max$2(fin - k, 0)); + var n = 0; + for (; k < fin; k++, n++) createProperty$5(result, n, O[k]); + result.length = n; + return result; + }; + + /* eslint-disable es/no-object-getownpropertynames -- safe */ + var classof$e = classofRaw$2; + var toIndexedObject$9 = toIndexedObject$e; + var $getOwnPropertyNames$1 = objectGetOwnPropertyNames.f; + var arraySlice$b = arraySliceSimple; + + var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames + ? Object.getOwnPropertyNames(window) : []; + + var getWindowNames = function (it) { + try { + return $getOwnPropertyNames$1(it); + } catch (error) { + return arraySlice$b(windowNames); + } + }; + + // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window + objectGetOwnPropertyNamesExternal.f = function getOwnPropertyNames(it) { + return windowNames && classof$e(it) === 'Window' + ? getWindowNames(it) + : $getOwnPropertyNames$1(toIndexedObject$9(it)); + }; + + var makeBuiltIn$1 = makeBuiltInExports; + var defineProperty$9 = objectDefineProperty; + + var defineBuiltInAccessor$b = function (target, name, descriptor) { + if (descriptor.get) makeBuiltIn$1(descriptor.get, name, { getter: true }); + if (descriptor.set) makeBuiltIn$1(descriptor.set, name, { setter: true }); + return defineProperty$9.f(target, name, descriptor); + }; + + var wellKnownSymbolWrapped = {}; + + var wellKnownSymbol$p = wellKnownSymbol$x; + + wellKnownSymbolWrapped.f = wellKnownSymbol$p; + + var global$A = global$O; + + var path$2 = global$A; + + var path$1 = path$2; + var hasOwn$i = hasOwnProperty_1; + var wrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped; + var defineProperty$8 = objectDefineProperty.f; + + var wellKnownSymbolDefine = function (NAME) { + var Symbol = path$1.Symbol || (path$1.Symbol = {}); + if (!hasOwn$i(Symbol, NAME)) defineProperty$8(Symbol, NAME, { + value: wrappedWellKnownSymbolModule$1.f(NAME) + }); + }; + + var call$m = functionCall; + var getBuiltIn$8 = getBuiltIn$c; + var wellKnownSymbol$o = wellKnownSymbol$x; + var defineBuiltIn$f = defineBuiltIn$i; + + var symbolDefineToPrimitive = function () { + var Symbol = getBuiltIn$8('Symbol'); + var SymbolPrototype = Symbol && Symbol.prototype; + var valueOf = SymbolPrototype && SymbolPrototype.valueOf; + var TO_PRIMITIVE = wellKnownSymbol$o('toPrimitive'); + + if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) { + // `Symbol.prototype[@@toPrimitive]` method + // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive + // eslint-disable-next-line no-unused-vars -- required for .length + defineBuiltIn$f(SymbolPrototype, TO_PRIMITIVE, function (hint) { + return call$m(valueOf, this); + }, { arity: 1 }); + } + }; + + var defineProperty$7 = objectDefineProperty.f; + var hasOwn$h = hasOwnProperty_1; + var wellKnownSymbol$n = wellKnownSymbol$x; + + var TO_STRING_TAG$2 = wellKnownSymbol$n('toStringTag'); + + var setToStringTag$b = function (target, TAG, STATIC) { + if (target && !STATIC) target = target.prototype; + if (target && !hasOwn$h(target, TO_STRING_TAG$2)) { + defineProperty$7(target, TO_STRING_TAG$2, { configurable: true, value: TAG }); + } + }; + + var uncurryThis$K = functionUncurryThisClause; + var aCallable$a = aCallable$c; + var NATIVE_BIND$1 = functionBindNative; + + var bind$c = uncurryThis$K(uncurryThis$K.bind); + + // optional / simple context binding + var functionBindContext = function (fn, that) { + aCallable$a(fn); + return that === undefined ? fn : NATIVE_BIND$1 ? bind$c(fn, that) : function (/* ...args */) { + return fn.apply(that, arguments); + }; + }; + + var classof$d = classofRaw$2; + + // `IsArray` abstract operation + // https://tc39.es/ecma262/#sec-isarray + // eslint-disable-next-line es/no-array-isarray -- safe + var isArray$8 = Array.isArray || function isArray(argument) { + return classof$d(argument) === 'Array'; + }; + + var uncurryThis$J = functionUncurryThis; + var fails$M = fails$_; + var isCallable$h = isCallable$w; + var classof$c = classof$i; + var getBuiltIn$7 = getBuiltIn$c; + var inspectSource$1 = inspectSource$3; + + var noop = function () { /* empty */ }; + var empty = []; + var construct$1 = getBuiltIn$7('Reflect', 'construct'); + var constructorRegExp = /^\s*(?:class|function)\b/; + var exec$6 = uncurryThis$J(constructorRegExp.exec); + var INCORRECT_TO_STRING = !constructorRegExp.test(noop); + + var isConstructorModern = function isConstructor(argument) { + if (!isCallable$h(argument)) return false; + try { + construct$1(noop, empty, argument); + return true; + } catch (error) { + return false; + } + }; + + var isConstructorLegacy = function isConstructor(argument) { + if (!isCallable$h(argument)) return false; + switch (classof$c(argument)) { + case 'AsyncFunction': + case 'GeneratorFunction': + case 'AsyncGeneratorFunction': return false; + } + try { + // we can't check .prototype since constructors produced by .bind haven't it + // `Function#toString` throws on some built-it function in some legacy engines + // (for example, `DOMQuad` and similar in FF41-) + return INCORRECT_TO_STRING || !!exec$6(constructorRegExp, inspectSource$1(argument)); + } catch (error) { + return true; + } + }; + + isConstructorLegacy.sham = true; + + // `IsConstructor` abstract operation + // https://tc39.es/ecma262/#sec-isconstructor + var isConstructor$4 = !construct$1 || fails$M(function () { + var called; + return isConstructorModern(isConstructorModern.call) + || !isConstructorModern(Object) + || !isConstructorModern(function () { called = true; }) + || called; + }) ? isConstructorLegacy : isConstructorModern; + + var isArray$7 = isArray$8; + var isConstructor$3 = isConstructor$4; + var isObject$m = isObject$t; + var wellKnownSymbol$m = wellKnownSymbol$x; + + var SPECIES$5 = wellKnownSymbol$m('species'); + var $Array$3 = Array; + + // a part of `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesConstructor$1 = function (originalArray) { + var C; + if (isArray$7(originalArray)) { + C = originalArray.constructor; + // cross-realm fallback + if (isConstructor$3(C) && (C === $Array$3 || isArray$7(C.prototype))) C = undefined; + else if (isObject$m(C)) { + C = C[SPECIES$5]; + if (C === null) C = undefined; + } + } return C === undefined ? $Array$3 : C; + }; + + var arraySpeciesConstructor = arraySpeciesConstructor$1; + + // `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesCreate$3 = function (originalArray, length) { + return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length); + }; + + var bind$b = functionBindContext; + var uncurryThis$I = functionUncurryThis; + var IndexedObject$3 = indexedObject; + var toObject$e = toObject$h; + var lengthOfArrayLike$d = lengthOfArrayLike$g; + var arraySpeciesCreate$2 = arraySpeciesCreate$3; + + var push$9 = uncurryThis$I([].push); + + // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation + var createMethod$4 = function (TYPE) { + var IS_MAP = TYPE === 1; + var IS_FILTER = TYPE === 2; + var IS_SOME = TYPE === 3; + var IS_EVERY = TYPE === 4; + var IS_FIND_INDEX = TYPE === 6; + var IS_FILTER_REJECT = TYPE === 7; + var NO_HOLES = TYPE === 5 || IS_FIND_INDEX; + return function ($this, callbackfn, that, specificCreate) { + var O = toObject$e($this); + var self = IndexedObject$3(O); + var boundFunction = bind$b(callbackfn, that); + var length = lengthOfArrayLike$d(self); + var index = 0; + var create = specificCreate || arraySpeciesCreate$2; + var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined; + var value, result; + for (;length > index; index++) if (NO_HOLES || index in self) { + value = self[index]; + result = boundFunction(value, index, O); + if (TYPE) { + if (IS_MAP) target[index] = result; // map + else if (result) switch (TYPE) { + case 3: return true; // some + case 5: return value; // find + case 6: return index; // findIndex + case 2: push$9(target, value); // filter + } else switch (TYPE) { + case 4: return false; // every + case 7: push$9(target, value); // filterReject + } + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target; + }; + }; + + var arrayIteration = { + // `Array.prototype.forEach` method + // https://tc39.es/ecma262/#sec-array.prototype.foreach + forEach: createMethod$4(0), + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + map: createMethod$4(1), + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + filter: createMethod$4(2), + // `Array.prototype.some` method + // https://tc39.es/ecma262/#sec-array.prototype.some + some: createMethod$4(3), + // `Array.prototype.every` method + // https://tc39.es/ecma262/#sec-array.prototype.every + every: createMethod$4(4), + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + find: createMethod$4(5), + // `Array.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-array.prototype.findIndex + findIndex: createMethod$4(6), + // `Array.prototype.filterReject` method + // https://github.com/tc39/proposal-array-filtering + filterReject: createMethod$4(7) + }; + + var $$1d = _export; + var global$z = global$O; + var call$l = functionCall; + var uncurryThis$H = functionUncurryThis; + var DESCRIPTORS$m = descriptors; + var NATIVE_SYMBOL$4 = symbolConstructorDetection; + var fails$L = fails$_; + var hasOwn$g = hasOwnProperty_1; + var isPrototypeOf$7 = objectIsPrototypeOf; + var anObject$h = anObject$p; + var toIndexedObject$8 = toIndexedObject$e; + var toPropertyKey$1 = toPropertyKey$5; + var $toString$3 = toString$n; + var createPropertyDescriptor$3 = createPropertyDescriptor$7; + var nativeObjectCreate = objectCreate; + var objectKeys$2 = objectKeys$4; + var getOwnPropertyNamesModule$1 = objectGetOwnPropertyNames; + var getOwnPropertyNamesExternal = objectGetOwnPropertyNamesExternal; + var getOwnPropertySymbolsModule$2 = objectGetOwnPropertySymbols; + var getOwnPropertyDescriptorModule$3 = objectGetOwnPropertyDescriptor; + var definePropertyModule$2 = objectDefineProperty; + var definePropertiesModule = objectDefineProperties; + var propertyIsEnumerableModule$1 = objectPropertyIsEnumerable; + var defineBuiltIn$e = defineBuiltIn$i; + var defineBuiltInAccessor$a = defineBuiltInAccessor$b; + var shared$2 = sharedExports; + var sharedKey$1 = sharedKey$4; + var hiddenKeys$1 = hiddenKeys$6; + var uid$2 = uid$5; + var wellKnownSymbol$l = wellKnownSymbol$x; + var wrappedWellKnownSymbolModule = wellKnownSymbolWrapped; + var defineWellKnownSymbol$4 = wellKnownSymbolDefine; + var defineSymbolToPrimitive$1 = symbolDefineToPrimitive; + var setToStringTag$a = setToStringTag$b; + var InternalStateModule$a = internalState; + var $forEach$2 = arrayIteration.forEach; + + var HIDDEN = sharedKey$1('hidden'); + var SYMBOL = 'Symbol'; + var PROTOTYPE$1 = 'prototype'; + + var setInternalState$9 = InternalStateModule$a.set; + var getInternalState$4 = InternalStateModule$a.getterFor(SYMBOL); + + var ObjectPrototype$4 = Object[PROTOTYPE$1]; + var $Symbol = global$z.Symbol; + var SymbolPrototype$1 = $Symbol && $Symbol[PROTOTYPE$1]; + var RangeError$4 = global$z.RangeError; + var TypeError$6 = global$z.TypeError; + var QObject = global$z.QObject; + var nativeGetOwnPropertyDescriptor$2 = getOwnPropertyDescriptorModule$3.f; + var nativeDefineProperty$1 = definePropertyModule$2.f; + var nativeGetOwnPropertyNames = getOwnPropertyNamesExternal.f; + var nativePropertyIsEnumerable = propertyIsEnumerableModule$1.f; + var push$8 = uncurryThis$H([].push); + + var AllSymbols = shared$2('symbols'); + var ObjectPrototypeSymbols = shared$2('op-symbols'); + var WellKnownSymbolsStore = shared$2('wks'); + + // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 + var USE_SETTER = !QObject || !QObject[PROTOTYPE$1] || !QObject[PROTOTYPE$1].findChild; + + // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 + var fallbackDefineProperty = function (O, P, Attributes) { + var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$2(ObjectPrototype$4, P); + if (ObjectPrototypeDescriptor) delete ObjectPrototype$4[P]; + nativeDefineProperty$1(O, P, Attributes); + if (ObjectPrototypeDescriptor && O !== ObjectPrototype$4) { + nativeDefineProperty$1(ObjectPrototype$4, P, ObjectPrototypeDescriptor); + } + }; + + var setSymbolDescriptor = DESCRIPTORS$m && fails$L(function () { + return nativeObjectCreate(nativeDefineProperty$1({}, 'a', { + get: function () { return nativeDefineProperty$1(this, 'a', { value: 7 }).a; } + })).a !== 7; + }) ? fallbackDefineProperty : nativeDefineProperty$1; + + var wrap = function (tag, description) { + var symbol = AllSymbols[tag] = nativeObjectCreate(SymbolPrototype$1); + setInternalState$9(symbol, { + type: SYMBOL, + tag: tag, + description: description + }); + if (!DESCRIPTORS$m) symbol.description = description; + return symbol; + }; + + var $defineProperty = function defineProperty(O, P, Attributes) { + if (O === ObjectPrototype$4) $defineProperty(ObjectPrototypeSymbols, P, Attributes); + anObject$h(O); + var key = toPropertyKey$1(P); + anObject$h(Attributes); + if (hasOwn$g(AllSymbols, key)) { + if (!Attributes.enumerable) { + if (!hasOwn$g(O, HIDDEN)) nativeDefineProperty$1(O, HIDDEN, createPropertyDescriptor$3(1, {})); + O[HIDDEN][key] = true; + } else { + if (hasOwn$g(O, HIDDEN) && O[HIDDEN][key]) O[HIDDEN][key] = false; + Attributes = nativeObjectCreate(Attributes, { enumerable: createPropertyDescriptor$3(0, false) }); + } return setSymbolDescriptor(O, key, Attributes); + } return nativeDefineProperty$1(O, key, Attributes); + }; + + var $defineProperties = function defineProperties(O, Properties) { + anObject$h(O); + var properties = toIndexedObject$8(Properties); + var keys = objectKeys$2(properties).concat($getOwnPropertySymbols(properties)); + $forEach$2(keys, function (key) { + if (!DESCRIPTORS$m || call$l($propertyIsEnumerable$1, properties, key)) $defineProperty(O, key, properties[key]); + }); + return O; + }; + + var $create = function create(O, Properties) { + return Properties === undefined ? nativeObjectCreate(O) : $defineProperties(nativeObjectCreate(O), Properties); + }; + + var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) { + var P = toPropertyKey$1(V); + var enumerable = call$l(nativePropertyIsEnumerable, this, P); + if (this === ObjectPrototype$4 && hasOwn$g(AllSymbols, P) && !hasOwn$g(ObjectPrototypeSymbols, P)) return false; + return enumerable || !hasOwn$g(this, P) || !hasOwn$g(AllSymbols, P) || hasOwn$g(this, HIDDEN) && this[HIDDEN][P] + ? enumerable : true; + }; + + var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(O, P) { + var it = toIndexedObject$8(O); + var key = toPropertyKey$1(P); + if (it === ObjectPrototype$4 && hasOwn$g(AllSymbols, key) && !hasOwn$g(ObjectPrototypeSymbols, key)) return; + var descriptor = nativeGetOwnPropertyDescriptor$2(it, key); + if (descriptor && hasOwn$g(AllSymbols, key) && !(hasOwn$g(it, HIDDEN) && it[HIDDEN][key])) { + descriptor.enumerable = true; + } + return descriptor; + }; + + var $getOwnPropertyNames = function getOwnPropertyNames(O) { + var names = nativeGetOwnPropertyNames(toIndexedObject$8(O)); + var result = []; + $forEach$2(names, function (key) { + if (!hasOwn$g(AllSymbols, key) && !hasOwn$g(hiddenKeys$1, key)) push$8(result, key); + }); + return result; + }; + + var $getOwnPropertySymbols = function (O) { + var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$4; + var names = nativeGetOwnPropertyNames(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject$8(O)); + var result = []; + $forEach$2(names, function (key) { + if (hasOwn$g(AllSymbols, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$g(ObjectPrototype$4, key))) { + push$8(result, AllSymbols[key]); + } + }); + return result; + }; + + // `Symbol` constructor + // https://tc39.es/ecma262/#sec-symbol-constructor + if (!NATIVE_SYMBOL$4) { + $Symbol = function Symbol() { + if (isPrototypeOf$7(SymbolPrototype$1, this)) throw new TypeError$6('Symbol is not a constructor'); + var description = !arguments.length || arguments[0] === undefined ? undefined : $toString$3(arguments[0]); + var tag = uid$2(description); + var setter = function (value) { + if (this === ObjectPrototype$4) call$l(setter, ObjectPrototypeSymbols, value); + if (hasOwn$g(this, HIDDEN) && hasOwn$g(this[HIDDEN], tag)) this[HIDDEN][tag] = false; + var descriptor = createPropertyDescriptor$3(1, value); + try { + setSymbolDescriptor(this, tag, descriptor); + } catch (error) { + if (!(error instanceof RangeError$4)) throw error; + fallbackDefineProperty(this, tag, descriptor); + } + }; + if (DESCRIPTORS$m && USE_SETTER) setSymbolDescriptor(ObjectPrototype$4, tag, { configurable: true, set: setter }); + return wrap(tag, description); + }; + + SymbolPrototype$1 = $Symbol[PROTOTYPE$1]; + + defineBuiltIn$e(SymbolPrototype$1, 'toString', function toString() { + return getInternalState$4(this).tag; + }); + + defineBuiltIn$e($Symbol, 'withoutSetter', function (description) { + return wrap(uid$2(description), description); + }); + + propertyIsEnumerableModule$1.f = $propertyIsEnumerable$1; + definePropertyModule$2.f = $defineProperty; + definePropertiesModule.f = $defineProperties; + getOwnPropertyDescriptorModule$3.f = $getOwnPropertyDescriptor; + getOwnPropertyNamesModule$1.f = getOwnPropertyNamesExternal.f = $getOwnPropertyNames; + getOwnPropertySymbolsModule$2.f = $getOwnPropertySymbols; + + wrappedWellKnownSymbolModule.f = function (name) { + return wrap(wellKnownSymbol$l(name), name); + }; + + if (DESCRIPTORS$m) { + // https://github.com/tc39/proposal-Symbol-description + defineBuiltInAccessor$a(SymbolPrototype$1, 'description', { + configurable: true, + get: function description() { + return getInternalState$4(this).description; + } + }); + { + defineBuiltIn$e(ObjectPrototype$4, 'propertyIsEnumerable', $propertyIsEnumerable$1, { unsafe: true }); + } + } + } + + $$1d({ global: true, constructor: true, wrap: true, forced: !NATIVE_SYMBOL$4, sham: !NATIVE_SYMBOL$4 }, { + Symbol: $Symbol + }); + + $forEach$2(objectKeys$2(WellKnownSymbolsStore), function (name) { + defineWellKnownSymbol$4(name); + }); + + $$1d({ target: SYMBOL, stat: true, forced: !NATIVE_SYMBOL$4 }, { + useSetter: function () { USE_SETTER = true; }, + useSimple: function () { USE_SETTER = false; } + }); + + $$1d({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$4, sham: !DESCRIPTORS$m }, { + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + create: $create, + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + defineProperty: $defineProperty, + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + defineProperties: $defineProperties, + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors + getOwnPropertyDescriptor: $getOwnPropertyDescriptor + }); + + $$1d({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$4 }, { + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + getOwnPropertyNames: $getOwnPropertyNames + }); + + // `Symbol.prototype[@@toPrimitive]` method + // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive + defineSymbolToPrimitive$1(); + + // `Symbol.prototype[@@toStringTag]` property + // https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag + setToStringTag$a($Symbol, SYMBOL); + + hiddenKeys$1[HIDDEN] = true; + + var NATIVE_SYMBOL$3 = symbolConstructorDetection; + + /* eslint-disable es/no-symbol -- safe */ + var symbolRegistryDetection = NATIVE_SYMBOL$3 && !!Symbol['for'] && !!Symbol.keyFor; + + var $$1c = _export; + var getBuiltIn$6 = getBuiltIn$c; + var hasOwn$f = hasOwnProperty_1; + var toString$i = toString$n; + var shared$1 = sharedExports; + var NATIVE_SYMBOL_REGISTRY$1 = symbolRegistryDetection; + + var StringToSymbolRegistry = shared$1('string-to-symbol-registry'); + var SymbolToStringRegistry$1 = shared$1('symbol-to-string-registry'); + + // `Symbol.for` method + // https://tc39.es/ecma262/#sec-symbol.for + $$1c({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY$1 }, { + 'for': function (key) { + var string = toString$i(key); + if (hasOwn$f(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string]; + var symbol = getBuiltIn$6('Symbol')(string); + StringToSymbolRegistry[string] = symbol; + SymbolToStringRegistry$1[symbol] = string; + return symbol; + } + }); + + var $$1b = _export; + var hasOwn$e = hasOwnProperty_1; + var isSymbol$3 = isSymbol$6; + var tryToString$5 = tryToString$7; + var shared = sharedExports; + var NATIVE_SYMBOL_REGISTRY = symbolRegistryDetection; + + var SymbolToStringRegistry = shared('symbol-to-string-registry'); + + // `Symbol.keyFor` method + // https://tc39.es/ecma262/#sec-symbol.keyfor + $$1b({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY }, { + keyFor: function keyFor(sym) { + if (!isSymbol$3(sym)) throw new TypeError(tryToString$5(sym) + ' is not a symbol'); + if (hasOwn$e(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym]; + } + }); + + var uncurryThis$G = functionUncurryThis; + + var arraySlice$a = uncurryThis$G([].slice); + + var uncurryThis$F = functionUncurryThis; + var isArray$6 = isArray$8; + var isCallable$g = isCallable$w; + var classof$b = classofRaw$2; + var toString$h = toString$n; + + var push$7 = uncurryThis$F([].push); + + var getJsonReplacerFunction = function (replacer) { + if (isCallable$g(replacer)) return replacer; + if (!isArray$6(replacer)) return; + var rawLength = replacer.length; + var keys = []; + for (var i = 0; i < rawLength; i++) { + var element = replacer[i]; + if (typeof element == 'string') push$7(keys, element); + else if (typeof element == 'number' || classof$b(element) === 'Number' || classof$b(element) === 'String') push$7(keys, toString$h(element)); + } + var keysLength = keys.length; + var root = true; + return function (key, value) { + if (root) { + root = false; + return value; + } + if (isArray$6(this)) return value; + for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value; + }; + }; + + var $$1a = _export; + var getBuiltIn$5 = getBuiltIn$c; + var apply$7 = functionApply; + var call$k = functionCall; + var uncurryThis$E = functionUncurryThis; + var fails$K = fails$_; + var isCallable$f = isCallable$w; + var isSymbol$2 = isSymbol$6; + var arraySlice$9 = arraySlice$a; + var getReplacerFunction = getJsonReplacerFunction; + var NATIVE_SYMBOL$2 = symbolConstructorDetection; + + var $String$1 = String; + var $stringify = getBuiltIn$5('JSON', 'stringify'); + var exec$5 = uncurryThis$E(/./.exec); + var charAt$5 = uncurryThis$E(''.charAt); + var charCodeAt$2 = uncurryThis$E(''.charCodeAt); + var replace$7 = uncurryThis$E(''.replace); + var numberToString$1 = uncurryThis$E(1.0.toString); + + var tester = /[\uD800-\uDFFF]/g; + var low = /^[\uD800-\uDBFF]$/; + var hi = /^[\uDC00-\uDFFF]$/; + + var WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL$2 || fails$K(function () { + var symbol = getBuiltIn$5('Symbol')('stringify detection'); + // MS Edge converts symbol values to JSON as {} + return $stringify([symbol]) !== '[null]' + // WebKit converts symbol values to JSON as null + || $stringify({ a: symbol }) !== '{}' + // V8 throws on boxed symbols + || $stringify(Object(symbol)) !== '{}'; + }); + + // https://github.com/tc39/proposal-well-formed-stringify + var ILL_FORMED_UNICODE = fails$K(function () { + return $stringify('\uDF06\uD834') !== '"\\udf06\\ud834"' + || $stringify('\uDEAD') !== '"\\udead"'; + }); + + var stringifyWithSymbolsFix = function (it, replacer) { + var args = arraySlice$9(arguments); + var $replacer = getReplacerFunction(replacer); + if (!isCallable$f($replacer) && (it === undefined || isSymbol$2(it))) return; // IE8 returns string on undefined + args[1] = function (key, value) { + // some old implementations (like WebKit) could pass numbers as keys + if (isCallable$f($replacer)) value = call$k($replacer, this, $String$1(key), value); + if (!isSymbol$2(value)) return value; + }; + return apply$7($stringify, null, args); + }; + + var fixIllFormed = function (match, offset, string) { + var prev = charAt$5(string, offset - 1); + var next = charAt$5(string, offset + 1); + if ((exec$5(low, match) && !exec$5(hi, next)) || (exec$5(hi, match) && !exec$5(low, prev))) { + return '\\u' + numberToString$1(charCodeAt$2(match, 0), 16); + } return match; + }; + + if ($stringify) { + // `JSON.stringify` method + // https://tc39.es/ecma262/#sec-json.stringify + $$1a({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + stringify: function stringify(it, replacer, space) { + var args = arraySlice$9(arguments); + var result = apply$7(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args); + return ILL_FORMED_UNICODE && typeof result == 'string' ? replace$7(result, tester, fixIllFormed) : result; + } + }); + } + + var $$19 = _export; + var NATIVE_SYMBOL$1 = symbolConstructorDetection; + var fails$J = fails$_; + var getOwnPropertySymbolsModule$1 = objectGetOwnPropertySymbols; + var toObject$d = toObject$h; + + // V8 ~ Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives + // https://bugs.chromium.org/p/v8/issues/detail?id=3443 + var FORCED$h = !NATIVE_SYMBOL$1 || fails$J(function () { getOwnPropertySymbolsModule$1.f(1); }); + + // `Object.getOwnPropertySymbols` method + // https://tc39.es/ecma262/#sec-object.getownpropertysymbols + $$19({ target: 'Object', stat: true, forced: FORCED$h }, { + getOwnPropertySymbols: function getOwnPropertySymbols(it) { + var $getOwnPropertySymbols = getOwnPropertySymbolsModule$1.f; + return $getOwnPropertySymbols ? $getOwnPropertySymbols(toObject$d(it)) : []; + } + }); + + var $$18 = _export; + var DESCRIPTORS$l = descriptors; + var global$y = global$O; + var uncurryThis$D = functionUncurryThis; + var hasOwn$d = hasOwnProperty_1; + var isCallable$e = isCallable$w; + var isPrototypeOf$6 = objectIsPrototypeOf; + var toString$g = toString$n; + var defineBuiltInAccessor$9 = defineBuiltInAccessor$b; + var copyConstructorProperties$1 = copyConstructorProperties$3; + + var NativeSymbol = global$y.Symbol; + var SymbolPrototype = NativeSymbol && NativeSymbol.prototype; + + if (DESCRIPTORS$l && isCallable$e(NativeSymbol) && (!('description' in SymbolPrototype) || + // Safari 12 bug + NativeSymbol().description !== undefined + )) { + var EmptyStringDescriptionStore = {}; + // wrap Symbol constructor for correct work with undefined description + var SymbolWrapper = function Symbol() { + var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString$g(arguments[0]); + var result = isPrototypeOf$6(SymbolPrototype, this) + ? new NativeSymbol(description) + // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)' + : description === undefined ? NativeSymbol() : NativeSymbol(description); + if (description === '') EmptyStringDescriptionStore[result] = true; + return result; + }; + + copyConstructorProperties$1(SymbolWrapper, NativeSymbol); + SymbolWrapper.prototype = SymbolPrototype; + SymbolPrototype.constructor = SymbolWrapper; + + var NATIVE_SYMBOL = String(NativeSymbol('description detection')) === 'Symbol(description detection)'; + var thisSymbolValue = uncurryThis$D(SymbolPrototype.valueOf); + var symbolDescriptiveString = uncurryThis$D(SymbolPrototype.toString); + var regexp = /^Symbol\((.*)\)[^)]+$/; + var replace$6 = uncurryThis$D(''.replace); + var stringSlice$7 = uncurryThis$D(''.slice); + + defineBuiltInAccessor$9(SymbolPrototype, 'description', { + configurable: true, + get: function description() { + var symbol = thisSymbolValue(this); + if (hasOwn$d(EmptyStringDescriptionStore, symbol)) return ''; + var string = symbolDescriptiveString(symbol); + var desc = NATIVE_SYMBOL ? stringSlice$7(string, 7, -1) : replace$6(string, regexp, '$1'); + return desc === '' ? undefined : desc; + } + }); + + $$18({ global: true, constructor: true, forced: true }, { + Symbol: SymbolWrapper + }); + } + + var TO_STRING_TAG_SUPPORT$1 = toStringTagSupport; + var classof$a = classof$i; + + // `Object.prototype.toString` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.tostring + var objectToString = TO_STRING_TAG_SUPPORT$1 ? {}.toString : function toString() { + return '[object ' + classof$a(this) + ']'; + }; + + var TO_STRING_TAG_SUPPORT = toStringTagSupport; + var defineBuiltIn$d = defineBuiltIn$i; + var toString$f = objectToString; + + // `Object.prototype.toString` method + // https://tc39.es/ecma262/#sec-object.prototype.tostring + if (!TO_STRING_TAG_SUPPORT) { + defineBuiltIn$d(Object.prototype, 'toString', toString$f, { unsafe: true }); + } + + var defineWellKnownSymbol$3 = wellKnownSymbolDefine; + + // `Symbol.iterator` well-known symbol + // https://tc39.es/ecma262/#sec-symbol.iterator + defineWellKnownSymbol$3('iterator'); + + var wellKnownSymbol$k = wellKnownSymbol$x; + var create$6 = objectCreate; + var defineProperty$6 = objectDefineProperty.f; + + var UNSCOPABLES = wellKnownSymbol$k('unscopables'); + var ArrayPrototype$1 = Array.prototype; + + // Array.prototype[@@unscopables] + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + if (ArrayPrototype$1[UNSCOPABLES] === undefined) { + defineProperty$6(ArrayPrototype$1, UNSCOPABLES, { + configurable: true, + value: create$6(null) + }); + } + + // add a key to Array.prototype[@@unscopables] + var addToUnscopables$4 = function (key) { + ArrayPrototype$1[UNSCOPABLES][key] = true; + }; + + var iterators = {}; + + var fails$I = fails$_; + + var correctPrototypeGetter = !fails$I(function () { + function F() { /* empty */ } + F.prototype.constructor = null; + // eslint-disable-next-line es/no-object-getprototypeof -- required for testing + return Object.getPrototypeOf(new F()) !== F.prototype; + }); + + var hasOwn$c = hasOwnProperty_1; + var isCallable$d = isCallable$w; + var toObject$c = toObject$h; + var sharedKey = sharedKey$4; + var CORRECT_PROTOTYPE_GETTER$1 = correctPrototypeGetter; + + var IE_PROTO = sharedKey('IE_PROTO'); + var $Object$1 = Object; + var ObjectPrototype$3 = $Object$1.prototype; + + // `Object.getPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.getprototypeof + // eslint-disable-next-line es/no-object-getprototypeof -- safe + var objectGetPrototypeOf$1 = CORRECT_PROTOTYPE_GETTER$1 ? $Object$1.getPrototypeOf : function (O) { + var object = toObject$c(O); + if (hasOwn$c(object, IE_PROTO)) return object[IE_PROTO]; + var constructor = object.constructor; + if (isCallable$d(constructor) && object instanceof constructor) { + return constructor.prototype; + } return object instanceof $Object$1 ? ObjectPrototype$3 : null; + }; + + var fails$H = fails$_; + var isCallable$c = isCallable$w; + var isObject$l = isObject$t; + var getPrototypeOf$5 = objectGetPrototypeOf$1; + var defineBuiltIn$c = defineBuiltIn$i; + var wellKnownSymbol$j = wellKnownSymbol$x; + + var ITERATOR$a = wellKnownSymbol$j('iterator'); + var BUGGY_SAFARI_ITERATORS$1 = false; + + // `%IteratorPrototype%` object + // https://tc39.es/ecma262/#sec-%iteratorprototype%-object + var IteratorPrototype$2, PrototypeOfArrayIteratorPrototype, arrayIterator; + + /* eslint-disable es/no-array-prototype-keys -- safe */ + if ([].keys) { + arrayIterator = [].keys(); + // Safari 8 has buggy iterators w/o `next` + if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true; + else { + PrototypeOfArrayIteratorPrototype = getPrototypeOf$5(getPrototypeOf$5(arrayIterator)); + if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$2 = PrototypeOfArrayIteratorPrototype; + } + } + + var NEW_ITERATOR_PROTOTYPE = !isObject$l(IteratorPrototype$2) || fails$H(function () { + var test = {}; + // FF44- legacy iterators case + return IteratorPrototype$2[ITERATOR$a].call(test) !== test; + }); + + if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$2 = {}; + + // `%IteratorPrototype%[@@iterator]()` method + // https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator + if (!isCallable$c(IteratorPrototype$2[ITERATOR$a])) { + defineBuiltIn$c(IteratorPrototype$2, ITERATOR$a, function () { + return this; + }); + } + + var iteratorsCore = { + IteratorPrototype: IteratorPrototype$2, + BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1 + }; + + var IteratorPrototype$1 = iteratorsCore.IteratorPrototype; + var create$5 = objectCreate; + var createPropertyDescriptor$2 = createPropertyDescriptor$7; + var setToStringTag$9 = setToStringTag$b; + var Iterators$4 = iterators; + + var returnThis$1 = function () { return this; }; + + var iteratorCreateConstructor = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) { + var TO_STRING_TAG = NAME + ' Iterator'; + IteratorConstructor.prototype = create$5(IteratorPrototype$1, { next: createPropertyDescriptor$2(+!ENUMERABLE_NEXT, next) }); + setToStringTag$9(IteratorConstructor, TO_STRING_TAG, false); + Iterators$4[TO_STRING_TAG] = returnThis$1; + return IteratorConstructor; + }; + + var uncurryThis$C = functionUncurryThis; + var aCallable$9 = aCallable$c; + + var functionUncurryThisAccessor = function (object, key, method) { + try { + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + return uncurryThis$C(aCallable$9(Object.getOwnPropertyDescriptor(object, key)[method])); + } catch (error) { /* empty */ } + }; + + var isCallable$b = isCallable$w; + + var $String = String; + var $TypeError$d = TypeError; + + var aPossiblePrototype$1 = function (argument) { + if (typeof argument == 'object' || isCallable$b(argument)) return argument; + throw new $TypeError$d("Can't set " + $String(argument) + ' as a prototype'); + }; + + /* eslint-disable no-proto -- safe */ + var uncurryThisAccessor = functionUncurryThisAccessor; + var anObject$g = anObject$p; + var aPossiblePrototype = aPossiblePrototype$1; + + // `Object.setPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.setprototypeof + // Works with __proto__ only. Old v8 can't work with null proto objects. + // eslint-disable-next-line es/no-object-setprototypeof -- safe + var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () { + var CORRECT_SETTER = false; + var test = {}; + var setter; + try { + setter = uncurryThisAccessor(Object.prototype, '__proto__', 'set'); + setter(test, []); + CORRECT_SETTER = test instanceof Array; + } catch (error) { /* empty */ } + return function setPrototypeOf(O, proto) { + anObject$g(O); + aPossiblePrototype(proto); + if (CORRECT_SETTER) setter(O, proto); + else O.__proto__ = proto; + return O; + }; + }() : undefined); + + var $$17 = _export; + var call$j = functionCall; + var FunctionName$1 = functionName; + var isCallable$a = isCallable$w; + var createIteratorConstructor$1 = iteratorCreateConstructor; + var getPrototypeOf$4 = objectGetPrototypeOf$1; + var setPrototypeOf$6 = objectSetPrototypeOf; + var setToStringTag$8 = setToStringTag$b; + var createNonEnumerableProperty$6 = createNonEnumerableProperty$a; + var defineBuiltIn$b = defineBuiltIn$i; + var wellKnownSymbol$i = wellKnownSymbol$x; + var Iterators$3 = iterators; + var IteratorsCore = iteratorsCore; + + var PROPER_FUNCTION_NAME$3 = FunctionName$1.PROPER; + var CONFIGURABLE_FUNCTION_NAME$1 = FunctionName$1.CONFIGURABLE; + var IteratorPrototype = IteratorsCore.IteratorPrototype; + var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS; + var ITERATOR$9 = wellKnownSymbol$i('iterator'); + var KEYS = 'keys'; + var VALUES = 'values'; + var ENTRIES = 'entries'; + + var returnThis = function () { return this; }; + + var iteratorDefine = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) { + createIteratorConstructor$1(IteratorConstructor, NAME, next); + + var getIterationMethod = function (KIND) { + if (KIND === DEFAULT && defaultIterator) return defaultIterator; + if (!BUGGY_SAFARI_ITERATORS && KIND && KIND in IterablePrototype) return IterablePrototype[KIND]; + + switch (KIND) { + case KEYS: return function keys() { return new IteratorConstructor(this, KIND); }; + case VALUES: return function values() { return new IteratorConstructor(this, KIND); }; + case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); }; + } + + return function () { return new IteratorConstructor(this); }; + }; + + var TO_STRING_TAG = NAME + ' Iterator'; + var INCORRECT_VALUES_NAME = false; + var IterablePrototype = Iterable.prototype; + var nativeIterator = IterablePrototype[ITERATOR$9] + || IterablePrototype['@@iterator'] + || DEFAULT && IterablePrototype[DEFAULT]; + var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT); + var anyNativeIterator = NAME === 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator; + var CurrentIteratorPrototype, methods, KEY; + + // fix native + if (anyNativeIterator) { + CurrentIteratorPrototype = getPrototypeOf$4(anyNativeIterator.call(new Iterable())); + if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) { + if (getPrototypeOf$4(CurrentIteratorPrototype) !== IteratorPrototype) { + if (setPrototypeOf$6) { + setPrototypeOf$6(CurrentIteratorPrototype, IteratorPrototype); + } else if (!isCallable$a(CurrentIteratorPrototype[ITERATOR$9])) { + defineBuiltIn$b(CurrentIteratorPrototype, ITERATOR$9, returnThis); + } + } + // Set @@toStringTag to native iterators + setToStringTag$8(CurrentIteratorPrototype, TO_STRING_TAG, true); + } + } + + // fix Array.prototype.{ values, @@iterator }.name in V8 / FF + if (PROPER_FUNCTION_NAME$3 && DEFAULT === VALUES && nativeIterator && nativeIterator.name !== VALUES) { + if (CONFIGURABLE_FUNCTION_NAME$1) { + createNonEnumerableProperty$6(IterablePrototype, 'name', VALUES); + } else { + INCORRECT_VALUES_NAME = true; + defaultIterator = function values() { return call$j(nativeIterator, this); }; + } + } + + // export additional methods + if (DEFAULT) { + methods = { + values: getIterationMethod(VALUES), + keys: IS_SET ? defaultIterator : getIterationMethod(KEYS), + entries: getIterationMethod(ENTRIES) + }; + if (FORCED) for (KEY in methods) { + if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) { + defineBuiltIn$b(IterablePrototype, KEY, methods[KEY]); + } + } else $$17({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods); + } + + // define iterator + if (IterablePrototype[ITERATOR$9] !== defaultIterator) { + defineBuiltIn$b(IterablePrototype, ITERATOR$9, defaultIterator, { name: DEFAULT }); + } + Iterators$3[NAME] = defaultIterator; + + return methods; + }; + + // `CreateIterResultObject` abstract operation + // https://tc39.es/ecma262/#sec-createiterresultobject + var createIterResultObject$3 = function (value, done) { + return { value: value, done: done }; + }; + + var toIndexedObject$7 = toIndexedObject$e; + var addToUnscopables$3 = addToUnscopables$4; + var Iterators$2 = iterators; + var InternalStateModule$9 = internalState; + var defineProperty$5 = objectDefineProperty.f; + var defineIterator$2 = iteratorDefine; + var createIterResultObject$2 = createIterResultObject$3; + var DESCRIPTORS$k = descriptors; + + var ARRAY_ITERATOR = 'Array Iterator'; + var setInternalState$8 = InternalStateModule$9.set; + var getInternalState$3 = InternalStateModule$9.getterFor(ARRAY_ITERATOR); + + // `Array.prototype.entries` method + // https://tc39.es/ecma262/#sec-array.prototype.entries + // `Array.prototype.keys` method + // https://tc39.es/ecma262/#sec-array.prototype.keys + // `Array.prototype.values` method + // https://tc39.es/ecma262/#sec-array.prototype.values + // `Array.prototype[@@iterator]` method + // https://tc39.es/ecma262/#sec-array.prototype-@@iterator + // `CreateArrayIterator` internal method + // https://tc39.es/ecma262/#sec-createarrayiterator + var es_array_iterator = defineIterator$2(Array, 'Array', function (iterated, kind) { + setInternalState$8(this, { + type: ARRAY_ITERATOR, + target: toIndexedObject$7(iterated), // target + index: 0, // next index + kind: kind // kind + }); + // `%ArrayIteratorPrototype%.next` method + // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next + }, function () { + var state = getInternalState$3(this); + var target = state.target; + var kind = state.kind; + var index = state.index++; + if (!target || index >= target.length) { + state.target = undefined; + return createIterResultObject$2(undefined, true); + } + switch (kind) { + case 'keys': return createIterResultObject$2(index, false); + case 'values': return createIterResultObject$2(target[index], false); + } return createIterResultObject$2([index, target[index]], false); + }, 'values'); + + // argumentsList[@@iterator] is %ArrayProto_values% + // https://tc39.es/ecma262/#sec-createunmappedargumentsobject + // https://tc39.es/ecma262/#sec-createmappedargumentsobject + var values = Iterators$2.Arguments = Iterators$2.Array; + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables$3('keys'); + addToUnscopables$3('values'); + addToUnscopables$3('entries'); + + // V8 ~ Chrome 45- bug + if (DESCRIPTORS$k && values.name !== 'values') try { + defineProperty$5(values, 'name', { value: 'values' }); + } catch (error) { /* empty */ } + + var charAt$4 = stringMultibyte.charAt; + var toString$e = toString$n; + var InternalStateModule$8 = internalState; + var defineIterator$1 = iteratorDefine; + var createIterResultObject$1 = createIterResultObject$3; + + var STRING_ITERATOR = 'String Iterator'; + var setInternalState$7 = InternalStateModule$8.set; + var getInternalState$2 = InternalStateModule$8.getterFor(STRING_ITERATOR); + + // `String.prototype[@@iterator]` method + // https://tc39.es/ecma262/#sec-string.prototype-@@iterator + defineIterator$1(String, 'String', function (iterated) { + setInternalState$7(this, { + type: STRING_ITERATOR, + string: toString$e(iterated), + index: 0 + }); + // `%StringIteratorPrototype%.next` method + // https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next + }, function next() { + var state = getInternalState$2(this); + var string = state.string; + var index = state.index; + var point; + if (index >= string.length) return createIterResultObject$1(undefined, true); + point = charAt$4(string, index); + state.index += point.length; + return createIterResultObject$1(point, false); + }); + + // iterable DOM collections + // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods + var domIterables = { + CSSRuleList: 0, + CSSStyleDeclaration: 0, + CSSValueList: 0, + ClientRectList: 0, + DOMRectList: 0, + DOMStringList: 0, + DOMTokenList: 1, + DataTransferItemList: 0, + FileList: 0, + HTMLAllCollection: 0, + HTMLCollection: 0, + HTMLFormElement: 0, + HTMLSelectElement: 0, + MediaList: 0, + MimeTypeArray: 0, + NamedNodeMap: 0, + NodeList: 1, + PaintRequestList: 0, + Plugin: 0, + PluginArray: 0, + SVGLengthList: 0, + SVGNumberList: 0, + SVGPathSegList: 0, + SVGPointList: 0, + SVGStringList: 0, + SVGTransformList: 0, + SourceBufferList: 0, + StyleSheetList: 0, + TextTrackCueList: 0, + TextTrackList: 0, + TouchList: 0 + }; + + // in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList` + var documentCreateElement = documentCreateElement$2; + + var classList = documentCreateElement('span').classList; + var DOMTokenListPrototype$2 = classList && classList.constructor && classList.constructor.prototype; + + var domTokenListPrototype = DOMTokenListPrototype$2 === Object.prototype ? undefined : DOMTokenListPrototype$2; + + var global$x = global$O; + var DOMIterables$1 = domIterables; + var DOMTokenListPrototype$1 = domTokenListPrototype; + var ArrayIteratorMethods = es_array_iterator; + var createNonEnumerableProperty$5 = createNonEnumerableProperty$a; + var wellKnownSymbol$h = wellKnownSymbol$x; + + var ITERATOR$8 = wellKnownSymbol$h('iterator'); + var TO_STRING_TAG$1 = wellKnownSymbol$h('toStringTag'); + var ArrayValues = ArrayIteratorMethods.values; + + var handlePrototype$1 = function (CollectionPrototype, COLLECTION_NAME) { + if (CollectionPrototype) { + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype[ITERATOR$8] !== ArrayValues) try { + createNonEnumerableProperty$5(CollectionPrototype, ITERATOR$8, ArrayValues); + } catch (error) { + CollectionPrototype[ITERATOR$8] = ArrayValues; + } + if (!CollectionPrototype[TO_STRING_TAG$1]) { + createNonEnumerableProperty$5(CollectionPrototype, TO_STRING_TAG$1, COLLECTION_NAME); + } + if (DOMIterables$1[COLLECTION_NAME]) for (var METHOD_NAME in ArrayIteratorMethods) { + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype[METHOD_NAME] !== ArrayIteratorMethods[METHOD_NAME]) try { + createNonEnumerableProperty$5(CollectionPrototype, METHOD_NAME, ArrayIteratorMethods[METHOD_NAME]); + } catch (error) { + CollectionPrototype[METHOD_NAME] = ArrayIteratorMethods[METHOD_NAME]; + } + } + } + }; + + for (var COLLECTION_NAME$1 in DOMIterables$1) { + handlePrototype$1(global$x[COLLECTION_NAME$1] && global$x[COLLECTION_NAME$1].prototype, COLLECTION_NAME$1); + } + + handlePrototype$1(DOMTokenListPrototype$1, 'DOMTokenList'); + + var defineWellKnownSymbol$2 = wellKnownSymbolDefine; + var defineSymbolToPrimitive = symbolDefineToPrimitive; + + // `Symbol.toPrimitive` well-known symbol + // https://tc39.es/ecma262/#sec-symbol.toprimitive + defineWellKnownSymbol$2('toPrimitive'); + + // `Symbol.prototype[@@toPrimitive]` method + // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive + defineSymbolToPrimitive(); + + var anObject$f = anObject$p; + var ordinaryToPrimitive = ordinaryToPrimitive$2; + + var $TypeError$c = TypeError; + + // `Date.prototype[@@toPrimitive](hint)` method implementation + // https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive + var dateToPrimitive$1 = function (hint) { + anObject$f(this); + if (hint === 'string' || hint === 'default') hint = 'string'; + else if (hint !== 'number') throw new $TypeError$c('Incorrect hint'); + return ordinaryToPrimitive(this, hint); + }; + + var hasOwn$b = hasOwnProperty_1; + var defineBuiltIn$a = defineBuiltIn$i; + var dateToPrimitive = dateToPrimitive$1; + var wellKnownSymbol$g = wellKnownSymbol$x; + + var TO_PRIMITIVE = wellKnownSymbol$g('toPrimitive'); + var DatePrototype$2 = Date.prototype; + + // `Date.prototype[@@toPrimitive]` method + // https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive + if (!hasOwn$b(DatePrototype$2, TO_PRIMITIVE)) { + defineBuiltIn$a(DatePrototype$2, TO_PRIMITIVE, dateToPrimitive); + } + + var isCallable$9 = isCallable$w; + var isObject$k = isObject$t; + var setPrototypeOf$5 = objectSetPrototypeOf; + + // makes subclassing work correct for wrapped built-ins + var inheritIfRequired$4 = function ($this, dummy, Wrapper) { + var NewTarget, NewTargetPrototype; + if ( + // it can work only with native `setPrototypeOf` + setPrototypeOf$5 && + // we haven't completely correct pre-ES6 way for getting `new.target`, so use this + isCallable$9(NewTarget = dummy.constructor) && + NewTarget !== Wrapper && + isObject$k(NewTargetPrototype = NewTarget.prototype) && + NewTargetPrototype !== Wrapper.prototype + ) setPrototypeOf$5($this, NewTargetPrototype); + return $this; + }; + + var uncurryThis$B = functionUncurryThis; + + // `thisNumberValue` abstract operation + // https://tc39.es/ecma262/#sec-thisnumbervalue + var thisNumberValue$1 = uncurryThis$B(1.0.valueOf); + + // a string of all valid unicode whitespaces + var whitespaces$4 = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' + + '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; + + var uncurryThis$A = functionUncurryThis; + var requireObjectCoercible$9 = requireObjectCoercible$f; + var toString$d = toString$n; + var whitespaces$3 = whitespaces$4; + + var replace$5 = uncurryThis$A(''.replace); + var ltrim = RegExp('^[' + whitespaces$3 + ']+'); + var rtrim = RegExp('(^|[^' + whitespaces$3 + '])[' + whitespaces$3 + ']+$'); + + // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation + var createMethod$3 = function (TYPE) { + return function ($this) { + var string = toString$d(requireObjectCoercible$9($this)); + if (TYPE & 1) string = replace$5(string, ltrim, ''); + if (TYPE & 2) string = replace$5(string, rtrim, '$1'); + return string; + }; + }; + + var stringTrim = { + // `String.prototype.{ trimLeft, trimStart }` methods + // https://tc39.es/ecma262/#sec-string.prototype.trimstart + start: createMethod$3(1), + // `String.prototype.{ trimRight, trimEnd }` methods + // https://tc39.es/ecma262/#sec-string.prototype.trimend + end: createMethod$3(2), + // `String.prototype.trim` method + // https://tc39.es/ecma262/#sec-string.prototype.trim + trim: createMethod$3(3) + }; + + var $$16 = _export; + var IS_PURE$1 = isPure; + var DESCRIPTORS$j = descriptors; + var global$w = global$O; + var path = path$2; + var uncurryThis$z = functionUncurryThis; + var isForced$3 = isForced_1; + var hasOwn$a = hasOwnProperty_1; + var inheritIfRequired$3 = inheritIfRequired$4; + var isPrototypeOf$5 = objectIsPrototypeOf; + var isSymbol$1 = isSymbol$6; + var toPrimitive$2 = toPrimitive$4; + var fails$G = fails$_; + var getOwnPropertyNames$4 = objectGetOwnPropertyNames.f; + var getOwnPropertyDescriptor$5 = objectGetOwnPropertyDescriptor.f; + var defineProperty$4 = objectDefineProperty.f; + var thisNumberValue = thisNumberValue$1; + var trim$2 = stringTrim.trim; + + var NUMBER = 'Number'; + var NativeNumber = global$w[NUMBER]; + path[NUMBER]; + var NumberPrototype = NativeNumber.prototype; + var TypeError$5 = global$w.TypeError; + var stringSlice$6 = uncurryThis$z(''.slice); + var charCodeAt$1 = uncurryThis$z(''.charCodeAt); + + // `ToNumeric` abstract operation + // https://tc39.es/ecma262/#sec-tonumeric + var toNumeric = function (value) { + var primValue = toPrimitive$2(value, 'number'); + return typeof primValue == 'bigint' ? primValue : toNumber(primValue); + }; + + // `ToNumber` abstract operation + // https://tc39.es/ecma262/#sec-tonumber + var toNumber = function (argument) { + var it = toPrimitive$2(argument, 'number'); + var first, third, radix, maxCode, digits, length, index, code; + if (isSymbol$1(it)) throw new TypeError$5('Cannot convert a Symbol value to a number'); + if (typeof it == 'string' && it.length > 2) { + it = trim$2(it); + first = charCodeAt$1(it, 0); + if (first === 43 || first === 45) { + third = charCodeAt$1(it, 2); + if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix + } else if (first === 48) { + switch (charCodeAt$1(it, 1)) { + // fast equal of /^0b[01]+$/i + case 66: + case 98: + radix = 2; + maxCode = 49; + break; + // fast equal of /^0o[0-7]+$/i + case 79: + case 111: + radix = 8; + maxCode = 55; + break; + default: + return +it; + } + digits = stringSlice$6(it, 2); + length = digits.length; + for (index = 0; index < length; index++) { + code = charCodeAt$1(digits, index); + // parseInt parses a string to a first unavailable symbol + // but ToNumber should return NaN if a string contains unavailable symbols + if (code < 48 || code > maxCode) return NaN; + } return parseInt(digits, radix); + } + } return +it; + }; + + var FORCED$g = isForced$3(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1')); + + var calledWithNew = function (dummy) { + // includes check on 1..constructor(foo) case + return isPrototypeOf$5(NumberPrototype, dummy) && fails$G(function () { thisNumberValue(dummy); }); + }; + + // `Number` constructor + // https://tc39.es/ecma262/#sec-number-constructor + var NumberWrapper = function Number(value) { + var n = arguments.length < 1 ? 0 : NativeNumber(toNumeric(value)); + return calledWithNew(this) ? inheritIfRequired$3(Object(n), this, NumberWrapper) : n; + }; + + NumberWrapper.prototype = NumberPrototype; + if (FORCED$g && !IS_PURE$1) NumberPrototype.constructor = NumberWrapper; + + $$16({ global: true, constructor: true, wrap: true, forced: FORCED$g }, { + Number: NumberWrapper + }); + + // Use `internal/copy-constructor-properties` helper in `core-js@4` + var copyConstructorProperties = function (target, source) { + for (var keys = DESCRIPTORS$j ? getOwnPropertyNames$4(source) : ( + // ES3: + 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + + // ES2015 (in case, if modules with ES2015 Number statics required before): + 'EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,' + + // ESNext + 'fromString,range' + ).split(','), j = 0, key; keys.length > j; j++) { + if (hasOwn$a(source, key = keys[j]) && !hasOwn$a(target, key)) { + defineProperty$4(target, key, getOwnPropertyDescriptor$5(source, key)); + } + } + }; + if (FORCED$g || IS_PURE$1) copyConstructorProperties(path[NUMBER], NativeNumber); + + var $$15 = _export; + var DESCRIPTORS$i = descriptors; + var defineProperty$3 = objectDefineProperty.f; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + // eslint-disable-next-line es/no-object-defineproperty -- safe + $$15({ target: 'Object', stat: true, forced: Object.defineProperty !== defineProperty$3, sham: !DESCRIPTORS$i }, { + defineProperty: defineProperty$3 + }); + + var $$14 = _export; + var global$v = global$O; + + // `globalThis` object + // https://tc39.es/ecma262/#sec-globalthis + $$14({ global: true, forced: global$v.globalThis !== global$v }, { + globalThis: global$v + }); + + var uncurryThis$y = functionUncurryThis; + var aCallable$8 = aCallable$c; + var isObject$j = isObject$t; + var hasOwn$9 = hasOwnProperty_1; + var arraySlice$8 = arraySlice$a; + var NATIVE_BIND = functionBindNative; + + var $Function = Function; + var concat$1 = uncurryThis$y([].concat); + var join$4 = uncurryThis$y([].join); + var factories = {}; + + var construct = function (C, argsLength, args) { + if (!hasOwn$9(factories, argsLength)) { + var list = []; + var i = 0; + for (; i < argsLength; i++) list[i] = 'a[' + i + ']'; + factories[argsLength] = $Function('C,a', 'return new C(' + join$4(list, ',') + ')'); + } return factories[argsLength](C, args); + }; + + // `Function.prototype.bind` method implementation + // https://tc39.es/ecma262/#sec-function.prototype.bind + // eslint-disable-next-line es/no-function-prototype-bind -- detection + var functionBind = NATIVE_BIND ? $Function.bind : function bind(that /* , ...args */) { + var F = aCallable$8(this); + var Prototype = F.prototype; + var partArgs = arraySlice$8(arguments, 1); + var boundFunction = function bound(/* args... */) { + var args = concat$1(partArgs, arraySlice$8(arguments)); + return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args); + }; + if (isObject$j(Prototype)) boundFunction.prototype = Prototype; + return boundFunction; + }; + + var isConstructor$2 = isConstructor$4; + var tryToString$4 = tryToString$7; + + var $TypeError$b = TypeError; + + // `Assert: IsConstructor(argument) is true` + var aConstructor$3 = function (argument) { + if (isConstructor$2(argument)) return argument; + throw new $TypeError$b(tryToString$4(argument) + ' is not a constructor'); + }; + + var $$13 = _export; + var getBuiltIn$4 = getBuiltIn$c; + var apply$6 = functionApply; + var bind$a = functionBind; + var aConstructor$2 = aConstructor$3; + var anObject$e = anObject$p; + var isObject$i = isObject$t; + var create$4 = objectCreate; + var fails$F = fails$_; + + var nativeConstruct = getBuiltIn$4('Reflect', 'construct'); + var ObjectPrototype$2 = Object.prototype; + var push$6 = [].push; + + // `Reflect.construct` method + // https://tc39.es/ecma262/#sec-reflect.construct + // MS Edge supports only 2 arguments and argumentsList argument is optional + // FF Nightly sets third argument as `new.target`, but does not create `this` from it + var NEW_TARGET_BUG = fails$F(function () { + function F() { /* empty */ } + return !(nativeConstruct(function () { /* empty */ }, [], F) instanceof F); + }); + + var ARGS_BUG = !fails$F(function () { + nativeConstruct(function () { /* empty */ }); + }); + + var FORCED$f = NEW_TARGET_BUG || ARGS_BUG; + + $$13({ target: 'Reflect', stat: true, forced: FORCED$f, sham: FORCED$f }, { + construct: function construct(Target, args /* , newTarget */) { + aConstructor$2(Target); + anObject$e(args); + var newTarget = arguments.length < 3 ? Target : aConstructor$2(arguments[2]); + if (ARGS_BUG && !NEW_TARGET_BUG) return nativeConstruct(Target, args, newTarget); + if (Target === newTarget) { + // w/o altered newTarget, optimization for 0-4 arguments + switch (args.length) { + case 0: return new Target(); + case 1: return new Target(args[0]); + case 2: return new Target(args[0], args[1]); + case 3: return new Target(args[0], args[1], args[2]); + case 4: return new Target(args[0], args[1], args[2], args[3]); + } + // w/o altered newTarget, lot of arguments case + var $args = [null]; + apply$6(push$6, $args, args); + return new (apply$6(bind$a, Target, $args))(); + } + // with altered newTarget, not support built-in constructors + var proto = newTarget.prototype; + var instance = create$4(isObject$i(proto) ? proto : ObjectPrototype$2); + var result = apply$6(Target, instance, args); + return isObject$i(result) ? result : instance; + } + }); + + var fails$E = fails$_; + + var arrayMethodIsStrict$8 = function (METHOD_NAME, argument) { + var method = [][METHOD_NAME]; + return !!method && fails$E(function () { + // eslint-disable-next-line no-useless-call -- required for testing + method.call(null, argument || function () { return 1; }, 1); + }); + }; + + var $forEach$1 = arrayIteration.forEach; + var arrayMethodIsStrict$7 = arrayMethodIsStrict$8; + + var STRICT_METHOD$4 = arrayMethodIsStrict$7('forEach'); + + // `Array.prototype.forEach` method implementation + // https://tc39.es/ecma262/#sec-array.prototype.foreach + var arrayForEach = !STRICT_METHOD$4 ? function forEach(callbackfn /* , thisArg */) { + return $forEach$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + // eslint-disable-next-line es/no-array-prototype-foreach -- safe + } : [].forEach; + + var $$12 = _export; + var forEach$2 = arrayForEach; + + // `Array.prototype.forEach` method + // https://tc39.es/ecma262/#sec-array.prototype.foreach + // eslint-disable-next-line es/no-array-prototype-foreach -- safe + $$12({ target: 'Array', proto: true, forced: [].forEach !== forEach$2 }, { + forEach: forEach$2 + }); + + var global$u = global$O; + var DOMIterables = domIterables; + var DOMTokenListPrototype = domTokenListPrototype; + var forEach$1 = arrayForEach; + var createNonEnumerableProperty$4 = createNonEnumerableProperty$a; + + var handlePrototype = function (CollectionPrototype) { + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype && CollectionPrototype.forEach !== forEach$1) try { + createNonEnumerableProperty$4(CollectionPrototype, 'forEach', forEach$1); + } catch (error) { + CollectionPrototype.forEach = forEach$1; + } + }; + + for (var COLLECTION_NAME in DOMIterables) { + if (DOMIterables[COLLECTION_NAME]) { + handlePrototype(global$u[COLLECTION_NAME] && global$u[COLLECTION_NAME].prototype); + } + } + + handlePrototype(DOMTokenListPrototype); + + var $$11 = _export; + var toObject$b = toObject$h; + var nativeKeys = objectKeys$4; + var fails$D = fails$_; + + var FAILS_ON_PRIMITIVES$4 = fails$D(function () { nativeKeys(1); }); + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + $$11({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$4 }, { + keys: function keys(it) { + return nativeKeys(toObject$b(it)); + } + }); + + var $$10 = _export; + var fails$C = fails$_; + var toIndexedObject$6 = toIndexedObject$e; + var nativeGetOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f; + var DESCRIPTORS$h = descriptors; + + var FORCED$e = !DESCRIPTORS$h || fails$C(function () { nativeGetOwnPropertyDescriptor$1(1); }); + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + $$10({ target: 'Object', stat: true, forced: FORCED$e, sham: !DESCRIPTORS$h }, { + getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) { + return nativeGetOwnPropertyDescriptor$1(toIndexedObject$6(it), key); + } + }); + + var PROPER_FUNCTION_NAME$2 = functionName.PROPER; + var fails$B = fails$_; + var whitespaces$2 = whitespaces$4; + + var non = '\u200B\u0085\u180E'; + + // check that a method works with the correct list + // of whitespaces and has a correct name + var stringTrimForced = function (METHOD_NAME) { + return fails$B(function () { + return !!whitespaces$2[METHOD_NAME]() + || non[METHOD_NAME]() !== non + || (PROPER_FUNCTION_NAME$2 && whitespaces$2[METHOD_NAME].name !== METHOD_NAME); + }); + }; + + var $$$ = _export; + var $trim = stringTrim.trim; + var forcedStringTrimMethod = stringTrimForced; + + // `String.prototype.trim` method + // https://tc39.es/ecma262/#sec-string.prototype.trim + $$$({ target: 'String', proto: true, forced: forcedStringTrimMethod('trim') }, { + trim: function trim() { + return $trim(this); + } + }); + + var aCallable$7 = aCallable$c; + var toObject$a = toObject$h; + var IndexedObject$2 = indexedObject; + var lengthOfArrayLike$c = lengthOfArrayLike$g; + + var $TypeError$a = TypeError; + + // `Array.prototype.{ reduce, reduceRight }` methods implementation + var createMethod$2 = function (IS_RIGHT) { + return function (that, callbackfn, argumentsLength, memo) { + aCallable$7(callbackfn); + var O = toObject$a(that); + var self = IndexedObject$2(O); + var length = lengthOfArrayLike$c(O); + var index = IS_RIGHT ? length - 1 : 0; + var i = IS_RIGHT ? -1 : 1; + if (argumentsLength < 2) while (true) { + if (index in self) { + memo = self[index]; + index += i; + break; + } + index += i; + if (IS_RIGHT ? index < 0 : length <= index) { + throw new $TypeError$a('Reduce of empty array with no initial value'); + } + } + for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) { + memo = callbackfn(memo, self[index], index, O); + } + return memo; + }; + }; + + var arrayReduce = { + // `Array.prototype.reduce` method + // https://tc39.es/ecma262/#sec-array.prototype.reduce + left: createMethod$2(false), + // `Array.prototype.reduceRight` method + // https://tc39.es/ecma262/#sec-array.prototype.reduceright + right: createMethod$2(true) + }; + + var global$t = global$O; + var classof$9 = classofRaw$2; + + var engineIsNode = classof$9(global$t.process) === 'process'; + + var $$_ = _export; + var $reduce$1 = arrayReduce.left; + var arrayMethodIsStrict$6 = arrayMethodIsStrict$8; + var CHROME_VERSION = engineV8Version; + var IS_NODE$4 = engineIsNode; + + // Chrome 80-82 has a critical bug + // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 + var CHROME_BUG = !IS_NODE$4 && CHROME_VERSION > 79 && CHROME_VERSION < 83; + var FORCED$d = CHROME_BUG || !arrayMethodIsStrict$6('reduce'); + + // `Array.prototype.reduce` method + // https://tc39.es/ecma262/#sec-array.prototype.reduce + $$_({ target: 'Array', proto: true, forced: FORCED$d }, { + reduce: function reduce(callbackfn /* , initialValue */) { + var length = arguments.length; + return $reduce$1(this, callbackfn, length, length > 1 ? arguments[1] : undefined); + } + }); + + var DESCRIPTORS$g = descriptors; + var uncurryThis$x = functionUncurryThis; + var call$i = functionCall; + var fails$A = fails$_; + var objectKeys$1 = objectKeys$4; + var getOwnPropertySymbolsModule = objectGetOwnPropertySymbols; + var propertyIsEnumerableModule = objectPropertyIsEnumerable; + var toObject$9 = toObject$h; + var IndexedObject$1 = indexedObject; + + // eslint-disable-next-line es/no-object-assign -- safe + var $assign = Object.assign; + // eslint-disable-next-line es/no-object-defineproperty -- required for testing + var defineProperty$2 = Object.defineProperty; + var concat = uncurryThis$x([].concat); + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + var objectAssign = !$assign || fails$A(function () { + // should have correct order of operations (Edge bug) + if (DESCRIPTORS$g && $assign({ b: 1 }, $assign(defineProperty$2({}, 'a', { + enumerable: true, + get: function () { + defineProperty$2(this, 'b', { + value: 3, + enumerable: false + }); + } + }), { b: 2 })).b !== 1) return true; + // should work with symbols and should have deterministic property order (V8 bug) + var A = {}; + var B = {}; + // eslint-disable-next-line es/no-symbol -- safe + var symbol = Symbol('assign detection'); + var alphabet = 'abcdefghijklmnopqrst'; + A[symbol] = 7; + alphabet.split('').forEach(function (chr) { B[chr] = chr; }); + return $assign({}, A)[symbol] !== 7 || objectKeys$1($assign({}, B)).join('') !== alphabet; + }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length` + var T = toObject$9(target); + var argumentsLength = arguments.length; + var index = 1; + var getOwnPropertySymbols = getOwnPropertySymbolsModule.f; + var propertyIsEnumerable = propertyIsEnumerableModule.f; + while (argumentsLength > index) { + var S = IndexedObject$1(arguments[index++]); + var keys = getOwnPropertySymbols ? concat(objectKeys$1(S), getOwnPropertySymbols(S)) : objectKeys$1(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) { + key = keys[j++]; + if (!DESCRIPTORS$g || call$i(propertyIsEnumerable, S, key)) T[key] = S[key]; + } + } return T; + } : $assign; + + var $$Z = _export; + var assign$1 = objectAssign; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + // eslint-disable-next-line es/no-object-assign -- required for testing + $$Z({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign$1 }, { + assign: assign$1 + }); + + /* eslint-disable es/no-array-prototype-indexof -- required for testing */ + var $$Y = _export; + var uncurryThis$w = functionUncurryThisClause; + var $indexOf$1 = arrayIncludes.indexOf; + var arrayMethodIsStrict$5 = arrayMethodIsStrict$8; + + var nativeIndexOf = uncurryThis$w([].indexOf); + + var NEGATIVE_ZERO$1 = !!nativeIndexOf && 1 / nativeIndexOf([1], 1, -0) < 0; + var FORCED$c = NEGATIVE_ZERO$1 || !arrayMethodIsStrict$5('indexOf'); + + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + $$Y({ target: 'Array', proto: true, forced: FORCED$c }, { + indexOf: function indexOf(searchElement /* , fromIndex = 0 */) { + var fromIndex = arguments.length > 1 ? arguments[1] : undefined; + return NEGATIVE_ZERO$1 + // convert -0 to +0 + ? nativeIndexOf(this, searchElement, fromIndex) || 0 + : $indexOf$1(this, searchElement, fromIndex); + } + }); + + // TODO: Remove from `core-js@4` + var uncurryThis$v = functionUncurryThis; + var defineBuiltIn$9 = defineBuiltIn$i; + + var DatePrototype$1 = Date.prototype; + var INVALID_DATE = 'Invalid Date'; + var TO_STRING$1 = 'toString'; + var nativeDateToString = uncurryThis$v(DatePrototype$1[TO_STRING$1]); + var thisTimeValue$2 = uncurryThis$v(DatePrototype$1.getTime); + + // `Date.prototype.toString` method + // https://tc39.es/ecma262/#sec-date.prototype.tostring + if (String(new Date(NaN)) !== INVALID_DATE) { + defineBuiltIn$9(DatePrototype$1, TO_STRING$1, function toString() { + var value = thisTimeValue$2(this); + // eslint-disable-next-line no-self-compare -- NaN check + return value === value ? nativeDateToString(this) : INVALID_DATE; + }); + } + + var PROPER_FUNCTION_NAME$1 = functionName.PROPER; + var defineBuiltIn$8 = defineBuiltIn$i; + var anObject$d = anObject$p; + var $toString$2 = toString$n; + var fails$z = fails$_; + var getRegExpFlags$1 = regexpGetFlags; + + var TO_STRING = 'toString'; + var RegExpPrototype$2 = RegExp.prototype; + var nativeToString = RegExpPrototype$2[TO_STRING]; + + var NOT_GENERIC = fails$z(function () { return nativeToString.call({ source: 'a', flags: 'b' }) !== '/a/b'; }); + // FF44- RegExp#toString has a wrong name + var INCORRECT_NAME = PROPER_FUNCTION_NAME$1 && nativeToString.name !== TO_STRING; + + // `RegExp.prototype.toString` method + // https://tc39.es/ecma262/#sec-regexp.prototype.tostring + if (NOT_GENERIC || INCORRECT_NAME) { + defineBuiltIn$8(RegExp.prototype, TO_STRING, function toString() { + var R = anObject$d(this); + var pattern = $toString$2(R.source); + var flags = $toString$2(getRegExpFlags$1(R)); + return '/' + pattern + '/' + flags; + }, { unsafe: true }); + } + + // eslint-disable-next-line es/no-typed-arrays -- safe + var arrayBufferBasicDetection = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined'; + + var defineBuiltIn$7 = defineBuiltIn$i; + + var defineBuiltIns$5 = function (target, src, options) { + for (var key in src) defineBuiltIn$7(target, key, src[key], options); + return target; + }; + + var isPrototypeOf$4 = objectIsPrototypeOf; + + var $TypeError$9 = TypeError; + + var anInstance$8 = function (it, Prototype) { + if (isPrototypeOf$4(Prototype, it)) return it; + throw new $TypeError$9('Incorrect invocation'); + }; + + var toIntegerOrInfinity$5 = toIntegerOrInfinity$a; + var toLength$9 = toLength$c; + + var $RangeError$5 = RangeError; + + // `ToIndex` abstract operation + // https://tc39.es/ecma262/#sec-toindex + var toIndex$2 = function (it) { + if (it === undefined) return 0; + var number = toIntegerOrInfinity$5(it); + var length = toLength$9(number); + if (number !== length) throw new $RangeError$5('Wrong length or index'); + return length; + }; + + // `Math.sign` method implementation + // https://tc39.es/ecma262/#sec-math.sign + // eslint-disable-next-line es/no-math-sign -- safe + var mathSign = Math.sign || function sign(x) { + var n = +x; + // eslint-disable-next-line no-self-compare -- NaN check + return n === 0 || n !== n ? n : n < 0 ? -1 : 1; + }; + + var sign = mathSign; + + var abs$2 = Math.abs; + + var EPSILON = 2.220446049250313e-16; // Number.EPSILON + var INVERSE_EPSILON = 1 / EPSILON; + + var roundTiesToEven = function (n) { + return n + INVERSE_EPSILON - INVERSE_EPSILON; + }; + + var mathFloatRound = function (x, FLOAT_EPSILON, FLOAT_MAX_VALUE, FLOAT_MIN_VALUE) { + var n = +x; + var absolute = abs$2(n); + var s = sign(n); + if (absolute < FLOAT_MIN_VALUE) return s * roundTiesToEven(absolute / FLOAT_MIN_VALUE / FLOAT_EPSILON) * FLOAT_MIN_VALUE * FLOAT_EPSILON; + var a = (1 + FLOAT_EPSILON / EPSILON) * absolute; + var result = a - (a - absolute); + // eslint-disable-next-line no-self-compare -- NaN check + if (result > FLOAT_MAX_VALUE || result !== result) return s * Infinity; + return s * result; + }; + + var floatRound = mathFloatRound; + + var FLOAT32_EPSILON = 1.1920928955078125e-7; // 2 ** -23; + var FLOAT32_MAX_VALUE = 3.4028234663852886e+38; // 2 ** 128 - 2 ** 104 + var FLOAT32_MIN_VALUE = 1.1754943508222875e-38; // 2 ** -126; + + // `Math.fround` method implementation + // https://tc39.es/ecma262/#sec-math.fround + // eslint-disable-next-line es/no-math-fround -- safe + var mathFround = Math.fround || function fround(x) { + return floatRound(x, FLOAT32_EPSILON, FLOAT32_MAX_VALUE, FLOAT32_MIN_VALUE); + }; + + // IEEE754 conversions based on https://github.com/feross/ieee754 + var $Array$2 = Array; + var abs$1 = Math.abs; + var pow$1 = Math.pow; + var floor$5 = Math.floor; + var log = Math.log; + var LN2 = Math.LN2; + + var pack = function (number, mantissaLength, bytes) { + var buffer = $Array$2(bytes); + var exponentLength = bytes * 8 - mantissaLength - 1; + var eMax = (1 << exponentLength) - 1; + var eBias = eMax >> 1; + var rt = mantissaLength === 23 ? pow$1(2, -24) - pow$1(2, -77) : 0; + var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0; + var index = 0; + var exponent, mantissa, c; + number = abs$1(number); + // eslint-disable-next-line no-self-compare -- NaN check + if (number !== number || number === Infinity) { + // eslint-disable-next-line no-self-compare -- NaN check + mantissa = number !== number ? 1 : 0; + exponent = eMax; + } else { + exponent = floor$5(log(number) / LN2); + c = pow$1(2, -exponent); + if (number * c < 1) { + exponent--; + c *= 2; + } + if (exponent + eBias >= 1) { + number += rt / c; + } else { + number += rt * pow$1(2, 1 - eBias); + } + if (number * c >= 2) { + exponent++; + c /= 2; + } + if (exponent + eBias >= eMax) { + mantissa = 0; + exponent = eMax; + } else if (exponent + eBias >= 1) { + mantissa = (number * c - 1) * pow$1(2, mantissaLength); + exponent += eBias; + } else { + mantissa = number * pow$1(2, eBias - 1) * pow$1(2, mantissaLength); + exponent = 0; + } + } + while (mantissaLength >= 8) { + buffer[index++] = mantissa & 255; + mantissa /= 256; + mantissaLength -= 8; + } + exponent = exponent << mantissaLength | mantissa; + exponentLength += mantissaLength; + while (exponentLength > 0) { + buffer[index++] = exponent & 255; + exponent /= 256; + exponentLength -= 8; + } + buffer[--index] |= sign * 128; + return buffer; + }; + + var unpack = function (buffer, mantissaLength) { + var bytes = buffer.length; + var exponentLength = bytes * 8 - mantissaLength - 1; + var eMax = (1 << exponentLength) - 1; + var eBias = eMax >> 1; + var nBits = exponentLength - 7; + var index = bytes - 1; + var sign = buffer[index--]; + var exponent = sign & 127; + var mantissa; + sign >>= 7; + while (nBits > 0) { + exponent = exponent * 256 + buffer[index--]; + nBits -= 8; + } + mantissa = exponent & (1 << -nBits) - 1; + exponent >>= -nBits; + nBits += mantissaLength; + while (nBits > 0) { + mantissa = mantissa * 256 + buffer[index--]; + nBits -= 8; + } + if (exponent === 0) { + exponent = 1 - eBias; + } else if (exponent === eMax) { + return mantissa ? NaN : sign ? -Infinity : Infinity; + } else { + mantissa += pow$1(2, mantissaLength); + exponent -= eBias; + } return (sign ? -1 : 1) * mantissa * pow$1(2, exponent - mantissaLength); + }; + + var ieee754 = { + pack: pack, + unpack: unpack + }; + + var toObject$8 = toObject$h; + var toAbsoluteIndex$5 = toAbsoluteIndex$8; + var lengthOfArrayLike$b = lengthOfArrayLike$g; + + // `Array.prototype.fill` method implementation + // https://tc39.es/ecma262/#sec-array.prototype.fill + var arrayFill$1 = function fill(value /* , start = 0, end = @length */) { + var O = toObject$8(this); + var length = lengthOfArrayLike$b(O); + var argumentsLength = arguments.length; + var index = toAbsoluteIndex$5(argumentsLength > 1 ? arguments[1] : undefined, length); + var end = argumentsLength > 2 ? arguments[2] : undefined; + var endPos = end === undefined ? length : toAbsoluteIndex$5(end, length); + while (endPos > index) O[index++] = value; + return O; + }; + + var global$s = global$O; + var uncurryThis$u = functionUncurryThis; + var DESCRIPTORS$f = descriptors; + var NATIVE_ARRAY_BUFFER$2 = arrayBufferBasicDetection; + var FunctionName = functionName; + var createNonEnumerableProperty$3 = createNonEnumerableProperty$a; + var defineBuiltInAccessor$8 = defineBuiltInAccessor$b; + var defineBuiltIns$4 = defineBuiltIns$5; + var fails$y = fails$_; + var anInstance$7 = anInstance$8; + var toIntegerOrInfinity$4 = toIntegerOrInfinity$a; + var toLength$8 = toLength$c; + var toIndex$1 = toIndex$2; + var fround = mathFround; + var IEEE754 = ieee754; + var getPrototypeOf$3 = objectGetPrototypeOf$1; + var setPrototypeOf$4 = objectSetPrototypeOf; + var getOwnPropertyNames$3 = objectGetOwnPropertyNames.f; + var arrayFill = arrayFill$1; + var arraySlice$7 = arraySliceSimple; + var setToStringTag$7 = setToStringTag$b; + var InternalStateModule$7 = internalState; + + var PROPER_FUNCTION_NAME = FunctionName.PROPER; + var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE; + var ARRAY_BUFFER$1 = 'ArrayBuffer'; + var DATA_VIEW = 'DataView'; + var PROTOTYPE = 'prototype'; + var WRONG_LENGTH$1 = 'Wrong length'; + var WRONG_INDEX = 'Wrong index'; + var getInternalArrayBufferState = InternalStateModule$7.getterFor(ARRAY_BUFFER$1); + var getInternalDataViewState = InternalStateModule$7.getterFor(DATA_VIEW); + var setInternalState$6 = InternalStateModule$7.set; + var NativeArrayBuffer$1 = global$s[ARRAY_BUFFER$1]; + var $ArrayBuffer = NativeArrayBuffer$1; + var ArrayBufferPrototype$1 = $ArrayBuffer && $ArrayBuffer[PROTOTYPE]; + var $DataView = global$s[DATA_VIEW]; + var DataViewPrototype$1 = $DataView && $DataView[PROTOTYPE]; + var ObjectPrototype$1 = Object.prototype; + var Array$1 = global$s.Array; + var RangeError$3 = global$s.RangeError; + var fill$1 = uncurryThis$u(arrayFill); + var reverse = uncurryThis$u([].reverse); + + var packIEEE754 = IEEE754.pack; + var unpackIEEE754 = IEEE754.unpack; + + var packInt8 = function (number) { + return [number & 0xFF]; + }; + + var packInt16 = function (number) { + return [number & 0xFF, number >> 8 & 0xFF]; + }; + + var packInt32 = function (number) { + return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF]; + }; + + var unpackInt32 = function (buffer) { + return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]; + }; + + var packFloat32 = function (number) { + return packIEEE754(fround(number), 23, 4); + }; + + var packFloat64 = function (number) { + return packIEEE754(number, 52, 8); + }; + + var addGetter$1 = function (Constructor, key, getInternalState) { + defineBuiltInAccessor$8(Constructor[PROTOTYPE], key, { + configurable: true, + get: function () { + return getInternalState(this)[key]; + } + }); + }; + + var get$1 = function (view, count, index, isLittleEndian) { + var store = getInternalDataViewState(view); + var intIndex = toIndex$1(index); + var boolIsLittleEndian = !!isLittleEndian; + if (intIndex + count > store.byteLength) throw new RangeError$3(WRONG_INDEX); + var bytes = store.bytes; + var start = intIndex + store.byteOffset; + var pack = arraySlice$7(bytes, start, start + count); + return boolIsLittleEndian ? pack : reverse(pack); + }; + + var set$1 = function (view, count, index, conversion, value, isLittleEndian) { + var store = getInternalDataViewState(view); + var intIndex = toIndex$1(index); + var pack = conversion(+value); + var boolIsLittleEndian = !!isLittleEndian; + if (intIndex + count > store.byteLength) throw new RangeError$3(WRONG_INDEX); + var bytes = store.bytes; + var start = intIndex + store.byteOffset; + for (var i = 0; i < count; i++) bytes[start + i] = pack[boolIsLittleEndian ? i : count - i - 1]; + }; + + if (!NATIVE_ARRAY_BUFFER$2) { + $ArrayBuffer = function ArrayBuffer(length) { + anInstance$7(this, ArrayBufferPrototype$1); + var byteLength = toIndex$1(length); + setInternalState$6(this, { + type: ARRAY_BUFFER$1, + bytes: fill$1(Array$1(byteLength), 0), + byteLength: byteLength + }); + if (!DESCRIPTORS$f) { + this.byteLength = byteLength; + this.detached = false; + } + }; + + ArrayBufferPrototype$1 = $ArrayBuffer[PROTOTYPE]; + + $DataView = function DataView(buffer, byteOffset, byteLength) { + anInstance$7(this, DataViewPrototype$1); + anInstance$7(buffer, ArrayBufferPrototype$1); + var bufferState = getInternalArrayBufferState(buffer); + var bufferLength = bufferState.byteLength; + var offset = toIntegerOrInfinity$4(byteOffset); + if (offset < 0 || offset > bufferLength) throw new RangeError$3('Wrong offset'); + byteLength = byteLength === undefined ? bufferLength - offset : toLength$8(byteLength); + if (offset + byteLength > bufferLength) throw new RangeError$3(WRONG_LENGTH$1); + setInternalState$6(this, { + type: DATA_VIEW, + buffer: buffer, + byteLength: byteLength, + byteOffset: offset, + bytes: bufferState.bytes + }); + if (!DESCRIPTORS$f) { + this.buffer = buffer; + this.byteLength = byteLength; + this.byteOffset = offset; + } + }; + + DataViewPrototype$1 = $DataView[PROTOTYPE]; + + if (DESCRIPTORS$f) { + addGetter$1($ArrayBuffer, 'byteLength', getInternalArrayBufferState); + addGetter$1($DataView, 'buffer', getInternalDataViewState); + addGetter$1($DataView, 'byteLength', getInternalDataViewState); + addGetter$1($DataView, 'byteOffset', getInternalDataViewState); + } + + defineBuiltIns$4(DataViewPrototype$1, { + getInt8: function getInt8(byteOffset) { + return get$1(this, 1, byteOffset)[0] << 24 >> 24; + }, + getUint8: function getUint8(byteOffset) { + return get$1(this, 1, byteOffset)[0]; + }, + getInt16: function getInt16(byteOffset /* , littleEndian */) { + var bytes = get$1(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false); + return (bytes[1] << 8 | bytes[0]) << 16 >> 16; + }, + getUint16: function getUint16(byteOffset /* , littleEndian */) { + var bytes = get$1(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false); + return bytes[1] << 8 | bytes[0]; + }, + getInt32: function getInt32(byteOffset /* , littleEndian */) { + return unpackInt32(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false)); + }, + getUint32: function getUint32(byteOffset /* , littleEndian */) { + return unpackInt32(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false)) >>> 0; + }, + getFloat32: function getFloat32(byteOffset /* , littleEndian */) { + return unpackIEEE754(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false), 23); + }, + getFloat64: function getFloat64(byteOffset /* , littleEndian */) { + return unpackIEEE754(get$1(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : false), 52); + }, + setInt8: function setInt8(byteOffset, value) { + set$1(this, 1, byteOffset, packInt8, value); + }, + setUint8: function setUint8(byteOffset, value) { + set$1(this, 1, byteOffset, packInt8, value); + }, + setInt16: function setInt16(byteOffset, value /* , littleEndian */) { + set$1(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false); + }, + setUint16: function setUint16(byteOffset, value /* , littleEndian */) { + set$1(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false); + }, + setInt32: function setInt32(byteOffset, value /* , littleEndian */) { + set$1(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false); + }, + setUint32: function setUint32(byteOffset, value /* , littleEndian */) { + set$1(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false); + }, + setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) { + set$1(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : false); + }, + setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) { + set$1(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : false); + } + }); + } else { + var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME && NativeArrayBuffer$1.name !== ARRAY_BUFFER$1; + /* eslint-disable no-new -- required for testing */ + if (!fails$y(function () { + NativeArrayBuffer$1(1); + }) || !fails$y(function () { + new NativeArrayBuffer$1(-1); + }) || fails$y(function () { + new NativeArrayBuffer$1(); + new NativeArrayBuffer$1(1.5); + new NativeArrayBuffer$1(NaN); + return NativeArrayBuffer$1.length !== 1 || INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME; + })) { + /* eslint-enable no-new -- required for testing */ + $ArrayBuffer = function ArrayBuffer(length) { + anInstance$7(this, ArrayBufferPrototype$1); + return new NativeArrayBuffer$1(toIndex$1(length)); + }; + + $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype$1; + + for (var keys$1 = getOwnPropertyNames$3(NativeArrayBuffer$1), j = 0, key; keys$1.length > j;) { + if (!((key = keys$1[j++]) in $ArrayBuffer)) { + createNonEnumerableProperty$3($ArrayBuffer, key, NativeArrayBuffer$1[key]); + } + } + + ArrayBufferPrototype$1.constructor = $ArrayBuffer; + } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) { + createNonEnumerableProperty$3(NativeArrayBuffer$1, 'name', ARRAY_BUFFER$1); + } + + // WebKit bug - the same parent prototype for typed arrays and data view + if (setPrototypeOf$4 && getPrototypeOf$3(DataViewPrototype$1) !== ObjectPrototype$1) { + setPrototypeOf$4(DataViewPrototype$1, ObjectPrototype$1); + } + + // iOS Safari 7.x bug + var testView = new $DataView(new $ArrayBuffer(2)); + var $setInt8 = uncurryThis$u(DataViewPrototype$1.setInt8); + testView.setInt8(0, 2147483648); + testView.setInt8(1, 2147483649); + if (testView.getInt8(0) || !testView.getInt8(1)) defineBuiltIns$4(DataViewPrototype$1, { + setInt8: function setInt8(byteOffset, value) { + $setInt8(this, byteOffset, value << 24 >> 24); + }, + setUint8: function setUint8(byteOffset, value) { + $setInt8(this, byteOffset, value << 24 >> 24); + } + }, { unsafe: true }); + } + + setToStringTag$7($ArrayBuffer, ARRAY_BUFFER$1); + setToStringTag$7($DataView, DATA_VIEW); + + var arrayBuffer = { + ArrayBuffer: $ArrayBuffer, + DataView: $DataView + }; + + var anObject$c = anObject$p; + var aConstructor$1 = aConstructor$3; + var isNullOrUndefined$7 = isNullOrUndefined$c; + var wellKnownSymbol$f = wellKnownSymbol$x; + + var SPECIES$4 = wellKnownSymbol$f('species'); + + // `SpeciesConstructor` abstract operation + // https://tc39.es/ecma262/#sec-speciesconstructor + var speciesConstructor$4 = function (O, defaultConstructor) { + var C = anObject$c(O).constructor; + var S; + return C === undefined || isNullOrUndefined$7(S = anObject$c(C)[SPECIES$4]) ? defaultConstructor : aConstructor$1(S); + }; + + var $$X = _export; + var uncurryThis$t = functionUncurryThisClause; + var fails$x = fails$_; + var ArrayBufferModule$2 = arrayBuffer; + var anObject$b = anObject$p; + var toAbsoluteIndex$4 = toAbsoluteIndex$8; + var toLength$7 = toLength$c; + var speciesConstructor$3 = speciesConstructor$4; + + var ArrayBuffer$4 = ArrayBufferModule$2.ArrayBuffer; + var DataView$2 = ArrayBufferModule$2.DataView; + var DataViewPrototype = DataView$2.prototype; + var nativeArrayBufferSlice = uncurryThis$t(ArrayBuffer$4.prototype.slice); + var getUint8 = uncurryThis$t(DataViewPrototype.getUint8); + var setUint8 = uncurryThis$t(DataViewPrototype.setUint8); + + var INCORRECT_SLICE = fails$x(function () { + return !new ArrayBuffer$4(2).slice(1, undefined).byteLength; + }); + + // `ArrayBuffer.prototype.slice` method + // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice + $$X({ target: 'ArrayBuffer', proto: true, unsafe: true, forced: INCORRECT_SLICE }, { + slice: function slice(start, end) { + if (nativeArrayBufferSlice && end === undefined) { + return nativeArrayBufferSlice(anObject$b(this), start); // FF fix + } + var length = anObject$b(this).byteLength; + var first = toAbsoluteIndex$4(start, length); + var fin = toAbsoluteIndex$4(end === undefined ? length : end, length); + var result = new (speciesConstructor$3(this, ArrayBuffer$4))(toLength$7(fin - first)); + var viewSource = new DataView$2(this); + var viewTarget = new DataView$2(result); + var index = 0; + while (first < fin) { + setUint8(viewTarget, index++, getUint8(viewSource, first++)); + } return result; + } + }); + + var typedArrayConstructor = {exports: {}}; + + var wellKnownSymbol$e = wellKnownSymbol$x; + + var ITERATOR$7 = wellKnownSymbol$e('iterator'); + var SAFE_CLOSING = false; + + try { + var called = 0; + var iteratorWithReturn = { + next: function () { + return { done: !!called++ }; + }, + 'return': function () { + SAFE_CLOSING = true; + } + }; + iteratorWithReturn[ITERATOR$7] = function () { + return this; + }; + // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing + Array.from(iteratorWithReturn, function () { throw 2; }); + } catch (error) { /* empty */ } + + var checkCorrectnessOfIteration$4 = function (exec, SKIP_CLOSING) { + try { + if (!SKIP_CLOSING && !SAFE_CLOSING) return false; + } catch (error) { return false; } // workaround of old WebKit + `eval` bug + var ITERATION_SUPPORT = false; + try { + var object = {}; + object[ITERATOR$7] = function () { + return { + next: function () { + return { done: ITERATION_SUPPORT = true }; + } + }; + }; + exec(object); + } catch (error) { /* empty */ } + return ITERATION_SUPPORT; + }; + + var NATIVE_ARRAY_BUFFER$1 = arrayBufferBasicDetection; + var DESCRIPTORS$e = descriptors; + var global$r = global$O; + var isCallable$8 = isCallable$w; + var isObject$h = isObject$t; + var hasOwn$8 = hasOwnProperty_1; + var classof$8 = classof$i; + var tryToString$3 = tryToString$7; + var createNonEnumerableProperty$2 = createNonEnumerableProperty$a; + var defineBuiltIn$6 = defineBuiltIn$i; + var defineBuiltInAccessor$7 = defineBuiltInAccessor$b; + var isPrototypeOf$3 = objectIsPrototypeOf; + var getPrototypeOf$2 = objectGetPrototypeOf$1; + var setPrototypeOf$3 = objectSetPrototypeOf; + var wellKnownSymbol$d = wellKnownSymbol$x; + var uid$1 = uid$5; + var InternalStateModule$6 = internalState; + + var enforceInternalState$3 = InternalStateModule$6.enforce; + var getInternalState$1 = InternalStateModule$6.get; + var Int8Array$4 = global$r.Int8Array; + var Int8ArrayPrototype$1 = Int8Array$4 && Int8Array$4.prototype; + var Uint8ClampedArray$1 = global$r.Uint8ClampedArray; + var Uint8ClampedArrayPrototype = Uint8ClampedArray$1 && Uint8ClampedArray$1.prototype; + var TypedArray$1 = Int8Array$4 && getPrototypeOf$2(Int8Array$4); + var TypedArrayPrototype$2 = Int8ArrayPrototype$1 && getPrototypeOf$2(Int8ArrayPrototype$1); + var ObjectPrototype = Object.prototype; + var TypeError$4 = global$r.TypeError; + + var TO_STRING_TAG = wellKnownSymbol$d('toStringTag'); + var TYPED_ARRAY_TAG$1 = uid$1('TYPED_ARRAY_TAG'); + var TYPED_ARRAY_CONSTRUCTOR = 'TypedArrayConstructor'; + // Fixing native typed arrays in Opera Presto crashes the browser, see #595 + var NATIVE_ARRAY_BUFFER_VIEWS$2 = NATIVE_ARRAY_BUFFER$1 && !!setPrototypeOf$3 && classof$8(global$r.opera) !== 'Opera'; + var TYPED_ARRAY_TAG_REQUIRED = false; + var NAME$1, Constructor, Prototype; + + var TypedArrayConstructorsList = { + Int8Array: 1, + Uint8Array: 1, + Uint8ClampedArray: 1, + Int16Array: 2, + Uint16Array: 2, + Int32Array: 4, + Uint32Array: 4, + Float32Array: 4, + Float64Array: 8 + }; + + var BigIntArrayConstructorsList = { + BigInt64Array: 8, + BigUint64Array: 8 + }; + + var isView = function isView(it) { + if (!isObject$h(it)) return false; + var klass = classof$8(it); + return klass === 'DataView' + || hasOwn$8(TypedArrayConstructorsList, klass) + || hasOwn$8(BigIntArrayConstructorsList, klass); + }; + + var getTypedArrayConstructor$1 = function (it) { + var proto = getPrototypeOf$2(it); + if (!isObject$h(proto)) return; + var state = getInternalState$1(proto); + return (state && hasOwn$8(state, TYPED_ARRAY_CONSTRUCTOR)) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor$1(proto); + }; + + var isTypedArray$1 = function (it) { + if (!isObject$h(it)) return false; + var klass = classof$8(it); + return hasOwn$8(TypedArrayConstructorsList, klass) + || hasOwn$8(BigIntArrayConstructorsList, klass); + }; + + var aTypedArray$m = function (it) { + if (isTypedArray$1(it)) return it; + throw new TypeError$4('Target is not a typed array'); + }; + + var aTypedArrayConstructor$3 = function (C) { + if (isCallable$8(C) && (!setPrototypeOf$3 || isPrototypeOf$3(TypedArray$1, C))) return C; + throw new TypeError$4(tryToString$3(C) + ' is not a typed array constructor'); + }; + + var exportTypedArrayMethod$n = function (KEY, property, forced, options) { + if (!DESCRIPTORS$e) return; + if (forced) for (var ARRAY in TypedArrayConstructorsList) { + var TypedArrayConstructor = global$r[ARRAY]; + if (TypedArrayConstructor && hasOwn$8(TypedArrayConstructor.prototype, KEY)) try { + delete TypedArrayConstructor.prototype[KEY]; + } catch (error) { + // old WebKit bug - some methods are non-configurable + try { + TypedArrayConstructor.prototype[KEY] = property; + } catch (error2) { /* empty */ } + } + } + if (!TypedArrayPrototype$2[KEY] || forced) { + defineBuiltIn$6(TypedArrayPrototype$2, KEY, forced ? property + : NATIVE_ARRAY_BUFFER_VIEWS$2 && Int8ArrayPrototype$1[KEY] || property, options); + } + }; + + var exportTypedArrayStaticMethod = function (KEY, property, forced) { + var ARRAY, TypedArrayConstructor; + if (!DESCRIPTORS$e) return; + if (setPrototypeOf$3) { + if (forced) for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = global$r[ARRAY]; + if (TypedArrayConstructor && hasOwn$8(TypedArrayConstructor, KEY)) try { + delete TypedArrayConstructor[KEY]; + } catch (error) { /* empty */ } + } + if (!TypedArray$1[KEY] || forced) { + // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable + try { + return defineBuiltIn$6(TypedArray$1, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS$2 && TypedArray$1[KEY] || property); + } catch (error) { /* empty */ } + } else return; + } + for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = global$r[ARRAY]; + if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) { + defineBuiltIn$6(TypedArrayConstructor, KEY, property); + } + } + }; + + for (NAME$1 in TypedArrayConstructorsList) { + Constructor = global$r[NAME$1]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState$3(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + else NATIVE_ARRAY_BUFFER_VIEWS$2 = false; + } + + for (NAME$1 in BigIntArrayConstructorsList) { + Constructor = global$r[NAME$1]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState$3(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + } + + // WebKit bug - typed arrays constructors prototype is Object.prototype + if (!NATIVE_ARRAY_BUFFER_VIEWS$2 || !isCallable$8(TypedArray$1) || TypedArray$1 === Function.prototype) { + // eslint-disable-next-line no-shadow -- safe + TypedArray$1 = function TypedArray() { + throw new TypeError$4('Incorrect invocation'); + }; + if (NATIVE_ARRAY_BUFFER_VIEWS$2) for (NAME$1 in TypedArrayConstructorsList) { + if (global$r[NAME$1]) setPrototypeOf$3(global$r[NAME$1], TypedArray$1); + } + } + + if (!NATIVE_ARRAY_BUFFER_VIEWS$2 || !TypedArrayPrototype$2 || TypedArrayPrototype$2 === ObjectPrototype) { + TypedArrayPrototype$2 = TypedArray$1.prototype; + if (NATIVE_ARRAY_BUFFER_VIEWS$2) for (NAME$1 in TypedArrayConstructorsList) { + if (global$r[NAME$1]) setPrototypeOf$3(global$r[NAME$1].prototype, TypedArrayPrototype$2); + } + } + + // WebKit bug - one more object in Uint8ClampedArray prototype chain + if (NATIVE_ARRAY_BUFFER_VIEWS$2 && getPrototypeOf$2(Uint8ClampedArrayPrototype) !== TypedArrayPrototype$2) { + setPrototypeOf$3(Uint8ClampedArrayPrototype, TypedArrayPrototype$2); + } + + if (DESCRIPTORS$e && !hasOwn$8(TypedArrayPrototype$2, TO_STRING_TAG)) { + TYPED_ARRAY_TAG_REQUIRED = true; + defineBuiltInAccessor$7(TypedArrayPrototype$2, TO_STRING_TAG, { + configurable: true, + get: function () { + return isObject$h(this) ? this[TYPED_ARRAY_TAG$1] : undefined; + } + }); + for (NAME$1 in TypedArrayConstructorsList) if (global$r[NAME$1]) { + createNonEnumerableProperty$2(global$r[NAME$1], TYPED_ARRAY_TAG$1, NAME$1); + } + } + + var arrayBufferViewCore = { + NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS$2, + TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG$1, + aTypedArray: aTypedArray$m, + aTypedArrayConstructor: aTypedArrayConstructor$3, + exportTypedArrayMethod: exportTypedArrayMethod$n, + exportTypedArrayStaticMethod: exportTypedArrayStaticMethod, + getTypedArrayConstructor: getTypedArrayConstructor$1, + isView: isView, + isTypedArray: isTypedArray$1, + TypedArray: TypedArray$1, + TypedArrayPrototype: TypedArrayPrototype$2 + }; + + /* eslint-disable no-new -- required for testing */ + var global$q = global$O; + var fails$w = fails$_; + var checkCorrectnessOfIteration$3 = checkCorrectnessOfIteration$4; + var NATIVE_ARRAY_BUFFER_VIEWS$1 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS; + + var ArrayBuffer$3 = global$q.ArrayBuffer; + var Int8Array$3 = global$q.Int8Array; + + var typedArrayConstructorsRequireWrappers = !NATIVE_ARRAY_BUFFER_VIEWS$1 || !fails$w(function () { + Int8Array$3(1); + }) || !fails$w(function () { + new Int8Array$3(-1); + }) || !checkCorrectnessOfIteration$3(function (iterable) { + new Int8Array$3(); + new Int8Array$3(null); + new Int8Array$3(1.5); + new Int8Array$3(iterable); + }, true) || fails$w(function () { + // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill + return new Int8Array$3(new ArrayBuffer$3(2), 1, undefined).length !== 1; + }); + + var isObject$g = isObject$t; + + var floor$4 = Math.floor; + + // `IsIntegralNumber` abstract operation + // https://tc39.es/ecma262/#sec-isintegralnumber + // eslint-disable-next-line es/no-number-isinteger -- safe + var isIntegralNumber$1 = Number.isInteger || function isInteger(it) { + return !isObject$g(it) && isFinite(it) && floor$4(it) === it; + }; + + var toIntegerOrInfinity$3 = toIntegerOrInfinity$a; + + var $RangeError$4 = RangeError; + + var toPositiveInteger$1 = function (it) { + var result = toIntegerOrInfinity$3(it); + if (result < 0) throw new $RangeError$4("The argument can't be less than 0"); + return result; + }; + + var toPositiveInteger = toPositiveInteger$1; + + var $RangeError$3 = RangeError; + + var toOffset$2 = function (it, BYTES) { + var offset = toPositiveInteger(it); + if (offset % BYTES) throw new $RangeError$3('Wrong offset'); + return offset; + }; + + var round = Math.round; + + var toUint8Clamped$1 = function (it) { + var value = round(it); + return value < 0 ? 0 : value > 0xFF ? 0xFF : value & 0xFF; + }; + + var classof$7 = classof$i; + var getMethod$4 = getMethod$8; + var isNullOrUndefined$6 = isNullOrUndefined$c; + var Iterators$1 = iterators; + var wellKnownSymbol$c = wellKnownSymbol$x; + + var ITERATOR$6 = wellKnownSymbol$c('iterator'); + + var getIteratorMethod$5 = function (it) { + if (!isNullOrUndefined$6(it)) return getMethod$4(it, ITERATOR$6) + || getMethod$4(it, '@@iterator') + || Iterators$1[classof$7(it)]; + }; + + var call$h = functionCall; + var aCallable$6 = aCallable$c; + var anObject$a = anObject$p; + var tryToString$2 = tryToString$7; + var getIteratorMethod$4 = getIteratorMethod$5; + + var $TypeError$8 = TypeError; + + var getIterator$4 = function (argument, usingIterator) { + var iteratorMethod = arguments.length < 2 ? getIteratorMethod$4(argument) : usingIterator; + if (aCallable$6(iteratorMethod)) return anObject$a(call$h(iteratorMethod, argument)); + throw new $TypeError$8(tryToString$2(argument) + ' is not iterable'); + }; + + var wellKnownSymbol$b = wellKnownSymbol$x; + var Iterators = iterators; + + var ITERATOR$5 = wellKnownSymbol$b('iterator'); + var ArrayPrototype = Array.prototype; + + // check on default Array iterator + var isArrayIteratorMethod$3 = function (it) { + return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR$5] === it); + }; + + var classof$6 = classof$i; + + var isBigIntArray$1 = function (it) { + var klass = classof$6(it); + return klass === 'BigInt64Array' || klass === 'BigUint64Array'; + }; + + var toPrimitive$1 = toPrimitive$4; + + var $TypeError$7 = TypeError; + + // `ToBigInt` abstract operation + // https://tc39.es/ecma262/#sec-tobigint + var toBigInt$2 = function (argument) { + var prim = toPrimitive$1(argument, 'number'); + if (typeof prim == 'number') throw new $TypeError$7("Can't convert number to bigint"); + // eslint-disable-next-line es/no-bigint -- safe + return BigInt(prim); + }; + + var bind$9 = functionBindContext; + var call$g = functionCall; + var aConstructor = aConstructor$3; + var toObject$7 = toObject$h; + var lengthOfArrayLike$a = lengthOfArrayLike$g; + var getIterator$3 = getIterator$4; + var getIteratorMethod$3 = getIteratorMethod$5; + var isArrayIteratorMethod$2 = isArrayIteratorMethod$3; + var isBigIntArray = isBigIntArray$1; + var aTypedArrayConstructor$2 = arrayBufferViewCore.aTypedArrayConstructor; + var toBigInt$1 = toBigInt$2; + + var typedArrayFrom$1 = function from(source /* , mapfn, thisArg */) { + var C = aConstructor(this); + var O = toObject$7(source); + var argumentsLength = arguments.length; + var mapfn = argumentsLength > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; + var iteratorMethod = getIteratorMethod$3(O); + var i, length, result, thisIsBigIntArray, value, step, iterator, next; + if (iteratorMethod && !isArrayIteratorMethod$2(iteratorMethod)) { + iterator = getIterator$3(O, iteratorMethod); + next = iterator.next; + O = []; + while (!(step = call$g(next, iterator)).done) { + O.push(step.value); + } + } + if (mapping && argumentsLength > 2) { + mapfn = bind$9(mapfn, arguments[2]); + } + length = lengthOfArrayLike$a(O); + result = new (aTypedArrayConstructor$2(C))(length); + thisIsBigIntArray = isBigIntArray(result); + for (i = 0; length > i; i++) { + value = mapping ? mapfn(O[i], i) : O[i]; + // FF30- typed arrays doesn't properly convert objects to typed array values + result[i] = thisIsBigIntArray ? toBigInt$1(value) : +value; + } + return result; + }; + + var getBuiltIn$3 = getBuiltIn$c; + var defineBuiltInAccessor$6 = defineBuiltInAccessor$b; + var wellKnownSymbol$a = wellKnownSymbol$x; + var DESCRIPTORS$d = descriptors; + + var SPECIES$3 = wellKnownSymbol$a('species'); + + var setSpecies$5 = function (CONSTRUCTOR_NAME) { + var Constructor = getBuiltIn$3(CONSTRUCTOR_NAME); + + if (DESCRIPTORS$d && Constructor && !Constructor[SPECIES$3]) { + defineBuiltInAccessor$6(Constructor, SPECIES$3, { + configurable: true, + get: function () { return this; } + }); + } + }; + + var $$W = _export; + var global$p = global$O; + var call$f = functionCall; + var DESCRIPTORS$c = descriptors; + var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = typedArrayConstructorsRequireWrappers; + var ArrayBufferViewCore$n = arrayBufferViewCore; + var ArrayBufferModule$1 = arrayBuffer; + var anInstance$6 = anInstance$8; + var createPropertyDescriptor$1 = createPropertyDescriptor$7; + var createNonEnumerableProperty$1 = createNonEnumerableProperty$a; + var isIntegralNumber = isIntegralNumber$1; + var toLength$6 = toLength$c; + var toIndex = toIndex$2; + var toOffset$1 = toOffset$2; + var toUint8Clamped = toUint8Clamped$1; + var toPropertyKey = toPropertyKey$5; + var hasOwn$7 = hasOwnProperty_1; + var classof$5 = classof$i; + var isObject$f = isObject$t; + var isSymbol = isSymbol$6; + var create$3 = objectCreate; + var isPrototypeOf$2 = objectIsPrototypeOf; + var setPrototypeOf$2 = objectSetPrototypeOf; + var getOwnPropertyNames$2 = objectGetOwnPropertyNames.f; + var typedArrayFrom = typedArrayFrom$1; + var forEach = arrayIteration.forEach; + var setSpecies$4 = setSpecies$5; + var defineBuiltInAccessor$5 = defineBuiltInAccessor$b; + var definePropertyModule$1 = objectDefineProperty; + var getOwnPropertyDescriptorModule$2 = objectGetOwnPropertyDescriptor; + var InternalStateModule$5 = internalState; + var inheritIfRequired$2 = inheritIfRequired$4; + + var getInternalState = InternalStateModule$5.get; + var setInternalState$5 = InternalStateModule$5.set; + var enforceInternalState$2 = InternalStateModule$5.enforce; + var nativeDefineProperty = definePropertyModule$1.f; + var nativeGetOwnPropertyDescriptor = getOwnPropertyDescriptorModule$2.f; + var RangeError$2 = global$p.RangeError; + var ArrayBuffer$2 = ArrayBufferModule$1.ArrayBuffer; + var ArrayBufferPrototype = ArrayBuffer$2.prototype; + var DataView$1 = ArrayBufferModule$1.DataView; + var NATIVE_ARRAY_BUFFER_VIEWS = ArrayBufferViewCore$n.NATIVE_ARRAY_BUFFER_VIEWS; + var TYPED_ARRAY_TAG = ArrayBufferViewCore$n.TYPED_ARRAY_TAG; + var TypedArray = ArrayBufferViewCore$n.TypedArray; + var TypedArrayPrototype$1 = ArrayBufferViewCore$n.TypedArrayPrototype; + var aTypedArrayConstructor$1 = ArrayBufferViewCore$n.aTypedArrayConstructor; + var isTypedArray = ArrayBufferViewCore$n.isTypedArray; + var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT'; + var WRONG_LENGTH = 'Wrong length'; + + var fromList = function (C, list) { + aTypedArrayConstructor$1(C); + var index = 0; + var length = list.length; + var result = new C(length); + while (length > index) result[index] = list[index++]; + return result; + }; + + var addGetter = function (it, key) { + defineBuiltInAccessor$5(it, key, { + configurable: true, + get: function () { + return getInternalState(this)[key]; + } + }); + }; + + var isArrayBuffer = function (it) { + var klass; + return isPrototypeOf$2(ArrayBufferPrototype, it) || (klass = classof$5(it)) === 'ArrayBuffer' || klass === 'SharedArrayBuffer'; + }; + + var isTypedArrayIndex = function (target, key) { + return isTypedArray(target) + && !isSymbol(key) + && key in target + && isIntegralNumber(+key) + && key >= 0; + }; + + var wrappedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(target, key) { + key = toPropertyKey(key); + return isTypedArrayIndex(target, key) + ? createPropertyDescriptor$1(2, target[key]) + : nativeGetOwnPropertyDescriptor(target, key); + }; + + var wrappedDefineProperty = function defineProperty(target, key, descriptor) { + key = toPropertyKey(key); + if (isTypedArrayIndex(target, key) + && isObject$f(descriptor) + && hasOwn$7(descriptor, 'value') + && !hasOwn$7(descriptor, 'get') + && !hasOwn$7(descriptor, 'set') + // TODO: add validation descriptor w/o calling accessors + && !descriptor.configurable + && (!hasOwn$7(descriptor, 'writable') || descriptor.writable) + && (!hasOwn$7(descriptor, 'enumerable') || descriptor.enumerable) + ) { + target[key] = descriptor.value; + return target; + } return nativeDefineProperty(target, key, descriptor); + }; + + if (DESCRIPTORS$c) { + if (!NATIVE_ARRAY_BUFFER_VIEWS) { + getOwnPropertyDescriptorModule$2.f = wrappedGetOwnPropertyDescriptor; + definePropertyModule$1.f = wrappedDefineProperty; + addGetter(TypedArrayPrototype$1, 'buffer'); + addGetter(TypedArrayPrototype$1, 'byteOffset'); + addGetter(TypedArrayPrototype$1, 'byteLength'); + addGetter(TypedArrayPrototype$1, 'length'); + } + + $$W({ target: 'Object', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS }, { + getOwnPropertyDescriptor: wrappedGetOwnPropertyDescriptor, + defineProperty: wrappedDefineProperty + }); + + typedArrayConstructor.exports = function (TYPE, wrapper, CLAMPED) { + var BYTES = TYPE.match(/\d+/)[0] / 8; + var CONSTRUCTOR_NAME = TYPE + (CLAMPED ? 'Clamped' : '') + 'Array'; + var GETTER = 'get' + TYPE; + var SETTER = 'set' + TYPE; + var NativeTypedArrayConstructor = global$p[CONSTRUCTOR_NAME]; + var TypedArrayConstructor = NativeTypedArrayConstructor; + var TypedArrayConstructorPrototype = TypedArrayConstructor && TypedArrayConstructor.prototype; + var exported = {}; + + var getter = function (that, index) { + var data = getInternalState(that); + return data.view[GETTER](index * BYTES + data.byteOffset, true); + }; + + var setter = function (that, index, value) { + var data = getInternalState(that); + data.view[SETTER](index * BYTES + data.byteOffset, CLAMPED ? toUint8Clamped(value) : value, true); + }; + + var addElement = function (that, index) { + nativeDefineProperty(that, index, { + get: function () { + return getter(this, index); + }, + set: function (value) { + return setter(this, index, value); + }, + enumerable: true + }); + }; + + if (!NATIVE_ARRAY_BUFFER_VIEWS) { + TypedArrayConstructor = wrapper(function (that, data, offset, $length) { + anInstance$6(that, TypedArrayConstructorPrototype); + var index = 0; + var byteOffset = 0; + var buffer, byteLength, length; + if (!isObject$f(data)) { + length = toIndex(data); + byteLength = length * BYTES; + buffer = new ArrayBuffer$2(byteLength); + } else if (isArrayBuffer(data)) { + buffer = data; + byteOffset = toOffset$1(offset, BYTES); + var $len = data.byteLength; + if ($length === undefined) { + if ($len % BYTES) throw new RangeError$2(WRONG_LENGTH); + byteLength = $len - byteOffset; + if (byteLength < 0) throw new RangeError$2(WRONG_LENGTH); + } else { + byteLength = toLength$6($length) * BYTES; + if (byteLength + byteOffset > $len) throw new RangeError$2(WRONG_LENGTH); + } + length = byteLength / BYTES; + } else if (isTypedArray(data)) { + return fromList(TypedArrayConstructor, data); + } else { + return call$f(typedArrayFrom, TypedArrayConstructor, data); + } + setInternalState$5(that, { + buffer: buffer, + byteOffset: byteOffset, + byteLength: byteLength, + length: length, + view: new DataView$1(buffer) + }); + while (index < length) addElement(that, index++); + }); + + if (setPrototypeOf$2) setPrototypeOf$2(TypedArrayConstructor, TypedArray); + TypedArrayConstructorPrototype = TypedArrayConstructor.prototype = create$3(TypedArrayPrototype$1); + } else if (TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS) { + TypedArrayConstructor = wrapper(function (dummy, data, typedArrayOffset, $length) { + anInstance$6(dummy, TypedArrayConstructorPrototype); + return inheritIfRequired$2(function () { + if (!isObject$f(data)) return new NativeTypedArrayConstructor(toIndex(data)); + if (isArrayBuffer(data)) return $length !== undefined + ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES), $length) + : typedArrayOffset !== undefined + ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES)) + : new NativeTypedArrayConstructor(data); + if (isTypedArray(data)) return fromList(TypedArrayConstructor, data); + return call$f(typedArrayFrom, TypedArrayConstructor, data); + }(), dummy, TypedArrayConstructor); + }); + + if (setPrototypeOf$2) setPrototypeOf$2(TypedArrayConstructor, TypedArray); + forEach(getOwnPropertyNames$2(NativeTypedArrayConstructor), function (key) { + if (!(key in TypedArrayConstructor)) { + createNonEnumerableProperty$1(TypedArrayConstructor, key, NativeTypedArrayConstructor[key]); + } + }); + TypedArrayConstructor.prototype = TypedArrayConstructorPrototype; + } + + if (TypedArrayConstructorPrototype.constructor !== TypedArrayConstructor) { + createNonEnumerableProperty$1(TypedArrayConstructorPrototype, 'constructor', TypedArrayConstructor); + } + + enforceInternalState$2(TypedArrayConstructorPrototype).TypedArrayConstructor = TypedArrayConstructor; + + if (TYPED_ARRAY_TAG) { + createNonEnumerableProperty$1(TypedArrayConstructorPrototype, TYPED_ARRAY_TAG, CONSTRUCTOR_NAME); + } + + var FORCED = TypedArrayConstructor !== NativeTypedArrayConstructor; + + exported[CONSTRUCTOR_NAME] = TypedArrayConstructor; + + $$W({ global: true, constructor: true, forced: FORCED, sham: !NATIVE_ARRAY_BUFFER_VIEWS }, exported); + + if (!(BYTES_PER_ELEMENT in TypedArrayConstructor)) { + createNonEnumerableProperty$1(TypedArrayConstructor, BYTES_PER_ELEMENT, BYTES); + } + + if (!(BYTES_PER_ELEMENT in TypedArrayConstructorPrototype)) { + createNonEnumerableProperty$1(TypedArrayConstructorPrototype, BYTES_PER_ELEMENT, BYTES); + } + + setSpecies$4(CONSTRUCTOR_NAME); + }; + } else typedArrayConstructor.exports = function () { /* empty */ }; + + var typedArrayConstructorExports = typedArrayConstructor.exports; + + var createTypedArrayConstructor$8 = typedArrayConstructorExports; + + // `Uint8Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$8('Uint8', function (init) { + return function Uint8Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var tryToString$1 = tryToString$7; + + var $TypeError$6 = TypeError; + + var deletePropertyOrThrow$3 = function (O, P) { + if (!delete O[P]) throw new $TypeError$6('Cannot delete property ' + tryToString$1(P) + ' of ' + tryToString$1(O)); + }; + + var toObject$6 = toObject$h; + var toAbsoluteIndex$3 = toAbsoluteIndex$8; + var lengthOfArrayLike$9 = lengthOfArrayLike$g; + var deletePropertyOrThrow$2 = deletePropertyOrThrow$3; + + var min$5 = Math.min; + + // `Array.prototype.copyWithin` method implementation + // https://tc39.es/ecma262/#sec-array.prototype.copywithin + // eslint-disable-next-line es/no-array-prototype-copywithin -- safe + var arrayCopyWithin = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) { + var O = toObject$6(this); + var len = lengthOfArrayLike$9(O); + var to = toAbsoluteIndex$3(target, len); + var from = toAbsoluteIndex$3(start, len); + var end = arguments.length > 2 ? arguments[2] : undefined; + var count = min$5((end === undefined ? len : toAbsoluteIndex$3(end, len)) - from, len - to); + var inc = 1; + if (from < to && to < from + count) { + inc = -1; + from += count - 1; + to += count - 1; + } + while (count-- > 0) { + if (from in O) O[to] = O[from]; + else deletePropertyOrThrow$2(O, to); + to += inc; + from += inc; + } return O; + }; + + var uncurryThis$s = functionUncurryThis; + var ArrayBufferViewCore$m = arrayBufferViewCore; + var $ArrayCopyWithin = arrayCopyWithin; + + var u$ArrayCopyWithin = uncurryThis$s($ArrayCopyWithin); + var aTypedArray$l = ArrayBufferViewCore$m.aTypedArray; + var exportTypedArrayMethod$m = ArrayBufferViewCore$m.exportTypedArrayMethod; + + // `%TypedArray%.prototype.copyWithin` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin + exportTypedArrayMethod$m('copyWithin', function copyWithin(target, start /* , end */) { + return u$ArrayCopyWithin(aTypedArray$l(this), target, start, arguments.length > 2 ? arguments[2] : undefined); + }); + + var ArrayBufferViewCore$l = arrayBufferViewCore; + var $every$1 = arrayIteration.every; + + var aTypedArray$k = ArrayBufferViewCore$l.aTypedArray; + var exportTypedArrayMethod$l = ArrayBufferViewCore$l.exportTypedArrayMethod; + + // `%TypedArray%.prototype.every` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.every + exportTypedArrayMethod$l('every', function every(callbackfn /* , thisArg */) { + return $every$1(aTypedArray$k(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$k = arrayBufferViewCore; + var $fill = arrayFill$1; + var toBigInt = toBigInt$2; + var classof$4 = classof$i; + var call$e = functionCall; + var uncurryThis$r = functionUncurryThis; + var fails$v = fails$_; + + var aTypedArray$j = ArrayBufferViewCore$k.aTypedArray; + var exportTypedArrayMethod$k = ArrayBufferViewCore$k.exportTypedArrayMethod; + var slice$1 = uncurryThis$r(''.slice); + + // V8 ~ Chrome < 59, Safari < 14.1, FF < 55, Edge <=18 + var CONVERSION_BUG = fails$v(function () { + var count = 0; + // eslint-disable-next-line es/no-typed-arrays -- safe + new Int8Array(2).fill({ valueOf: function () { return count++; } }); + return count !== 1; + }); + + // `%TypedArray%.prototype.fill` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill + exportTypedArrayMethod$k('fill', function fill(value /* , start, end */) { + var length = arguments.length; + aTypedArray$j(this); + var actualValue = slice$1(classof$4(this), 0, 3) === 'Big' ? toBigInt(value) : +value; + return call$e($fill, this, actualValue, length > 1 ? arguments[1] : undefined, length > 2 ? arguments[2] : undefined); + }, CONVERSION_BUG); + + var lengthOfArrayLike$8 = lengthOfArrayLike$g; + + var arrayFromConstructorAndList$1 = function (Constructor, list) { + var index = 0; + var length = lengthOfArrayLike$8(list); + var result = new Constructor(length); + while (length > index) result[index] = list[index++]; + return result; + }; + + var ArrayBufferViewCore$j = arrayBufferViewCore; + var speciesConstructor$2 = speciesConstructor$4; + + var aTypedArrayConstructor = ArrayBufferViewCore$j.aTypedArrayConstructor; + var getTypedArrayConstructor = ArrayBufferViewCore$j.getTypedArrayConstructor; + + // a part of `TypedArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#typedarray-species-create + var typedArraySpeciesConstructor$4 = function (originalArray) { + return aTypedArrayConstructor(speciesConstructor$2(originalArray, getTypedArrayConstructor(originalArray))); + }; + + var arrayFromConstructorAndList = arrayFromConstructorAndList$1; + var typedArraySpeciesConstructor$3 = typedArraySpeciesConstructor$4; + + var typedArrayFromSpeciesAndList = function (instance, list) { + return arrayFromConstructorAndList(typedArraySpeciesConstructor$3(instance), list); + }; + + var ArrayBufferViewCore$i = arrayBufferViewCore; + var $filter$1 = arrayIteration.filter; + var fromSpeciesAndList = typedArrayFromSpeciesAndList; + + var aTypedArray$i = ArrayBufferViewCore$i.aTypedArray; + var exportTypedArrayMethod$j = ArrayBufferViewCore$i.exportTypedArrayMethod; + + // `%TypedArray%.prototype.filter` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter + exportTypedArrayMethod$j('filter', function filter(callbackfn /* , thisArg */) { + var list = $filter$1(aTypedArray$i(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + return fromSpeciesAndList(this, list); + }); + + var ArrayBufferViewCore$h = arrayBufferViewCore; + var $find$1 = arrayIteration.find; + + var aTypedArray$h = ArrayBufferViewCore$h.aTypedArray; + var exportTypedArrayMethod$i = ArrayBufferViewCore$h.exportTypedArrayMethod; + + // `%TypedArray%.prototype.find` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.find + exportTypedArrayMethod$i('find', function find(predicate /* , thisArg */) { + return $find$1(aTypedArray$h(this), predicate, arguments.length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$g = arrayBufferViewCore; + var $findIndex = arrayIteration.findIndex; + + var aTypedArray$g = ArrayBufferViewCore$g.aTypedArray; + var exportTypedArrayMethod$h = ArrayBufferViewCore$g.exportTypedArrayMethod; + + // `%TypedArray%.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex + exportTypedArrayMethod$h('findIndex', function findIndex(predicate /* , thisArg */) { + return $findIndex(aTypedArray$g(this), predicate, arguments.length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$f = arrayBufferViewCore; + var $forEach = arrayIteration.forEach; + + var aTypedArray$f = ArrayBufferViewCore$f.aTypedArray; + var exportTypedArrayMethod$g = ArrayBufferViewCore$f.exportTypedArrayMethod; + + // `%TypedArray%.prototype.forEach` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach + exportTypedArrayMethod$g('forEach', function forEach(callbackfn /* , thisArg */) { + $forEach(aTypedArray$f(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$e = arrayBufferViewCore; + var $includes$1 = arrayIncludes.includes; + + var aTypedArray$e = ArrayBufferViewCore$e.aTypedArray; + var exportTypedArrayMethod$f = ArrayBufferViewCore$e.exportTypedArrayMethod; + + // `%TypedArray%.prototype.includes` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes + exportTypedArrayMethod$f('includes', function includes(searchElement /* , fromIndex */) { + return $includes$1(aTypedArray$e(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$d = arrayBufferViewCore; + var $indexOf = arrayIncludes.indexOf; + + var aTypedArray$d = ArrayBufferViewCore$d.aTypedArray; + var exportTypedArrayMethod$e = ArrayBufferViewCore$d.exportTypedArrayMethod; + + // `%TypedArray%.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof + exportTypedArrayMethod$e('indexOf', function indexOf(searchElement /* , fromIndex */) { + return $indexOf(aTypedArray$d(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); + }); + + var global$o = global$O; + var fails$u = fails$_; + var uncurryThis$q = functionUncurryThis; + var ArrayBufferViewCore$c = arrayBufferViewCore; + var ArrayIterators = es_array_iterator; + var wellKnownSymbol$9 = wellKnownSymbol$x; + + var ITERATOR$4 = wellKnownSymbol$9('iterator'); + var Uint8Array$2 = global$o.Uint8Array; + var arrayValues = uncurryThis$q(ArrayIterators.values); + var arrayKeys = uncurryThis$q(ArrayIterators.keys); + var arrayEntries = uncurryThis$q(ArrayIterators.entries); + var aTypedArray$c = ArrayBufferViewCore$c.aTypedArray; + var exportTypedArrayMethod$d = ArrayBufferViewCore$c.exportTypedArrayMethod; + var TypedArrayPrototype = Uint8Array$2 && Uint8Array$2.prototype; + + var GENERIC = !fails$u(function () { + TypedArrayPrototype[ITERATOR$4].call([1]); + }); + + var ITERATOR_IS_VALUES = !!TypedArrayPrototype + && TypedArrayPrototype.values + && TypedArrayPrototype[ITERATOR$4] === TypedArrayPrototype.values + && TypedArrayPrototype.values.name === 'values'; + + var typedArrayValues = function values() { + return arrayValues(aTypedArray$c(this)); + }; + + // `%TypedArray%.prototype.entries` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries + exportTypedArrayMethod$d('entries', function entries() { + return arrayEntries(aTypedArray$c(this)); + }, GENERIC); + // `%TypedArray%.prototype.keys` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys + exportTypedArrayMethod$d('keys', function keys() { + return arrayKeys(aTypedArray$c(this)); + }, GENERIC); + // `%TypedArray%.prototype.values` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.values + exportTypedArrayMethod$d('values', typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' }); + // `%TypedArray%.prototype[@@iterator]` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator + exportTypedArrayMethod$d(ITERATOR$4, typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' }); + + var ArrayBufferViewCore$b = arrayBufferViewCore; + var uncurryThis$p = functionUncurryThis; + + var aTypedArray$b = ArrayBufferViewCore$b.aTypedArray; + var exportTypedArrayMethod$c = ArrayBufferViewCore$b.exportTypedArrayMethod; + var $join = uncurryThis$p([].join); + + // `%TypedArray%.prototype.join` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.join + exportTypedArrayMethod$c('join', function join(separator) { + return $join(aTypedArray$b(this), separator); + }); + + /* eslint-disable es/no-array-prototype-lastindexof -- safe */ + var apply$5 = functionApply; + var toIndexedObject$5 = toIndexedObject$e; + var toIntegerOrInfinity$2 = toIntegerOrInfinity$a; + var lengthOfArrayLike$7 = lengthOfArrayLike$g; + var arrayMethodIsStrict$4 = arrayMethodIsStrict$8; + + var min$4 = Math.min; + var $lastIndexOf$1 = [].lastIndexOf; + var NEGATIVE_ZERO = !!$lastIndexOf$1 && 1 / [1].lastIndexOf(1, -0) < 0; + var STRICT_METHOD$3 = arrayMethodIsStrict$4('lastIndexOf'); + var FORCED$b = NEGATIVE_ZERO || !STRICT_METHOD$3; + + // `Array.prototype.lastIndexOf` method implementation + // https://tc39.es/ecma262/#sec-array.prototype.lastindexof + var arrayLastIndexOf = FORCED$b ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) { + // convert -0 to +0 + if (NEGATIVE_ZERO) return apply$5($lastIndexOf$1, this, arguments) || 0; + var O = toIndexedObject$5(this); + var length = lengthOfArrayLike$7(O); + var index = length - 1; + if (arguments.length > 1) index = min$4(index, toIntegerOrInfinity$2(arguments[1])); + if (index < 0) index = length + index; + for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0; + return -1; + } : $lastIndexOf$1; + + var ArrayBufferViewCore$a = arrayBufferViewCore; + var apply$4 = functionApply; + var $lastIndexOf = arrayLastIndexOf; + + var aTypedArray$a = ArrayBufferViewCore$a.aTypedArray; + var exportTypedArrayMethod$b = ArrayBufferViewCore$a.exportTypedArrayMethod; + + // `%TypedArray%.prototype.lastIndexOf` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof + exportTypedArrayMethod$b('lastIndexOf', function lastIndexOf(searchElement /* , fromIndex */) { + var length = arguments.length; + return apply$4($lastIndexOf, aTypedArray$a(this), length > 1 ? [searchElement, arguments[1]] : [searchElement]); + }); + + var ArrayBufferViewCore$9 = arrayBufferViewCore; + var $map$1 = arrayIteration.map; + var typedArraySpeciesConstructor$2 = typedArraySpeciesConstructor$4; + + var aTypedArray$9 = ArrayBufferViewCore$9.aTypedArray; + var exportTypedArrayMethod$a = ArrayBufferViewCore$9.exportTypedArrayMethod; + + // `%TypedArray%.prototype.map` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.map + exportTypedArrayMethod$a('map', function map(mapfn /* , thisArg */) { + return $map$1(aTypedArray$9(this), mapfn, arguments.length > 1 ? arguments[1] : undefined, function (O, length) { + return new (typedArraySpeciesConstructor$2(O))(length); + }); + }); + + var ArrayBufferViewCore$8 = arrayBufferViewCore; + var $reduce = arrayReduce.left; + + var aTypedArray$8 = ArrayBufferViewCore$8.aTypedArray; + var exportTypedArrayMethod$9 = ArrayBufferViewCore$8.exportTypedArrayMethod; + + // `%TypedArray%.prototype.reduce` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce + exportTypedArrayMethod$9('reduce', function reduce(callbackfn /* , initialValue */) { + var length = arguments.length; + return $reduce(aTypedArray$8(this), callbackfn, length, length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$7 = arrayBufferViewCore; + var $reduceRight = arrayReduce.right; + + var aTypedArray$7 = ArrayBufferViewCore$7.aTypedArray; + var exportTypedArrayMethod$8 = ArrayBufferViewCore$7.exportTypedArrayMethod; + + // `%TypedArray%.prototype.reduceRight` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright + exportTypedArrayMethod$8('reduceRight', function reduceRight(callbackfn /* , initialValue */) { + var length = arguments.length; + return $reduceRight(aTypedArray$7(this), callbackfn, length, length > 1 ? arguments[1] : undefined); + }); + + var ArrayBufferViewCore$6 = arrayBufferViewCore; + + var aTypedArray$6 = ArrayBufferViewCore$6.aTypedArray; + var exportTypedArrayMethod$7 = ArrayBufferViewCore$6.exportTypedArrayMethod; + var floor$3 = Math.floor; + + // `%TypedArray%.prototype.reverse` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse + exportTypedArrayMethod$7('reverse', function reverse() { + var that = this; + var length = aTypedArray$6(that).length; + var middle = floor$3(length / 2); + var index = 0; + var value; + while (index < middle) { + value = that[index]; + that[index++] = that[--length]; + that[length] = value; + } return that; + }); + + var global$n = global$O; + var call$d = functionCall; + var ArrayBufferViewCore$5 = arrayBufferViewCore; + var lengthOfArrayLike$6 = lengthOfArrayLike$g; + var toOffset = toOffset$2; + var toIndexedObject$4 = toObject$h; + var fails$t = fails$_; + + var RangeError$1 = global$n.RangeError; + var Int8Array$2 = global$n.Int8Array; + var Int8ArrayPrototype = Int8Array$2 && Int8Array$2.prototype; + var $set = Int8ArrayPrototype && Int8ArrayPrototype.set; + var aTypedArray$5 = ArrayBufferViewCore$5.aTypedArray; + var exportTypedArrayMethod$6 = ArrayBufferViewCore$5.exportTypedArrayMethod; + + var WORKS_WITH_OBJECTS_AND_GENERIC_ON_TYPED_ARRAYS = !fails$t(function () { + // eslint-disable-next-line es/no-typed-arrays -- required for testing + var array = new Uint8ClampedArray(2); + call$d($set, array, { length: 1, 0: 3 }, 1); + return array[1] !== 3; + }); + + // https://bugs.chromium.org/p/v8/issues/detail?id=11294 and other + var TO_OBJECT_BUG = WORKS_WITH_OBJECTS_AND_GENERIC_ON_TYPED_ARRAYS && ArrayBufferViewCore$5.NATIVE_ARRAY_BUFFER_VIEWS && fails$t(function () { + var array = new Int8Array$2(2); + array.set(1); + array.set('2', 1); + return array[0] !== 0 || array[1] !== 2; + }); + + // `%TypedArray%.prototype.set` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set + exportTypedArrayMethod$6('set', function set(arrayLike /* , offset */) { + aTypedArray$5(this); + var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1); + var src = toIndexedObject$4(arrayLike); + if (WORKS_WITH_OBJECTS_AND_GENERIC_ON_TYPED_ARRAYS) return call$d($set, this, src, offset); + var length = this.length; + var len = lengthOfArrayLike$6(src); + var index = 0; + if (len + offset > length) throw new RangeError$1('Wrong length'); + while (index < len) this[offset + index] = src[index++]; + }, !WORKS_WITH_OBJECTS_AND_GENERIC_ON_TYPED_ARRAYS || TO_OBJECT_BUG); + + var ArrayBufferViewCore$4 = arrayBufferViewCore; + var typedArraySpeciesConstructor$1 = typedArraySpeciesConstructor$4; + var fails$s = fails$_; + var arraySlice$6 = arraySlice$a; + + var aTypedArray$4 = ArrayBufferViewCore$4.aTypedArray; + var exportTypedArrayMethod$5 = ArrayBufferViewCore$4.exportTypedArrayMethod; + + var FORCED$a = fails$s(function () { + // eslint-disable-next-line es/no-typed-arrays -- required for testing + new Int8Array(1).slice(); + }); + + // `%TypedArray%.prototype.slice` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice + exportTypedArrayMethod$5('slice', function slice(start, end) { + var list = arraySlice$6(aTypedArray$4(this), start, end); + var C = typedArraySpeciesConstructor$1(this); + var index = 0; + var length = list.length; + var result = new C(length); + while (length > index) result[index] = list[index++]; + return result; + }, FORCED$a); + + var ArrayBufferViewCore$3 = arrayBufferViewCore; + var $some$1 = arrayIteration.some; + + var aTypedArray$3 = ArrayBufferViewCore$3.aTypedArray; + var exportTypedArrayMethod$4 = ArrayBufferViewCore$3.exportTypedArrayMethod; + + // `%TypedArray%.prototype.some` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.some + exportTypedArrayMethod$4('some', function some(callbackfn /* , thisArg */) { + return $some$1(aTypedArray$3(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }); + + var arraySlice$5 = arraySliceSimple; + + var floor$2 = Math.floor; + + var mergeSort = function (array, comparefn) { + var length = array.length; + var middle = floor$2(length / 2); + return length < 8 ? insertionSort(array, comparefn) : merge( + array, + mergeSort(arraySlice$5(array, 0, middle), comparefn), + mergeSort(arraySlice$5(array, middle), comparefn), + comparefn + ); + }; + + var insertionSort = function (array, comparefn) { + var length = array.length; + var i = 1; + var element, j; + + while (i < length) { + j = i; + element = array[i]; + while (j && comparefn(array[j - 1], element) > 0) { + array[j] = array[--j]; + } + if (j !== i++) array[j] = element; + } return array; + }; + + var merge = function (array, left, right, comparefn) { + var llength = left.length; + var rlength = right.length; + var lindex = 0; + var rindex = 0; + + while (lindex < llength || rindex < rlength) { + array[lindex + rindex] = (lindex < llength && rindex < rlength) + ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++] + : lindex < llength ? left[lindex++] : right[rindex++]; + } return array; + }; + + var arraySort$1 = mergeSort; + + var userAgent$4 = engineUserAgent; + + var firefox = userAgent$4.match(/firefox\/(\d+)/i); + + var engineFfVersion = !!firefox && +firefox[1]; + + var UA = engineUserAgent; + + var engineIsIeOrEdge = /MSIE|Trident/.test(UA); + + var userAgent$3 = engineUserAgent; + + var webkit = userAgent$3.match(/AppleWebKit\/(\d+)\./); + + var engineWebkitVersion = !!webkit && +webkit[1]; + + var global$m = global$O; + var uncurryThis$o = functionUncurryThisClause; + var fails$r = fails$_; + var aCallable$5 = aCallable$c; + var internalSort$1 = arraySort$1; + var ArrayBufferViewCore$2 = arrayBufferViewCore; + var FF$1 = engineFfVersion; + var IE_OR_EDGE$1 = engineIsIeOrEdge; + var V8$1 = engineV8Version; + var WEBKIT$1 = engineWebkitVersion; + + var aTypedArray$2 = ArrayBufferViewCore$2.aTypedArray; + var exportTypedArrayMethod$3 = ArrayBufferViewCore$2.exportTypedArrayMethod; + var Uint16Array$1 = global$m.Uint16Array; + var nativeSort$1 = Uint16Array$1 && uncurryThis$o(Uint16Array$1.prototype.sort); + + // WebKit + var ACCEPT_INCORRECT_ARGUMENTS = !!nativeSort$1 && !(fails$r(function () { + nativeSort$1(new Uint16Array$1(2), null); + }) && fails$r(function () { + nativeSort$1(new Uint16Array$1(2), {}); + })); + + var STABLE_SORT$1 = !!nativeSort$1 && !fails$r(function () { + // feature detection can be too slow, so check engines versions + if (V8$1) return V8$1 < 74; + if (FF$1) return FF$1 < 67; + if (IE_OR_EDGE$1) return true; + if (WEBKIT$1) return WEBKIT$1 < 602; + + var array = new Uint16Array$1(516); + var expected = Array(516); + var index, mod; + + for (index = 0; index < 516; index++) { + mod = index % 4; + array[index] = 515 - index; + expected[index] = index - 2 * mod + 3; + } + + nativeSort$1(array, function (a, b) { + return (a / 4 | 0) - (b / 4 | 0); + }); + + for (index = 0; index < 516; index++) { + if (array[index] !== expected[index]) return true; + } + }); + + var getSortCompare$1 = function (comparefn) { + return function (x, y) { + if (comparefn !== undefined) return +comparefn(x, y) || 0; + // eslint-disable-next-line no-self-compare -- NaN check + if (y !== y) return -1; + // eslint-disable-next-line no-self-compare -- NaN check + if (x !== x) return 1; + if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1; + return x > y; + }; + }; + + // `%TypedArray%.prototype.sort` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort + exportTypedArrayMethod$3('sort', function sort(comparefn) { + if (comparefn !== undefined) aCallable$5(comparefn); + if (STABLE_SORT$1) return nativeSort$1(this, comparefn); + + return internalSort$1(aTypedArray$2(this), getSortCompare$1(comparefn)); + }, !STABLE_SORT$1 || ACCEPT_INCORRECT_ARGUMENTS); + + var ArrayBufferViewCore$1 = arrayBufferViewCore; + var toLength$5 = toLength$c; + var toAbsoluteIndex$2 = toAbsoluteIndex$8; + var typedArraySpeciesConstructor = typedArraySpeciesConstructor$4; + + var aTypedArray$1 = ArrayBufferViewCore$1.aTypedArray; + var exportTypedArrayMethod$2 = ArrayBufferViewCore$1.exportTypedArrayMethod; + + // `%TypedArray%.prototype.subarray` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray + exportTypedArrayMethod$2('subarray', function subarray(begin, end) { + var O = aTypedArray$1(this); + var length = O.length; + var beginIndex = toAbsoluteIndex$2(begin, length); + var C = typedArraySpeciesConstructor(O); + return new C( + O.buffer, + O.byteOffset + beginIndex * O.BYTES_PER_ELEMENT, + toLength$5((end === undefined ? length : toAbsoluteIndex$2(end, length)) - beginIndex) + ); + }); + + var global$l = global$O; + var apply$3 = functionApply; + var ArrayBufferViewCore = arrayBufferViewCore; + var fails$q = fails$_; + var arraySlice$4 = arraySlice$a; + + var Int8Array$1 = global$l.Int8Array; + var aTypedArray = ArrayBufferViewCore.aTypedArray; + var exportTypedArrayMethod$1 = ArrayBufferViewCore.exportTypedArrayMethod; + var $toLocaleString = [].toLocaleString; + + // iOS Safari 6.x fails here + var TO_LOCALE_STRING_BUG = !!Int8Array$1 && fails$q(function () { + $toLocaleString.call(new Int8Array$1(1)); + }); + + var FORCED$9 = fails$q(function () { + return [1, 2].toLocaleString() !== new Int8Array$1([1, 2]).toLocaleString(); + }) || !fails$q(function () { + Int8Array$1.prototype.toLocaleString.call([1, 2]); + }); + + // `%TypedArray%.prototype.toLocaleString` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring + exportTypedArrayMethod$1('toLocaleString', function toLocaleString() { + return apply$3( + $toLocaleString, + TO_LOCALE_STRING_BUG ? arraySlice$4(aTypedArray(this)) : aTypedArray(this), + arraySlice$4(arguments) + ); + }, FORCED$9); + + var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod; + var fails$p = fails$_; + var global$k = global$O; + var uncurryThis$n = functionUncurryThis; + + var Uint8Array$1 = global$k.Uint8Array; + var Uint8ArrayPrototype = Uint8Array$1 && Uint8Array$1.prototype || {}; + var arrayToString = [].toString; + var join$3 = uncurryThis$n([].join); + + if (fails$p(function () { arrayToString.call({}); })) { + arrayToString = function toString() { + return join$3(this); + }; + } + + var IS_NOT_ARRAY_METHOD = Uint8ArrayPrototype.toString !== arrayToString; + + // `%TypedArray%.prototype.toString` method + // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring + exportTypedArrayMethod('toString', arrayToString, IS_NOT_ARRAY_METHOD); + + var $TypeError$5 = TypeError; + var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991 + + var doesNotExceedSafeInteger$2 = function (it) { + if (it > MAX_SAFE_INTEGER) throw $TypeError$5('Maximum allowed index exceeded'); + return it; + }; + + var fails$o = fails$_; + var wellKnownSymbol$8 = wellKnownSymbol$x; + var V8_VERSION$2 = engineV8Version; + + var SPECIES$2 = wellKnownSymbol$8('species'); + + var arrayMethodHasSpeciesSupport$5 = function (METHOD_NAME) { + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/677 + return V8_VERSION$2 >= 51 || !fails$o(function () { + var array = []; + var constructor = array.constructor = {}; + constructor[SPECIES$2] = function () { + return { foo: 1 }; + }; + return array[METHOD_NAME](Boolean).foo !== 1; + }); + }; + + var $$V = _export; + var fails$n = fails$_; + var isArray$5 = isArray$8; + var isObject$e = isObject$t; + var toObject$5 = toObject$h; + var lengthOfArrayLike$5 = lengthOfArrayLike$g; + var doesNotExceedSafeInteger$1 = doesNotExceedSafeInteger$2; + var createProperty$4 = createProperty$6; + var arraySpeciesCreate$1 = arraySpeciesCreate$3; + var arrayMethodHasSpeciesSupport$4 = arrayMethodHasSpeciesSupport$5; + var wellKnownSymbol$7 = wellKnownSymbol$x; + var V8_VERSION$1 = engineV8Version; + + var IS_CONCAT_SPREADABLE = wellKnownSymbol$7('isConcatSpreadable'); + + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/679 + var IS_CONCAT_SPREADABLE_SUPPORT = V8_VERSION$1 >= 51 || !fails$n(function () { + var array = []; + array[IS_CONCAT_SPREADABLE] = false; + return array.concat()[0] !== array; + }); + + var isConcatSpreadable = function (O) { + if (!isObject$e(O)) return false; + var spreadable = O[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray$5(O); + }; + + var FORCED$8 = !IS_CONCAT_SPREADABLE_SUPPORT || !arrayMethodHasSpeciesSupport$4('concat'); + + // `Array.prototype.concat` method + // https://tc39.es/ecma262/#sec-array.prototype.concat + // with adding support of @@isConcatSpreadable and @@species + $$V({ target: 'Array', proto: true, arity: 1, forced: FORCED$8 }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + concat: function concat(arg) { + var O = toObject$5(this); + var A = arraySpeciesCreate$1(O, 0); + var n = 0; + var i, k, length, len, E; + for (i = -1, length = arguments.length; i < length; i++) { + E = i === -1 ? O : arguments[i]; + if (isConcatSpreadable(E)) { + len = lengthOfArrayLike$5(E); + doesNotExceedSafeInteger$1(n + len); + for (k = 0; k < len; k++, n++) if (k in E) createProperty$4(A, n, E[k]); + } else { + doesNotExceedSafeInteger$1(n + 1); + createProperty$4(A, n++, E); + } + } + A.length = n; + return A; + } + }); + + var global$j = global$O; + var fails$m = fails$_; + var uncurryThis$m = functionUncurryThis; + var toString$c = toString$n; + var trim$1 = stringTrim.trim; + var whitespaces$1 = whitespaces$4; + + var charAt$3 = uncurryThis$m(''.charAt); + var $parseFloat$1 = global$j.parseFloat; + var Symbol$2 = global$j.Symbol; + var ITERATOR$3 = Symbol$2 && Symbol$2.iterator; + var FORCED$7 = 1 / $parseFloat$1(whitespaces$1 + '-0') !== -Infinity + // MS Edge 18- broken with boxed symbols + || (ITERATOR$3 && !fails$m(function () { $parseFloat$1(Object(ITERATOR$3)); })); + + // `parseFloat` method + // https://tc39.es/ecma262/#sec-parsefloat-string + var numberParseFloat = FORCED$7 ? function parseFloat(string) { + var trimmedString = trim$1(toString$c(string)); + var result = $parseFloat$1(trimmedString); + return result === 0 && charAt$3(trimmedString, 0) === '-' ? -0 : result; + } : $parseFloat$1; + + var $$U = _export; + var $parseFloat = numberParseFloat; + + // `parseFloat` method + // https://tc39.es/ecma262/#sec-parsefloat-string + $$U({ global: true, forced: parseFloat !== $parseFloat }, { + parseFloat: $parseFloat + }); + + var $$T = _export; + var isArray$4 = isArray$8; + var isConstructor$1 = isConstructor$4; + var isObject$d = isObject$t; + var toAbsoluteIndex$1 = toAbsoluteIndex$8; + var lengthOfArrayLike$4 = lengthOfArrayLike$g; + var toIndexedObject$3 = toIndexedObject$e; + var createProperty$3 = createProperty$6; + var wellKnownSymbol$6 = wellKnownSymbol$x; + var arrayMethodHasSpeciesSupport$3 = arrayMethodHasSpeciesSupport$5; + var nativeSlice = arraySlice$a; + + var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport$3('slice'); + + var SPECIES$1 = wellKnownSymbol$6('species'); + var $Array$1 = Array; + var max$1 = Math.max; + + // `Array.prototype.slice` method + // https://tc39.es/ecma262/#sec-array.prototype.slice + // fallback for not array-like ES3 strings and DOM objects + $$T({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, { + slice: function slice(start, end) { + var O = toIndexedObject$3(this); + var length = lengthOfArrayLike$4(O); + var k = toAbsoluteIndex$1(start, length); + var fin = toAbsoluteIndex$1(end === undefined ? length : end, length); + // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible + var Constructor, result, n; + if (isArray$4(O)) { + Constructor = O.constructor; + // cross-realm fallback + if (isConstructor$1(Constructor) && (Constructor === $Array$1 || isArray$4(Constructor.prototype))) { + Constructor = undefined; + } else if (isObject$d(Constructor)) { + Constructor = Constructor[SPECIES$1]; + if (Constructor === null) Constructor = undefined; + } + if (Constructor === $Array$1 || Constructor === undefined) { + return nativeSlice(O, k, fin); + } + } + result = new (Constructor === undefined ? $Array$1 : Constructor)(max$1(fin - k, 0)); + for (n = 0; k < fin; k++, n++) if (k in O) createProperty$3(result, n, O[k]); + result.length = n; + return result; + } + }); + + var $$S = _export; + var uncurryThis$l = functionUncurryThis; + var IndexedObject = indexedObject; + var toIndexedObject$2 = toIndexedObject$e; + var arrayMethodIsStrict$3 = arrayMethodIsStrict$8; + + var nativeJoin = uncurryThis$l([].join); + + var ES3_STRINGS = IndexedObject !== Object; + var FORCED$6 = ES3_STRINGS || !arrayMethodIsStrict$3('join', ','); + + // `Array.prototype.join` method + // https://tc39.es/ecma262/#sec-array.prototype.join + $$S({ target: 'Array', proto: true, forced: FORCED$6 }, { + join: function join(separator) { + return nativeJoin(toIndexedObject$2(this), separator === undefined ? ',' : separator); + } + }); + + var $$R = _export; + var $find = arrayIteration.find; + var addToUnscopables$2 = addToUnscopables$4; + + var FIND = 'find'; + var SKIPS_HOLES = true; + + // Shouldn't skip holes + // eslint-disable-next-line es/no-array-prototype-find -- testing + if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; }); + + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + $$R({ target: 'Array', proto: true, forced: SKIPS_HOLES }, { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables$2(FIND); + + var $$Q = _export; + var $filter = arrayIteration.filter; + var arrayMethodHasSpeciesSupport$2 = arrayMethodHasSpeciesSupport$5; + + var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport$2('filter'); + + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + // with adding support of @@species + $$Q({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, { + filter: function filter(callbackfn /* , thisArg */) { + return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var DESCRIPTORS$b = descriptors; + var FUNCTION_NAME_EXISTS = functionName.EXISTS; + var uncurryThis$k = functionUncurryThis; + var defineBuiltInAccessor$4 = defineBuiltInAccessor$b; + + var FunctionPrototype$1 = Function.prototype; + var functionToString = uncurryThis$k(FunctionPrototype$1.toString); + var nameRE = /function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/; + var regExpExec$2 = uncurryThis$k(nameRE.exec); + var NAME = 'name'; + + // Function instances `.name` property + // https://tc39.es/ecma262/#sec-function-instances-name + if (DESCRIPTORS$b && !FUNCTION_NAME_EXISTS) { + defineBuiltInAccessor$4(FunctionPrototype$1, NAME, { + configurable: true, + get: function () { + try { + return regExpExec$2(nameRE, functionToString(this))[1]; + } catch (error) { + return ''; + } + } + }); + } + + // TODO: Remove from `core-js@4` + var $$P = _export; + var uncurryThis$j = functionUncurryThis; + + var $Date = Date; + var thisTimeValue$1 = uncurryThis$j($Date.prototype.getTime); + + // `Date.now` method + // https://tc39.es/ecma262/#sec-date.now + $$P({ target: 'Date', stat: true }, { + now: function now() { + return thisTimeValue$1(new $Date()); + } + }); + + var global$i = global$O; + var DESCRIPTORS$a = descriptors; + var defineBuiltInAccessor$3 = defineBuiltInAccessor$b; + var regExpFlags = regexpFlags$1; + var fails$l = fails$_; + + // babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError + var RegExp$2 = global$i.RegExp; + var RegExpPrototype$1 = RegExp$2.prototype; + + var FORCED$5 = DESCRIPTORS$a && fails$l(function () { + var INDICES_SUPPORT = true; + try { + RegExp$2('.', 'd'); + } catch (error) { + INDICES_SUPPORT = false; + } + + var O = {}; + // modern V8 bug + var calls = ''; + var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy'; + + var addGetter = function (key, chr) { + // eslint-disable-next-line es/no-object-defineproperty -- safe + Object.defineProperty(O, key, { get: function () { + calls += chr; + return true; + } }); + }; + + var pairs = { + dotAll: 's', + global: 'g', + ignoreCase: 'i', + multiline: 'm', + sticky: 'y' + }; + + if (INDICES_SUPPORT) pairs.hasIndices = 'd'; + + for (var key in pairs) addGetter(key, pairs[key]); + + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var result = Object.getOwnPropertyDescriptor(RegExpPrototype$1, 'flags').get.call(O); + + return result !== expected || calls !== expected; + }); + + // `RegExp.prototype.flags` getter + // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags + if (FORCED$5) defineBuiltInAccessor$3(RegExpPrototype$1, 'flags', { + configurable: true, + get: regExpFlags + }); + + // TODO: Remove from `core-js@4` + var $$O = _export; + var bind$8 = functionBind; + + // `Function.prototype.bind` method + // https://tc39.es/ecma262/#sec-function.prototype.bind + // eslint-disable-next-line es/no-function-prototype-bind -- detection + $$O({ target: 'Function', proto: true, forced: Function.bind !== bind$8 }, { + bind: bind$8 + }); + + var DESCRIPTORS$9 = descriptors; + var isArray$3 = isArray$8; + + var $TypeError$4 = TypeError; + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var getOwnPropertyDescriptor$4 = Object.getOwnPropertyDescriptor; + + // Safari < 13 does not throw an error in this case + var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS$9 && !function () { + // makes no sense without proper strict mode support + if (this !== undefined) return true; + try { + // eslint-disable-next-line es/no-object-defineproperty -- safe + Object.defineProperty([], 'length', { writable: false }).length = 1; + } catch (error) { + return error instanceof TypeError; + } + }(); + + var arraySetLength = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) { + if (isArray$3(O) && !getOwnPropertyDescriptor$4(O, 'length').writable) { + throw new $TypeError$4('Cannot set read only .length'); + } return O.length = length; + } : function (O, length) { + return O.length = length; + }; + + var $$N = _export; + var toObject$4 = toObject$h; + var toAbsoluteIndex = toAbsoluteIndex$8; + var toIntegerOrInfinity$1 = toIntegerOrInfinity$a; + var lengthOfArrayLike$3 = lengthOfArrayLike$g; + var setArrayLength = arraySetLength; + var doesNotExceedSafeInteger = doesNotExceedSafeInteger$2; + var arraySpeciesCreate = arraySpeciesCreate$3; + var createProperty$2 = createProperty$6; + var deletePropertyOrThrow$1 = deletePropertyOrThrow$3; + var arrayMethodHasSpeciesSupport$1 = arrayMethodHasSpeciesSupport$5; + + var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport$1('splice'); + + var max = Math.max; + var min$3 = Math.min; + + // `Array.prototype.splice` method + // https://tc39.es/ecma262/#sec-array.prototype.splice + // with adding support of @@species + $$N({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, { + splice: function splice(start, deleteCount /* , ...items */) { + var O = toObject$4(this); + var len = lengthOfArrayLike$3(O); + var actualStart = toAbsoluteIndex(start, len); + var argumentsLength = arguments.length; + var insertCount, actualDeleteCount, A, k, from, to; + if (argumentsLength === 0) { + insertCount = actualDeleteCount = 0; + } else if (argumentsLength === 1) { + insertCount = 0; + actualDeleteCount = len - actualStart; + } else { + insertCount = argumentsLength - 2; + actualDeleteCount = min$3(max(toIntegerOrInfinity$1(deleteCount), 0), len - actualStart); + } + doesNotExceedSafeInteger(len + insertCount - actualDeleteCount); + A = arraySpeciesCreate(O, actualDeleteCount); + for (k = 0; k < actualDeleteCount; k++) { + from = actualStart + k; + if (from in O) createProperty$2(A, k, O[from]); + } + A.length = actualDeleteCount; + if (insertCount < actualDeleteCount) { + for (k = actualStart; k < len - actualDeleteCount; k++) { + from = k + actualDeleteCount; + to = k + insertCount; + if (from in O) O[to] = O[from]; + else deletePropertyOrThrow$1(O, to); + } + for (k = len; k > len - actualDeleteCount + insertCount; k--) deletePropertyOrThrow$1(O, k - 1); + } else if (insertCount > actualDeleteCount) { + for (k = len - actualDeleteCount; k > actualStart; k--) { + from = k + actualDeleteCount - 1; + to = k + insertCount - 1; + if (from in O) O[to] = O[from]; + else deletePropertyOrThrow$1(O, to); + } + } + for (k = 0; k < insertCount; k++) { + O[k + actualStart] = arguments[k + 2]; + } + setArrayLength(O, len - actualDeleteCount + insertCount); + return A; + } + }); + + var $$M = _export; + var uncurryThis$i = functionUncurryThis; + var isArray$2 = isArray$8; + + var nativeReverse = uncurryThis$i([].reverse); + var test$1 = [1, 2]; + + // `Array.prototype.reverse` method + // https://tc39.es/ecma262/#sec-array.prototype.reverse + // fix for Safari 12.0 bug + // https://bugs.webkit.org/show_bug.cgi?id=188794 + $$M({ target: 'Array', proto: true, forced: String(test$1) === String(test$1.reverse()) }, { + reverse: function reverse() { + // eslint-disable-next-line no-self-assign -- dirty hack + if (isArray$2(this)) this.length = this.length; + return nativeReverse(this); + } + }); + + var $TypeError$3 = TypeError; + + var validateArgumentsLength$4 = function (passed, required) { + if (passed < required) throw new $TypeError$3('Not enough arguments'); + return passed; + }; + + var userAgent$2 = engineUserAgent; + + // eslint-disable-next-line redos/no-vulnerable -- safe + var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent$2); + + var global$h = global$O; + var apply$2 = functionApply; + var bind$7 = functionBindContext; + var isCallable$7 = isCallable$w; + var hasOwn$6 = hasOwnProperty_1; + var fails$k = fails$_; + var html = html$2; + var arraySlice$3 = arraySlice$a; + var createElement = documentCreateElement$2; + var validateArgumentsLength$3 = validateArgumentsLength$4; + var IS_IOS$1 = engineIsIos; + var IS_NODE$3 = engineIsNode; + + var set = global$h.setImmediate; + var clear = global$h.clearImmediate; + var process$3 = global$h.process; + var Dispatch = global$h.Dispatch; + var Function$2 = global$h.Function; + var MessageChannel = global$h.MessageChannel; + var String$1 = global$h.String; + var counter = 0; + var queue$2 = {}; + var ONREADYSTATECHANGE = 'onreadystatechange'; + var $location, defer, channel, port; + + fails$k(function () { + // Deno throws a ReferenceError on `location` access without `--location` flag + $location = global$h.location; + }); + + var run = function (id) { + if (hasOwn$6(queue$2, id)) { + var fn = queue$2[id]; + delete queue$2[id]; + fn(); + } + }; + + var runner = function (id) { + return function () { + run(id); + }; + }; + + var eventListener = function (event) { + run(event.data); + }; + + var globalPostMessageDefer = function (id) { + // old engines have not location.origin + global$h.postMessage(String$1(id), $location.protocol + '//' + $location.host); + }; + + // Node.js 0.9+ & IE10+ has setImmediate, otherwise: + if (!set || !clear) { + set = function setImmediate(handler) { + validateArgumentsLength$3(arguments.length, 1); + var fn = isCallable$7(handler) ? handler : Function$2(handler); + var args = arraySlice$3(arguments, 1); + queue$2[++counter] = function () { + apply$2(fn, undefined, args); + }; + defer(counter); + return counter; + }; + clear = function clearImmediate(id) { + delete queue$2[id]; + }; + // Node.js 0.8- + if (IS_NODE$3) { + defer = function (id) { + process$3.nextTick(runner(id)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(runner(id)); + }; + // Browsers with MessageChannel, includes WebWorkers + // except iOS - https://github.com/zloirock/core-js/issues/624 + } else if (MessageChannel && !IS_IOS$1) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = eventListener; + defer = bind$7(port.postMessage, port); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if ( + global$h.addEventListener && + isCallable$7(global$h.postMessage) && + !global$h.importScripts && + $location && $location.protocol !== 'file:' && + !fails$k(globalPostMessageDefer) + ) { + defer = globalPostMessageDefer; + global$h.addEventListener('message', eventListener, false); + // IE8- + } else if (ONREADYSTATECHANGE in createElement('script')) { + defer = function (id) { + html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () { + html.removeChild(this); + run(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(runner(id), 0); + }; + } + } + + var task$1 = { + set: set, + clear: clear + }; + + var Queue$2 = function () { + this.head = null; + this.tail = null; + }; + + Queue$2.prototype = { + add: function (item) { + var entry = { item: item, next: null }; + var tail = this.tail; + if (tail) tail.next = entry; + else this.head = entry; + this.tail = entry; + }, + get: function () { + var entry = this.head; + if (entry) { + var next = this.head = entry.next; + if (next === null) this.tail = null; + return entry.item; + } + } + }; + + var queue$1 = Queue$2; + + var userAgent$1 = engineUserAgent; + + var engineIsIosPebble = /ipad|iphone|ipod/i.test(userAgent$1) && typeof Pebble != 'undefined'; + + var userAgent = engineUserAgent; + + var engineIsWebosWebkit = /web0s(?!.*chrome)/i.test(userAgent); + + var global$g = global$O; + var bind$6 = functionBindContext; + var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f; + var macrotask = task$1.set; + var Queue$1 = queue$1; + var IS_IOS = engineIsIos; + var IS_IOS_PEBBLE = engineIsIosPebble; + var IS_WEBOS_WEBKIT = engineIsWebosWebkit; + var IS_NODE$2 = engineIsNode; + + var MutationObserver = global$g.MutationObserver || global$g.WebKitMutationObserver; + var document$2 = global$g.document; + var process$2 = global$g.process; + var Promise$1 = global$g.Promise; + // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask` + var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global$g, 'queueMicrotask'); + var microtask$1 = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value; + var notify$1, toggle, node, promise, then; + + // modern engines have queueMicrotask method + if (!microtask$1) { + var queue = new Queue$1(); + + var flush = function () { + var parent, fn; + if (IS_NODE$2 && (parent = process$2.domain)) parent.exit(); + while (fn = queue.get()) try { + fn(); + } catch (error) { + if (queue.head) notify$1(); + throw error; + } + if (parent) parent.enter(); + }; + + // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339 + // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898 + if (!IS_IOS && !IS_NODE$2 && !IS_WEBOS_WEBKIT && MutationObserver && document$2) { + toggle = true; + node = document$2.createTextNode(''); + new MutationObserver(flush).observe(node, { characterData: true }); + notify$1 = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (!IS_IOS_PEBBLE && Promise$1 && Promise$1.resolve) { + // Promise.resolve without an argument throws an error in LG WebOS 2 + promise = Promise$1.resolve(undefined); + // workaround of WebKit ~ iOS Safari 10.1 bug + promise.constructor = Promise$1; + then = bind$6(promise.then, promise); + notify$1 = function () { + then(flush); + }; + // Node.js without promises + } else if (IS_NODE$2) { + notify$1 = function () { + process$2.nextTick(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessage + // - onreadystatechange + // - setTimeout + } else { + // `webpack` dev server bug on IE global methods - use bind(fn, global) + macrotask = bind$6(macrotask, global$g); + notify$1 = function () { + macrotask(flush); + }; + } + + microtask$1 = function (fn) { + if (!queue.head) notify$1(); + queue.add(fn); + }; + } + + var microtask_1 = microtask$1; + + var hostReportErrors$1 = function (a, b) { + try { + // eslint-disable-next-line no-console -- safe + arguments.length === 1 ? console.error(a) : console.error(a, b); + } catch (error) { /* empty */ } + }; + + var perform$3 = function (exec) { + try { + return { error: false, value: exec() }; + } catch (error) { + return { error: true, value: error }; + } + }; + + var global$f = global$O; + + var promiseNativeConstructor = global$f.Promise; + + /* global Deno -- Deno case */ + var engineIsDeno = typeof Deno == 'object' && Deno && typeof Deno.version == 'object'; + + var IS_DENO$1 = engineIsDeno; + var IS_NODE$1 = engineIsNode; + + var engineIsBrowser = !IS_DENO$1 && !IS_NODE$1 + && typeof window == 'object' + && typeof document == 'object'; + + var global$e = global$O; + var NativePromiseConstructor$3 = promiseNativeConstructor; + var isCallable$6 = isCallable$w; + var isForced$2 = isForced_1; + var inspectSource = inspectSource$3; + var wellKnownSymbol$5 = wellKnownSymbol$x; + var IS_BROWSER = engineIsBrowser; + var IS_DENO = engineIsDeno; + var V8_VERSION = engineV8Version; + + NativePromiseConstructor$3 && NativePromiseConstructor$3.prototype; + var SPECIES = wellKnownSymbol$5('species'); + var SUBCLASSING = false; + var NATIVE_PROMISE_REJECTION_EVENT$1 = isCallable$6(global$e.PromiseRejectionEvent); + + var FORCED_PROMISE_CONSTRUCTOR$5 = isForced$2('Promise', function () { + var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(NativePromiseConstructor$3); + var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(NativePromiseConstructor$3); + // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables + // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 + // We can't detect it synchronously, so just check versions + if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION === 66) return true; + // We can't use @@species feature detection in V8 since it causes + // deoptimization and performance degradation + // https://github.com/zloirock/core-js/issues/679 + if (!V8_VERSION || V8_VERSION < 51 || !/native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) { + // Detect correctness of subclassing with @@species support + var promise = new NativePromiseConstructor$3(function (resolve) { resolve(1); }); + var FakePromise = function (exec) { + exec(function () { /* empty */ }, function () { /* empty */ }); + }; + var constructor = promise.constructor = {}; + constructor[SPECIES] = FakePromise; + SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise; + if (!SUBCLASSING) return true; + // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test + } return !GLOBAL_CORE_JS_PROMISE && (IS_BROWSER || IS_DENO) && !NATIVE_PROMISE_REJECTION_EVENT$1; + }); + + var promiseConstructorDetection = { + CONSTRUCTOR: FORCED_PROMISE_CONSTRUCTOR$5, + REJECTION_EVENT: NATIVE_PROMISE_REJECTION_EVENT$1, + SUBCLASSING: SUBCLASSING + }; + + var newPromiseCapability$2 = {}; + + var aCallable$4 = aCallable$c; + + var $TypeError$2 = TypeError; + + var PromiseCapability = function (C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw new $TypeError$2('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aCallable$4(resolve); + this.reject = aCallable$4(reject); + }; + + // `NewPromiseCapability` abstract operation + // https://tc39.es/ecma262/#sec-newpromisecapability + newPromiseCapability$2.f = function (C) { + return new PromiseCapability(C); + }; + + var $$L = _export; + var IS_NODE = engineIsNode; + var global$d = global$O; + var call$c = functionCall; + var defineBuiltIn$5 = defineBuiltIn$i; + var setPrototypeOf$1 = objectSetPrototypeOf; + var setToStringTag$6 = setToStringTag$b; + var setSpecies$3 = setSpecies$5; + var aCallable$3 = aCallable$c; + var isCallable$5 = isCallable$w; + var isObject$c = isObject$t; + var anInstance$5 = anInstance$8; + var speciesConstructor$1 = speciesConstructor$4; + var task = task$1.set; + var microtask = microtask_1; + var hostReportErrors = hostReportErrors$1; + var perform$2 = perform$3; + var Queue = queue$1; + var InternalStateModule$4 = internalState; + var NativePromiseConstructor$2 = promiseNativeConstructor; + var PromiseConstructorDetection = promiseConstructorDetection; + var newPromiseCapabilityModule$3 = newPromiseCapability$2; + + var PROMISE = 'Promise'; + var FORCED_PROMISE_CONSTRUCTOR$4 = PromiseConstructorDetection.CONSTRUCTOR; + var NATIVE_PROMISE_REJECTION_EVENT = PromiseConstructorDetection.REJECTION_EVENT; + var NATIVE_PROMISE_SUBCLASSING = PromiseConstructorDetection.SUBCLASSING; + var getInternalPromiseState = InternalStateModule$4.getterFor(PROMISE); + var setInternalState$4 = InternalStateModule$4.set; + var NativePromisePrototype$1 = NativePromiseConstructor$2 && NativePromiseConstructor$2.prototype; + var PromiseConstructor = NativePromiseConstructor$2; + var PromisePrototype = NativePromisePrototype$1; + var TypeError$3 = global$d.TypeError; + var document$1 = global$d.document; + var process$1 = global$d.process; + var newPromiseCapability$1 = newPromiseCapabilityModule$3.f; + var newGenericPromiseCapability = newPromiseCapability$1; + + var DISPATCH_EVENT = !!(document$1 && document$1.createEvent && global$d.dispatchEvent); + var UNHANDLED_REJECTION = 'unhandledrejection'; + var REJECTION_HANDLED = 'rejectionhandled'; + var PENDING = 0; + var FULFILLED = 1; + var REJECTED = 2; + var HANDLED = 1; + var UNHANDLED = 2; + + var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen; + + // helpers + var isThenable = function (it) { + var then; + return isObject$c(it) && isCallable$5(then = it.then) ? then : false; + }; + + var callReaction = function (reaction, state) { + var value = state.value; + var ok = state.state === FULFILLED; + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then, exited; + try { + if (handler) { + if (!ok) { + if (state.rejection === UNHANDLED) onHandleUnhandled(state); + state.rejection = HANDLED; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); // can throw + if (domain) { + domain.exit(); + exited = true; + } + } + if (result === reaction.promise) { + reject(new TypeError$3('Promise-chain cycle')); + } else if (then = isThenable(result)) { + call$c(then, result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (error) { + if (domain && !exited) domain.exit(); + reject(error); + } + }; + + var notify = function (state, isReject) { + if (state.notified) return; + state.notified = true; + microtask(function () { + var reactions = state.reactions; + var reaction; + while (reaction = reactions.get()) { + callReaction(reaction, state); + } + state.notified = false; + if (isReject && !state.rejection) onUnhandled(state); + }); + }; + + var dispatchEvent = function (name, promise, reason) { + var event, handler; + if (DISPATCH_EVENT) { + event = document$1.createEvent('Event'); + event.promise = promise; + event.reason = reason; + event.initEvent(name, false, true); + global$d.dispatchEvent(event); + } else event = { promise: promise, reason: reason }; + if (!NATIVE_PROMISE_REJECTION_EVENT && (handler = global$d['on' + name])) handler(event); + else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason); + }; + + var onUnhandled = function (state) { + call$c(task, global$d, function () { + var promise = state.facade; + var value = state.value; + var IS_UNHANDLED = isUnhandled(state); + var result; + if (IS_UNHANDLED) { + result = perform$2(function () { + if (IS_NODE) { + process$1.emit('unhandledRejection', value, promise); + } else dispatchEvent(UNHANDLED_REJECTION, promise, value); + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + state.rejection = IS_NODE || isUnhandled(state) ? UNHANDLED : HANDLED; + if (result.error) throw result.value; + } + }); + }; + + var isUnhandled = function (state) { + return state.rejection !== HANDLED && !state.parent; + }; + + var onHandleUnhandled = function (state) { + call$c(task, global$d, function () { + var promise = state.facade; + if (IS_NODE) { + process$1.emit('rejectionHandled', promise); + } else dispatchEvent(REJECTION_HANDLED, promise, state.value); + }); + }; + + var bind$5 = function (fn, state, unwrap) { + return function (value) { + fn(state, value, unwrap); + }; + }; + + var internalReject = function (state, value, unwrap) { + if (state.done) return; + state.done = true; + if (unwrap) state = unwrap; + state.value = value; + state.state = REJECTED; + notify(state, true); + }; + + var internalResolve = function (state, value, unwrap) { + if (state.done) return; + state.done = true; + if (unwrap) state = unwrap; + try { + if (state.facade === value) throw new TypeError$3("Promise can't be resolved itself"); + var then = isThenable(value); + if (then) { + microtask(function () { + var wrapper = { done: false }; + try { + call$c(then, value, + bind$5(internalResolve, wrapper, state), + bind$5(internalReject, wrapper, state) + ); + } catch (error) { + internalReject(wrapper, error, state); + } + }); + } else { + state.value = value; + state.state = FULFILLED; + notify(state, false); + } + } catch (error) { + internalReject({ done: false }, error, state); + } + }; + + // constructor polyfill + if (FORCED_PROMISE_CONSTRUCTOR$4) { + // 25.4.3.1 Promise(executor) + PromiseConstructor = function Promise(executor) { + anInstance$5(this, PromisePrototype); + aCallable$3(executor); + call$c(Internal, this); + var state = getInternalPromiseState(this); + try { + executor(bind$5(internalResolve, state), bind$5(internalReject, state)); + } catch (error) { + internalReject(state, error); + } + }; + + PromisePrototype = PromiseConstructor.prototype; + + // eslint-disable-next-line no-unused-vars -- required for `.length` + Internal = function Promise(executor) { + setInternalState$4(this, { + type: PROMISE, + done: false, + notified: false, + parent: false, + reactions: new Queue(), + rejection: false, + state: PENDING, + value: undefined + }); + }; + + // `Promise.prototype.then` method + // https://tc39.es/ecma262/#sec-promise.prototype.then + Internal.prototype = defineBuiltIn$5(PromisePrototype, 'then', function then(onFulfilled, onRejected) { + var state = getInternalPromiseState(this); + var reaction = newPromiseCapability$1(speciesConstructor$1(this, PromiseConstructor)); + state.parent = true; + reaction.ok = isCallable$5(onFulfilled) ? onFulfilled : true; + reaction.fail = isCallable$5(onRejected) && onRejected; + reaction.domain = IS_NODE ? process$1.domain : undefined; + if (state.state === PENDING) state.reactions.add(reaction); + else microtask(function () { + callReaction(reaction, state); + }); + return reaction.promise; + }); + + OwnPromiseCapability = function () { + var promise = new Internal(); + var state = getInternalPromiseState(promise); + this.promise = promise; + this.resolve = bind$5(internalResolve, state); + this.reject = bind$5(internalReject, state); + }; + + newPromiseCapabilityModule$3.f = newPromiseCapability$1 = function (C) { + return C === PromiseConstructor || C === PromiseWrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; + + if (isCallable$5(NativePromiseConstructor$2) && NativePromisePrototype$1 !== Object.prototype) { + nativeThen = NativePromisePrototype$1.then; + + if (!NATIVE_PROMISE_SUBCLASSING) { + // make `Promise#then` return a polyfilled `Promise` for native promise-based APIs + defineBuiltIn$5(NativePromisePrototype$1, 'then', function then(onFulfilled, onRejected) { + var that = this; + return new PromiseConstructor(function (resolve, reject) { + call$c(nativeThen, that, resolve, reject); + }).then(onFulfilled, onRejected); + // https://github.com/zloirock/core-js/issues/640 + }, { unsafe: true }); + } + + // make `.constructor === Promise` work for native promise-based APIs + try { + delete NativePromisePrototype$1.constructor; + } catch (error) { /* empty */ } + + // make `instanceof Promise` work for native promise-based APIs + if (setPrototypeOf$1) { + setPrototypeOf$1(NativePromisePrototype$1, PromisePrototype); + } + } + } + + $$L({ global: true, constructor: true, wrap: true, forced: FORCED_PROMISE_CONSTRUCTOR$4 }, { + Promise: PromiseConstructor + }); + + setToStringTag$6(PromiseConstructor, PROMISE, false); + setSpecies$3(PROMISE); + + var call$b = functionCall; + var anObject$9 = anObject$p; + var getMethod$3 = getMethod$8; + + var iteratorClose$2 = function (iterator, kind, value) { + var innerResult, innerError; + anObject$9(iterator); + try { + innerResult = getMethod$3(iterator, 'return'); + if (!innerResult) { + if (kind === 'throw') throw value; + return value; + } + innerResult = call$b(innerResult, iterator); + } catch (error) { + innerError = true; + innerResult = error; + } + if (kind === 'throw') throw value; + if (innerError) throw innerResult; + anObject$9(innerResult); + return value; + }; + + var bind$4 = functionBindContext; + var call$a = functionCall; + var anObject$8 = anObject$p; + var tryToString = tryToString$7; + var isArrayIteratorMethod$1 = isArrayIteratorMethod$3; + var lengthOfArrayLike$2 = lengthOfArrayLike$g; + var isPrototypeOf$1 = objectIsPrototypeOf; + var getIterator$2 = getIterator$4; + var getIteratorMethod$2 = getIteratorMethod$5; + var iteratorClose$1 = iteratorClose$2; + + var $TypeError$1 = TypeError; + + var Result = function (stopped, result) { + this.stopped = stopped; + this.result = result; + }; + + var ResultPrototype = Result.prototype; + + var iterate$5 = function (iterable, unboundFunction, options) { + var that = options && options.that; + var AS_ENTRIES = !!(options && options.AS_ENTRIES); + var IS_RECORD = !!(options && options.IS_RECORD); + var IS_ITERATOR = !!(options && options.IS_ITERATOR); + var INTERRUPTED = !!(options && options.INTERRUPTED); + var fn = bind$4(unboundFunction, that); + var iterator, iterFn, index, length, result, next, step; + + var stop = function (condition) { + if (iterator) iteratorClose$1(iterator, 'normal', condition); + return new Result(true, condition); + }; + + var callFn = function (value) { + if (AS_ENTRIES) { + anObject$8(value); + return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]); + } return INTERRUPTED ? fn(value, stop) : fn(value); + }; + + if (IS_RECORD) { + iterator = iterable.iterator; + } else if (IS_ITERATOR) { + iterator = iterable; + } else { + iterFn = getIteratorMethod$2(iterable); + if (!iterFn) throw new $TypeError$1(tryToString(iterable) + ' is not iterable'); + // optimisation for array iterators + if (isArrayIteratorMethod$1(iterFn)) { + for (index = 0, length = lengthOfArrayLike$2(iterable); length > index; index++) { + result = callFn(iterable[index]); + if (result && isPrototypeOf$1(ResultPrototype, result)) return result; + } return new Result(false); + } + iterator = getIterator$2(iterable, iterFn); + } + + next = IS_RECORD ? iterable.next : iterator.next; + while (!(step = call$a(next, iterator)).done) { + try { + result = callFn(step.value); + } catch (error) { + iteratorClose$1(iterator, 'throw', error); + } + if (typeof result == 'object' && result && isPrototypeOf$1(ResultPrototype, result)) return result; + } return new Result(false); + }; + + var NativePromiseConstructor$1 = promiseNativeConstructor; + var checkCorrectnessOfIteration$2 = checkCorrectnessOfIteration$4; + var FORCED_PROMISE_CONSTRUCTOR$3 = promiseConstructorDetection.CONSTRUCTOR; + + var promiseStaticsIncorrectIteration = FORCED_PROMISE_CONSTRUCTOR$3 || !checkCorrectnessOfIteration$2(function (iterable) { + NativePromiseConstructor$1.all(iterable).then(undefined, function () { /* empty */ }); + }); + + var $$K = _export; + var call$9 = functionCall; + var aCallable$2 = aCallable$c; + var newPromiseCapabilityModule$2 = newPromiseCapability$2; + var perform$1 = perform$3; + var iterate$4 = iterate$5; + var PROMISE_STATICS_INCORRECT_ITERATION$1 = promiseStaticsIncorrectIteration; + + // `Promise.all` method + // https://tc39.es/ecma262/#sec-promise.all + $$K({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION$1 }, { + all: function all(iterable) { + var C = this; + var capability = newPromiseCapabilityModule$2.f(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = perform$1(function () { + var $promiseResolve = aCallable$2(C.resolve); + var values = []; + var counter = 0; + var remaining = 1; + iterate$4(iterable, function (promise) { + var index = counter++; + var alreadyCalled = false; + remaining++; + call$9($promiseResolve, C, promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.error) reject(result.value); + return capability.promise; + } + }); + + var $$J = _export; + var FORCED_PROMISE_CONSTRUCTOR$2 = promiseConstructorDetection.CONSTRUCTOR; + var NativePromiseConstructor = promiseNativeConstructor; + var getBuiltIn$2 = getBuiltIn$c; + var isCallable$4 = isCallable$w; + var defineBuiltIn$4 = defineBuiltIn$i; + + var NativePromisePrototype = NativePromiseConstructor && NativePromiseConstructor.prototype; + + // `Promise.prototype.catch` method + // https://tc39.es/ecma262/#sec-promise.prototype.catch + $$J({ target: 'Promise', proto: true, forced: FORCED_PROMISE_CONSTRUCTOR$2, real: true }, { + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + + // makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then` + if (isCallable$4(NativePromiseConstructor)) { + var method = getBuiltIn$2('Promise').prototype['catch']; + if (NativePromisePrototype['catch'] !== method) { + defineBuiltIn$4(NativePromisePrototype, 'catch', method, { unsafe: true }); + } + } + + var $$I = _export; + var call$8 = functionCall; + var aCallable$1 = aCallable$c; + var newPromiseCapabilityModule$1 = newPromiseCapability$2; + var perform = perform$3; + var iterate$3 = iterate$5; + var PROMISE_STATICS_INCORRECT_ITERATION = promiseStaticsIncorrectIteration; + + // `Promise.race` method + // https://tc39.es/ecma262/#sec-promise.race + $$I({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION }, { + race: function race(iterable) { + var C = this; + var capability = newPromiseCapabilityModule$1.f(C); + var reject = capability.reject; + var result = perform(function () { + var $promiseResolve = aCallable$1(C.resolve); + iterate$3(iterable, function (promise) { + call$8($promiseResolve, C, promise).then(capability.resolve, reject); + }); + }); + if (result.error) reject(result.value); + return capability.promise; + } + }); + + var $$H = _export; + var call$7 = functionCall; + var newPromiseCapabilityModule = newPromiseCapability$2; + var FORCED_PROMISE_CONSTRUCTOR$1 = promiseConstructorDetection.CONSTRUCTOR; + + // `Promise.reject` method + // https://tc39.es/ecma262/#sec-promise.reject + $$H({ target: 'Promise', stat: true, forced: FORCED_PROMISE_CONSTRUCTOR$1 }, { + reject: function reject(r) { + var capability = newPromiseCapabilityModule.f(this); + call$7(capability.reject, undefined, r); + return capability.promise; + } + }); + + var anObject$7 = anObject$p; + var isObject$b = isObject$t; + var newPromiseCapability = newPromiseCapability$2; + + var promiseResolve$1 = function (C, x) { + anObject$7(C); + if (isObject$b(x) && x.constructor === C) return x; + var promiseCapability = newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; + }; + + var $$G = _export; + var getBuiltIn$1 = getBuiltIn$c; + var FORCED_PROMISE_CONSTRUCTOR = promiseConstructorDetection.CONSTRUCTOR; + var promiseResolve = promiseResolve$1; + + getBuiltIn$1('Promise'); + + // `Promise.resolve` method + // https://tc39.es/ecma262/#sec-promise.resolve + $$G({ target: 'Promise', stat: true, forced: FORCED_PROMISE_CONSTRUCTOR }, { + resolve: function resolve(x) { + return promiseResolve(this, x); + } + }); + + var uncurryThis$h = functionUncurryThis; + var requireObjectCoercible$8 = requireObjectCoercible$f; + var toString$b = toString$n; + + var quot = /"/g; + var replace$4 = uncurryThis$h(''.replace); + + // `CreateHTML` abstract operation + // https://tc39.es/ecma262/#sec-createhtml + var createHtml = function (string, tag, attribute, value) { + var S = toString$b(requireObjectCoercible$8(string)); + var p1 = '<' + tag; + if (attribute !== '') p1 += ' ' + attribute + '="' + replace$4(toString$b(value), quot, '"') + '"'; + return p1 + '>' + S + ''; + }; + + var fails$j = fails$_; + + // check the existence of a method, lowercase + // of a tag and escaping quotes in arguments + var stringHtmlForced = function (METHOD_NAME) { + return fails$j(function () { + var test = ''[METHOD_NAME]('"'); + return test !== test.toLowerCase() || test.split('"').length > 3; + }); + }; + + var $$F = _export; + var createHTML = createHtml; + var forcedStringHTMLMethod = stringHtmlForced; + + // `String.prototype.bold` method + // https://tc39.es/ecma262/#sec-string.prototype.bold + $$F({ target: 'String', proto: true, forced: forcedStringHTMLMethod('bold') }, { + bold: function bold() { + return createHTML(this, 'b', '', ''); + } + }); + + // TODO: Remove from `core-js@4` + var $$E = _export; + var DESCRIPTORS$8 = descriptors; + var create$2 = objectCreate; + + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + $$E({ target: 'Object', stat: true, sham: !DESCRIPTORS$8 }, { + create: create$2 + }); + + var $$D = _export; + var $every = arrayIteration.every; + var arrayMethodIsStrict$2 = arrayMethodIsStrict$8; + + var STRICT_METHOD$2 = arrayMethodIsStrict$2('every'); + + // `Array.prototype.every` method + // https://tc39.es/ecma262/#sec-array.prototype.every + $$D({ target: 'Array', proto: true, forced: !STRICT_METHOD$2 }, { + every: function every(callbackfn /* , thisArg */) { + return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var $$C = _export; + var $map = arrayIteration.map; + var arrayMethodHasSpeciesSupport = arrayMethodHasSpeciesSupport$5; + + var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('map'); + + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + // with adding support of @@species + $$C({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, { + map: function map(callbackfn /* , thisArg */) { + return $map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var fails$i = fails$_; + + var freezing = !fails$i(function () { + // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing + return Object.isExtensible(Object.preventExtensions({})); + }); + + var internalMetadata = {exports: {}}; + + // FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it + var fails$h = fails$_; + + var arrayBufferNonExtensible = fails$h(function () { + if (typeof ArrayBuffer == 'function') { + var buffer = new ArrayBuffer(8); + // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe + if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 }); + } + }); + + var fails$g = fails$_; + var isObject$a = isObject$t; + var classof$3 = classofRaw$2; + var ARRAY_BUFFER_NON_EXTENSIBLE$2 = arrayBufferNonExtensible; + + // eslint-disable-next-line es/no-object-isextensible -- safe + var $isExtensible$1 = Object.isExtensible; + var FAILS_ON_PRIMITIVES$3 = fails$g(function () { $isExtensible$1(1); }); + + // `Object.isExtensible` method + // https://tc39.es/ecma262/#sec-object.isextensible + var objectIsExtensible = (FAILS_ON_PRIMITIVES$3 || ARRAY_BUFFER_NON_EXTENSIBLE$2) ? function isExtensible(it) { + if (!isObject$a(it)) return false; + if (ARRAY_BUFFER_NON_EXTENSIBLE$2 && classof$3(it) === 'ArrayBuffer') return false; + return $isExtensible$1 ? $isExtensible$1(it) : true; + } : $isExtensible$1; + + var $$B = _export; + var uncurryThis$g = functionUncurryThis; + var hiddenKeys = hiddenKeys$6; + var isObject$9 = isObject$t; + var hasOwn$5 = hasOwnProperty_1; + var defineProperty$1 = objectDefineProperty.f; + var getOwnPropertyNamesModule = objectGetOwnPropertyNames; + var getOwnPropertyNamesExternalModule = objectGetOwnPropertyNamesExternal; + var isExtensible$1 = objectIsExtensible; + var uid = uid$5; + var FREEZING$2 = freezing; + + var REQUIRED = false; + var METADATA = uid('meta'); + var id$1 = 0; + + var setMetadata = function (it) { + defineProperty$1(it, METADATA, { value: { + objectID: 'O' + id$1++, // object ID + weakData: {} // weak collections IDs + } }); + }; + + var fastKey$1 = function (it, create) { + // return a primitive with prefix + if (!isObject$9(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if (!hasOwn$5(it, METADATA)) { + // can't set metadata to uncaught frozen object + if (!isExtensible$1(it)) return 'F'; + // not necessary to add metadata + if (!create) return 'E'; + // add missing metadata + setMetadata(it); + // return object ID + } return it[METADATA].objectID; + }; + + var getWeakData$1 = function (it, create) { + if (!hasOwn$5(it, METADATA)) { + // can't set metadata to uncaught frozen object + if (!isExtensible$1(it)) return true; + // not necessary to add metadata + if (!create) return false; + // add missing metadata + setMetadata(it); + // return the store of weak collections IDs + } return it[METADATA].weakData; + }; + + // add metadata on freeze-family methods calling + var onFreeze$1 = function (it) { + if (FREEZING$2 && REQUIRED && isExtensible$1(it) && !hasOwn$5(it, METADATA)) setMetadata(it); + return it; + }; + + var enable = function () { + meta.enable = function () { /* empty */ }; + REQUIRED = true; + var getOwnPropertyNames = getOwnPropertyNamesModule.f; + var splice = uncurryThis$g([].splice); + var test = {}; + test[METADATA] = 1; + + // prevent exposing of metadata key + if (getOwnPropertyNames(test).length) { + getOwnPropertyNamesModule.f = function (it) { + var result = getOwnPropertyNames(it); + for (var i = 0, length = result.length; i < length; i++) { + if (result[i] === METADATA) { + splice(result, i, 1); + break; + } + } return result; + }; + + $$B({ target: 'Object', stat: true, forced: true }, { + getOwnPropertyNames: getOwnPropertyNamesExternalModule.f + }); + } + }; + + var meta = internalMetadata.exports = { + enable: enable, + fastKey: fastKey$1, + getWeakData: getWeakData$1, + onFreeze: onFreeze$1 + }; + + hiddenKeys[METADATA] = true; + + var internalMetadataExports = internalMetadata.exports; + + var $$A = _export; + var FREEZING$1 = freezing; + var fails$f = fails$_; + var isObject$8 = isObject$t; + var onFreeze = internalMetadataExports.onFreeze; + + // eslint-disable-next-line es/no-object-freeze -- safe + var $freeze = Object.freeze; + var FAILS_ON_PRIMITIVES$2 = fails$f(function () { $freeze(1); }); + + // `Object.freeze` method + // https://tc39.es/ecma262/#sec-object.freeze + $$A({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2, sham: !FREEZING$1 }, { + freeze: function freeze(it) { + return $freeze && isObject$8(it) ? $freeze(onFreeze(it)) : it; + } + }); + + var global$c = global$O; + var fails$e = fails$_; + var uncurryThis$f = functionUncurryThis; + var toString$a = toString$n; + var trim = stringTrim.trim; + var whitespaces = whitespaces$4; + + var $parseInt$1 = global$c.parseInt; + var Symbol$1 = global$c.Symbol; + var ITERATOR$2 = Symbol$1 && Symbol$1.iterator; + var hex = /^[+-]?0x/i; + var exec$4 = uncurryThis$f(hex.exec); + var FORCED$4 = $parseInt$1(whitespaces + '08') !== 8 || $parseInt$1(whitespaces + '0x16') !== 22 + // MS Edge 18- broken with boxed symbols + || (ITERATOR$2 && !fails$e(function () { $parseInt$1(Object(ITERATOR$2)); })); + + // `parseInt` method + // https://tc39.es/ecma262/#sec-parseint-string-radix + var numberParseInt = FORCED$4 ? function parseInt(string, radix) { + var S = trim(toString$a(string)); + return $parseInt$1(S, (radix >>> 0) || (exec$4(hex, S) ? 16 : 10)); + } : $parseInt$1; + + var $$z = _export; + var $parseInt = numberParseInt; + + // `parseInt` method + // https://tc39.es/ecma262/#sec-parseint-string-radix + $$z({ global: true, forced: parseInt !== $parseInt }, { + parseInt: $parseInt + }); + + var call$6 = functionCall; + var fixRegExpWellKnownSymbolLogic$2 = fixRegexpWellKnownSymbolLogic; + var anObject$6 = anObject$p; + var isNullOrUndefined$5 = isNullOrUndefined$c; + var toLength$4 = toLength$c; + var toString$9 = toString$n; + var requireObjectCoercible$7 = requireObjectCoercible$f; + var getMethod$2 = getMethod$8; + var advanceStringIndex$1 = advanceStringIndex$3; + var regExpExec$1 = regexpExecAbstract; + + // @@match logic + fixRegExpWellKnownSymbolLogic$2('match', function (MATCH, nativeMatch, maybeCallNative) { + return [ + // `String.prototype.match` method + // https://tc39.es/ecma262/#sec-string.prototype.match + function match(regexp) { + var O = requireObjectCoercible$7(this); + var matcher = isNullOrUndefined$5(regexp) ? undefined : getMethod$2(regexp, MATCH); + return matcher ? call$6(matcher, regexp, O) : new RegExp(regexp)[MATCH](toString$9(O)); + }, + // `RegExp.prototype[@@match]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@match + function (string) { + var rx = anObject$6(this); + var S = toString$9(string); + var res = maybeCallNative(nativeMatch, rx, S); + + if (res.done) return res.value; + + if (!rx.global) return regExpExec$1(rx, S); + + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + var A = []; + var n = 0; + var result; + while ((result = regExpExec$1(rx, S)) !== null) { + var matchStr = toString$9(result[0]); + A[n] = matchStr; + if (matchStr === '') rx.lastIndex = advanceStringIndex$1(S, toLength$4(rx.lastIndex), fullUnicode); + n++; + } + return n === 0 ? null : A; + } + ]; + }); + + var $$y = _export; + var isArray$1 = isArray$8; + + // `Array.isArray` method + // https://tc39.es/ecma262/#sec-array.isarray + $$y({ target: 'Array', stat: true }, { + isArray: isArray$1 + }); + + var $$x = _export; + var uncurryThis$e = functionUncurryThis; + var aCallable = aCallable$c; + var toObject$3 = toObject$h; + var lengthOfArrayLike$1 = lengthOfArrayLike$g; + var deletePropertyOrThrow = deletePropertyOrThrow$3; + var toString$8 = toString$n; + var fails$d = fails$_; + var internalSort = arraySort$1; + var arrayMethodIsStrict$1 = arrayMethodIsStrict$8; + var FF = engineFfVersion; + var IE_OR_EDGE = engineIsIeOrEdge; + var V8 = engineV8Version; + var WEBKIT = engineWebkitVersion; + + var test = []; + var nativeSort = uncurryThis$e(test.sort); + var push$5 = uncurryThis$e(test.push); + + // IE8- + var FAILS_ON_UNDEFINED = fails$d(function () { + test.sort(undefined); + }); + // V8 bug + var FAILS_ON_NULL = fails$d(function () { + test.sort(null); + }); + // Old WebKit + var STRICT_METHOD$1 = arrayMethodIsStrict$1('sort'); + + var STABLE_SORT = !fails$d(function () { + // feature detection can be too slow, so check engines versions + if (V8) return V8 < 70; + if (FF && FF > 3) return; + if (IE_OR_EDGE) return true; + if (WEBKIT) return WEBKIT < 603; + + var result = ''; + var code, chr, value, index; + + // generate an array with more 512 elements (Chakra and old V8 fails only in this case) + for (code = 65; code < 76; code++) { + chr = String.fromCharCode(code); + + switch (code) { + case 66: case 69: case 70: case 72: value = 3; break; + case 68: case 71: value = 4; break; + default: value = 2; + } + + for (index = 0; index < 47; index++) { + test.push({ k: chr + index, v: value }); + } + } + + test.sort(function (a, b) { return b.v - a.v; }); + + for (index = 0; index < test.length; index++) { + chr = test[index].k.charAt(0); + if (result.charAt(result.length - 1) !== chr) result += chr; + } + + return result !== 'DGBEFHACIJK'; + }); + + var FORCED$3 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$1 || !STABLE_SORT; + + var getSortCompare = function (comparefn) { + return function (x, y) { + if (y === undefined) return -1; + if (x === undefined) return 1; + if (comparefn !== undefined) return +comparefn(x, y) || 0; + return toString$8(x) > toString$8(y) ? 1 : -1; + }; + }; + + // `Array.prototype.sort` method + // https://tc39.es/ecma262/#sec-array.prototype.sort + $$x({ target: 'Array', proto: true, forced: FORCED$3 }, { + sort: function sort(comparefn) { + if (comparefn !== undefined) aCallable(comparefn); + + var array = toObject$3(this); + + if (STABLE_SORT) return comparefn === undefined ? nativeSort(array) : nativeSort(array, comparefn); + + var items = []; + var arrayLength = lengthOfArrayLike$1(array); + var itemsLength, index; + + for (index = 0; index < arrayLength; index++) { + if (index in array) push$5(items, array[index]); + } + + internalSort(items, getSortCompare(comparefn)); + + itemsLength = lengthOfArrayLike$1(items); + index = 0; + + while (index < itemsLength) array[index] = items[index++]; + while (index < arrayLength) deletePropertyOrThrow(array, index++); + + return array; + } + }); + + /* global Bun -- Deno case */ + var engineIsBun = typeof Bun == 'function' && Bun && typeof Bun.version == 'string'; + + var global$b = global$O; + var apply$1 = functionApply; + var isCallable$3 = isCallable$w; + var ENGINE_IS_BUN = engineIsBun; + var USER_AGENT = engineUserAgent; + var arraySlice$2 = arraySlice$a; + var validateArgumentsLength$2 = validateArgumentsLength$4; + + var Function$1 = global$b.Function; + // dirty IE9- and Bun 0.3.0- checks + var WRAP = /MSIE .\./.test(USER_AGENT) || ENGINE_IS_BUN && (function () { + var version = global$b.Bun.version.split('.'); + return version.length < 3 || version[0] === '0' && (version[1] < 3 || version[1] === '3' && version[2] === '0'); + })(); + + // IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix + // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers + // https://github.com/oven-sh/bun/issues/1633 + var schedulersFix$2 = function (scheduler, hasTimeArg) { + var firstParamIndex = hasTimeArg ? 2 : 1; + return WRAP ? function (handler, timeout /* , ...arguments */) { + var boundArgs = validateArgumentsLength$2(arguments.length, 1) > firstParamIndex; + var fn = isCallable$3(handler) ? handler : Function$1(handler); + var params = boundArgs ? arraySlice$2(arguments, firstParamIndex) : []; + var callback = boundArgs ? function () { + apply$1(fn, this, params); + } : fn; + return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback); + } : scheduler; + }; + + var $$w = _export; + var global$a = global$O; + var schedulersFix$1 = schedulersFix$2; + + var setInterval$1 = schedulersFix$1(global$a.setInterval, true); + + // Bun / IE9- setInterval additional parameters fix + // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval + $$w({ global: true, bind: true, forced: global$a.setInterval !== setInterval$1 }, { + setInterval: setInterval$1 + }); + + var $$v = _export; + var global$9 = global$O; + var schedulersFix = schedulersFix$2; + + var setTimeout$1 = schedulersFix(global$9.setTimeout, true); + + // Bun / IE9- setTimeout additional parameters fix + // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout + $$v({ global: true, bind: true, forced: global$9.setTimeout !== setTimeout$1 }, { + setTimeout: setTimeout$1 + }); + + var $$u = _export; + var fails$c = fails$_; + var toObject$2 = toObject$h; + var nativeGetPrototypeOf = objectGetPrototypeOf$1; + var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter; + + var FAILS_ON_PRIMITIVES$1 = fails$c(function () { nativeGetPrototypeOf(1); }); + + // `Object.getPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.getprototypeof + $$u({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$1, sham: !CORRECT_PROTOTYPE_GETTER }, { + getPrototypeOf: function getPrototypeOf(it) { + return nativeGetPrototypeOf(toObject$2(it)); + } + }); + + var getBuiltIn = getBuiltIn$c; + var defineWellKnownSymbol$1 = wellKnownSymbolDefine; + var setToStringTag$5 = setToStringTag$b; + + // `Symbol.toStringTag` well-known symbol + // https://tc39.es/ecma262/#sec-symbol.tostringtag + defineWellKnownSymbol$1('toStringTag'); + + // `Symbol.prototype[@@toStringTag]` property + // https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag + setToStringTag$5(getBuiltIn('Symbol'), 'Symbol'); + + var global$8 = global$O; + var setToStringTag$4 = setToStringTag$b; + + // JSON[@@toStringTag] property + // https://tc39.es/ecma262/#sec-json-@@tostringtag + setToStringTag$4(global$8.JSON, 'JSON', true); + + var setToStringTag$3 = setToStringTag$b; + + // Math[@@toStringTag] property + // https://tc39.es/ecma262/#sec-math-@@tostringtag + setToStringTag$3(Math, 'Math', true); + + var $$t = _export; + var fails$b = fails$_; + var isObject$7 = isObject$t; + var classof$2 = classofRaw$2; + var ARRAY_BUFFER_NON_EXTENSIBLE$1 = arrayBufferNonExtensible; + + // eslint-disable-next-line es/no-object-issealed -- safe + var $isSealed = Object.isSealed; + + var FORCED$2 = ARRAY_BUFFER_NON_EXTENSIBLE$1 || fails$b(function () { $isSealed(1); }); + + // `Object.isSealed` method + // https://tc39.es/ecma262/#sec-object.issealed + $$t({ target: 'Object', stat: true, forced: FORCED$2 }, { + isSealed: function isSealed(it) { + if (!isObject$7(it)) return true; + if (ARRAY_BUFFER_NON_EXTENSIBLE$1 && classof$2(it) === 'ArrayBuffer') return true; + return $isSealed ? $isSealed(it) : false; + } + }); + + var $$s = _export; + var fails$a = fails$_; + var getOwnPropertyNames$1 = objectGetOwnPropertyNamesExternal.f; + + // eslint-disable-next-line es/no-object-getownpropertynames -- required for testing + var FAILS_ON_PRIMITIVES = fails$a(function () { return !Object.getOwnPropertyNames(1); }); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + $$s({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, { + getOwnPropertyNames: getOwnPropertyNames$1 + }); + + var $$r = _export; + var $includes = arrayIncludes.includes; + var fails$9 = fails$_; + var addToUnscopables$1 = addToUnscopables$4; + + // FF99+ bug + var BROKEN_ON_SPARSE = fails$9(function () { + // eslint-disable-next-line es/no-array-prototype-includes -- detection + return !Array(1).includes(); + }); + + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + $$r({ target: 'Array', proto: true, forced: BROKEN_ON_SPARSE }, { + includes: function includes(el /* , fromIndex = 0 */) { + return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables$1('includes'); + + var $$q = _export; + var global$7 = global$O; + var uncurryThis$d = functionUncurryThis; + var isForced$1 = isForced_1; + var defineBuiltIn$3 = defineBuiltIn$i; + var InternalMetadataModule$1 = internalMetadataExports; + var iterate$2 = iterate$5; + var anInstance$4 = anInstance$8; + var isCallable$2 = isCallable$w; + var isNullOrUndefined$4 = isNullOrUndefined$c; + var isObject$6 = isObject$t; + var fails$8 = fails$_; + var checkCorrectnessOfIteration$1 = checkCorrectnessOfIteration$4; + var setToStringTag$2 = setToStringTag$b; + var inheritIfRequired$1 = inheritIfRequired$4; + + var collection$4 = function (CONSTRUCTOR_NAME, wrapper, common) { + var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1; + var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1; + var ADDER = IS_MAP ? 'set' : 'add'; + var NativeConstructor = global$7[CONSTRUCTOR_NAME]; + var NativePrototype = NativeConstructor && NativeConstructor.prototype; + var Constructor = NativeConstructor; + var exported = {}; + + var fixMethod = function (KEY) { + var uncurriedNativeMethod = uncurryThis$d(NativePrototype[KEY]); + defineBuiltIn$3(NativePrototype, KEY, + KEY === 'add' ? function add(value) { + uncurriedNativeMethod(this, value === 0 ? 0 : value); + return this; + } : KEY === 'delete' ? function (key) { + return IS_WEAK && !isObject$6(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key); + } : KEY === 'get' ? function get(key) { + return IS_WEAK && !isObject$6(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key); + } : KEY === 'has' ? function has(key) { + return IS_WEAK && !isObject$6(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key); + } : function set(key, value) { + uncurriedNativeMethod(this, key === 0 ? 0 : key, value); + return this; + } + ); + }; + + var REPLACE = isForced$1( + CONSTRUCTOR_NAME, + !isCallable$2(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails$8(function () { + new NativeConstructor().entries().next(); + })) + ); + + if (REPLACE) { + // create collection constructor + Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER); + InternalMetadataModule$1.enable(); + } else if (isForced$1(CONSTRUCTOR_NAME, true)) { + var instance = new Constructor(); + // early implementations not supports chaining + var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) !== instance; + // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false + var THROWS_ON_PRIMITIVES = fails$8(function () { instance.has(1); }); + // most early implementations doesn't supports iterables, most modern - not close it correctly + // eslint-disable-next-line no-new -- required for testing + var ACCEPT_ITERABLES = checkCorrectnessOfIteration$1(function (iterable) { new NativeConstructor(iterable); }); + // for early implementations -0 and +0 not the same + var BUGGY_ZERO = !IS_WEAK && fails$8(function () { + // V8 ~ Chromium 42- fails only with 5+ elements + var $instance = new NativeConstructor(); + var index = 5; + while (index--) $instance[ADDER](index, index); + return !$instance.has(-0); + }); + + if (!ACCEPT_ITERABLES) { + Constructor = wrapper(function (dummy, iterable) { + anInstance$4(dummy, NativePrototype); + var that = inheritIfRequired$1(new NativeConstructor(), dummy, Constructor); + if (!isNullOrUndefined$4(iterable)) iterate$2(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP }); + return that; + }); + Constructor.prototype = NativePrototype; + NativePrototype.constructor = Constructor; + } + + if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { + fixMethod('delete'); + fixMethod('has'); + IS_MAP && fixMethod('get'); + } + + if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); + + // weak collections should not contains .clear method + if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear; + } + + exported[CONSTRUCTOR_NAME] = Constructor; + $$q({ global: true, constructor: true, forced: Constructor !== NativeConstructor }, exported); + + setToStringTag$2(Constructor, CONSTRUCTOR_NAME); + + if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP); + + return Constructor; + }; + + var create$1 = objectCreate; + var defineBuiltInAccessor$2 = defineBuiltInAccessor$b; + var defineBuiltIns$3 = defineBuiltIns$5; + var bind$3 = functionBindContext; + var anInstance$3 = anInstance$8; + var isNullOrUndefined$3 = isNullOrUndefined$c; + var iterate$1 = iterate$5; + var defineIterator = iteratorDefine; + var createIterResultObject = createIterResultObject$3; + var setSpecies$2 = setSpecies$5; + var DESCRIPTORS$7 = descriptors; + var fastKey = internalMetadataExports.fastKey; + var InternalStateModule$3 = internalState; + + var setInternalState$3 = InternalStateModule$3.set; + var internalStateGetterFor$1 = InternalStateModule$3.getterFor; + + var collectionStrong$2 = { + getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) { + var Constructor = wrapper(function (that, iterable) { + anInstance$3(that, Prototype); + setInternalState$3(that, { + type: CONSTRUCTOR_NAME, + index: create$1(null), + first: undefined, + last: undefined, + size: 0 + }); + if (!DESCRIPTORS$7) that.size = 0; + if (!isNullOrUndefined$3(iterable)) iterate$1(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP }); + }); + + var Prototype = Constructor.prototype; + + var getInternalState = internalStateGetterFor$1(CONSTRUCTOR_NAME); + + var define = function (that, key, value) { + var state = getInternalState(that); + var entry = getEntry(that, key); + var previous, index; + // change existing entry + if (entry) { + entry.value = value; + // create new entry + } else { + state.last = entry = { + index: index = fastKey(key, true), + key: key, + value: value, + previous: previous = state.last, + next: undefined, + removed: false + }; + if (!state.first) state.first = entry; + if (previous) previous.next = entry; + if (DESCRIPTORS$7) state.size++; + else that.size++; + // add to index + if (index !== 'F') state.index[index] = entry; + } return that; + }; + + var getEntry = function (that, key) { + var state = getInternalState(that); + // fast case + var index = fastKey(key); + var entry; + if (index !== 'F') return state.index[index]; + // frozen object case + for (entry = state.first; entry; entry = entry.next) { + if (entry.key === key) return entry; + } + }; + + defineBuiltIns$3(Prototype, { + // `{ Map, Set }.prototype.clear()` methods + // https://tc39.es/ecma262/#sec-map.prototype.clear + // https://tc39.es/ecma262/#sec-set.prototype.clear + clear: function clear() { + var that = this; + var state = getInternalState(that); + var data = state.index; + var entry = state.first; + while (entry) { + entry.removed = true; + if (entry.previous) entry.previous = entry.previous.next = undefined; + delete data[entry.index]; + entry = entry.next; + } + state.first = state.last = undefined; + if (DESCRIPTORS$7) state.size = 0; + else that.size = 0; + }, + // `{ Map, Set }.prototype.delete(key)` methods + // https://tc39.es/ecma262/#sec-map.prototype.delete + // https://tc39.es/ecma262/#sec-set.prototype.delete + 'delete': function (key) { + var that = this; + var state = getInternalState(that); + var entry = getEntry(that, key); + if (entry) { + var next = entry.next; + var prev = entry.previous; + delete state.index[entry.index]; + entry.removed = true; + if (prev) prev.next = next; + if (next) next.previous = prev; + if (state.first === entry) state.first = next; + if (state.last === entry) state.last = prev; + if (DESCRIPTORS$7) state.size--; + else that.size--; + } return !!entry; + }, + // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods + // https://tc39.es/ecma262/#sec-map.prototype.foreach + // https://tc39.es/ecma262/#sec-set.prototype.foreach + forEach: function forEach(callbackfn /* , that = undefined */) { + var state = getInternalState(this); + var boundFunction = bind$3(callbackfn, arguments.length > 1 ? arguments[1] : undefined); + var entry; + while (entry = entry ? entry.next : state.first) { + boundFunction(entry.value, entry.key, this); + // revert to the last existing entry + while (entry && entry.removed) entry = entry.previous; + } + }, + // `{ Map, Set}.prototype.has(key)` methods + // https://tc39.es/ecma262/#sec-map.prototype.has + // https://tc39.es/ecma262/#sec-set.prototype.has + has: function has(key) { + return !!getEntry(this, key); + } + }); + + defineBuiltIns$3(Prototype, IS_MAP ? { + // `Map.prototype.get(key)` method + // https://tc39.es/ecma262/#sec-map.prototype.get + get: function get(key) { + var entry = getEntry(this, key); + return entry && entry.value; + }, + // `Map.prototype.set(key, value)` method + // https://tc39.es/ecma262/#sec-map.prototype.set + set: function set(key, value) { + return define(this, key === 0 ? 0 : key, value); + } + } : { + // `Set.prototype.add(value)` method + // https://tc39.es/ecma262/#sec-set.prototype.add + add: function add(value) { + return define(this, value = value === 0 ? 0 : value, value); + } + }); + if (DESCRIPTORS$7) defineBuiltInAccessor$2(Prototype, 'size', { + configurable: true, + get: function () { + return getInternalState(this).size; + } + }); + return Constructor; + }, + setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) { + var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator'; + var getInternalCollectionState = internalStateGetterFor$1(CONSTRUCTOR_NAME); + var getInternalIteratorState = internalStateGetterFor$1(ITERATOR_NAME); + // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods + // https://tc39.es/ecma262/#sec-map.prototype.entries + // https://tc39.es/ecma262/#sec-map.prototype.keys + // https://tc39.es/ecma262/#sec-map.prototype.values + // https://tc39.es/ecma262/#sec-map.prototype-@@iterator + // https://tc39.es/ecma262/#sec-set.prototype.entries + // https://tc39.es/ecma262/#sec-set.prototype.keys + // https://tc39.es/ecma262/#sec-set.prototype.values + // https://tc39.es/ecma262/#sec-set.prototype-@@iterator + defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) { + setInternalState$3(this, { + type: ITERATOR_NAME, + target: iterated, + state: getInternalCollectionState(iterated), + kind: kind, + last: undefined + }); + }, function () { + var state = getInternalIteratorState(this); + var kind = state.kind; + var entry = state.last; + // revert to the last existing entry + while (entry && entry.removed) entry = entry.previous; + // get next entry + if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) { + // or finish the iteration + state.target = undefined; + return createIterResultObject(undefined, true); + } + // return step by kind + if (kind === 'keys') return createIterResultObject(entry.key, false); + if (kind === 'values') return createIterResultObject(entry.value, false); + return createIterResultObject([entry.key, entry.value], false); + }, IS_MAP ? 'entries' : 'values', !IS_MAP, true); + + // `{ Map, Set }.prototype[@@species]` accessors + // https://tc39.es/ecma262/#sec-get-map-@@species + // https://tc39.es/ecma262/#sec-get-set-@@species + setSpecies$2(CONSTRUCTOR_NAME); + } + }; + + var collection$3 = collection$4; + var collectionStrong$1 = collectionStrong$2; + + // `Map` constructor + // https://tc39.es/ecma262/#sec-map-objects + collection$3('Map', function (init) { + return function Map() { return init(this, arguments.length ? arguments[0] : undefined); }; + }, collectionStrong$1); + + var collection$2 = collection$4; + var collectionStrong = collectionStrong$2; + + // `Set` constructor + // https://tc39.es/ecma262/#sec-set-objects + collection$2('Set', function (init) { + return function Set() { return init(this, arguments.length ? arguments[0] : undefined); }; + }, collectionStrong); + + var global$6 = global$O; + + var globalIsFinite = global$6.isFinite; + + // `Number.isFinite` method + // https://tc39.es/ecma262/#sec-number.isfinite + // eslint-disable-next-line es/no-number-isfinite -- safe + var numberIsFinite$1 = Number.isFinite || function isFinite(it) { + return typeof it == 'number' && globalIsFinite(it); + }; + + var $$p = _export; + var numberIsFinite = numberIsFinite$1; + + // `Number.isFinite` method + // https://tc39.es/ecma262/#sec-number.isfinite + $$p({ target: 'Number', stat: true }, { isFinite: numberIsFinite }); + + var defineProperty = objectDefineProperty.f; + + var proxyAccessor$1 = function (Target, Source, key) { + key in Target || defineProperty(Target, key, { + configurable: true, + get: function () { return Source[key]; }, + set: function (it) { Source[key] = it; } + }); + }; + + var DESCRIPTORS$6 = descriptors; + var global$5 = global$O; + var uncurryThis$c = functionUncurryThis; + var isForced = isForced_1; + var inheritIfRequired = inheritIfRequired$4; + var createNonEnumerableProperty = createNonEnumerableProperty$a; + var getOwnPropertyNames = objectGetOwnPropertyNames.f; + var isPrototypeOf = objectIsPrototypeOf; + var isRegExp$2 = isRegexp; + var toString$7 = toString$n; + var getRegExpFlags = regexpGetFlags; + var stickyHelpers$1 = regexpStickyHelpers; + var proxyAccessor = proxyAccessor$1; + var defineBuiltIn$2 = defineBuiltIn$i; + var fails$7 = fails$_; + var hasOwn$4 = hasOwnProperty_1; + var enforceInternalState$1 = internalState.enforce; + var setSpecies$1 = setSpecies$5; + var wellKnownSymbol$4 = wellKnownSymbol$x; + var UNSUPPORTED_DOT_ALL = regexpUnsupportedDotAll; + var UNSUPPORTED_NCG = regexpUnsupportedNcg; + + var MATCH$1 = wellKnownSymbol$4('match'); + var NativeRegExp = global$5.RegExp; + var RegExpPrototype = NativeRegExp.prototype; + var SyntaxError = global$5.SyntaxError; + var exec$3 = uncurryThis$c(RegExpPrototype.exec); + var charAt$2 = uncurryThis$c(''.charAt); + var replace$3 = uncurryThis$c(''.replace); + var stringIndexOf$1 = uncurryThis$c(''.indexOf); + var stringSlice$5 = uncurryThis$c(''.slice); + // TODO: Use only proper RegExpIdentifierName + var IS_NCG = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/; + var re1 = /a/g; + var re2 = /a/g; + + // "new" should create a new object, old webkit bug + var CORRECT_NEW = new NativeRegExp(re1) !== re1; + + var MISSED_STICKY = stickyHelpers$1.MISSED_STICKY; + var UNSUPPORTED_Y$1 = stickyHelpers$1.UNSUPPORTED_Y; + + var BASE_FORCED = DESCRIPTORS$6 && + (!CORRECT_NEW || MISSED_STICKY || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG || fails$7(function () { + re2[MATCH$1] = false; + // RegExp constructor can alter flags and IsRegExp works correct with @@match + return NativeRegExp(re1) !== re1 || NativeRegExp(re2) === re2 || String(NativeRegExp(re1, 'i')) !== '/a/i'; + })); + + var handleDotAll = function (string) { + var length = string.length; + var index = 0; + var result = ''; + var brackets = false; + var chr; + for (; index <= length; index++) { + chr = charAt$2(string, index); + if (chr === '\\') { + result += chr + charAt$2(string, ++index); + continue; + } + if (!brackets && chr === '.') { + result += '[\\s\\S]'; + } else { + if (chr === '[') { + brackets = true; + } else if (chr === ']') { + brackets = false; + } result += chr; + } + } return result; + }; + + var handleNCG = function (string) { + var length = string.length; + var index = 0; + var result = ''; + var named = []; + var names = {}; + var brackets = false; + var ncg = false; + var groupid = 0; + var groupname = ''; + var chr; + for (; index <= length; index++) { + chr = charAt$2(string, index); + if (chr === '\\') { + chr += charAt$2(string, ++index); + } else if (chr === ']') { + brackets = false; + } else if (!brackets) switch (true) { + case chr === '[': + brackets = true; + break; + case chr === '(': + if (exec$3(IS_NCG, stringSlice$5(string, index + 1))) { + index += 2; + ncg = true; + } + result += chr; + groupid++; + continue; + case chr === '>' && ncg: + if (groupname === '' || hasOwn$4(names, groupname)) { + throw new SyntaxError('Invalid capture group name'); + } + names[groupname] = true; + named[named.length] = [groupname, groupid]; + ncg = false; + groupname = ''; + continue; + } + if (ncg) groupname += chr; + else result += chr; + } return [result, named]; + }; + + // `RegExp` constructor + // https://tc39.es/ecma262/#sec-regexp-constructor + if (isForced('RegExp', BASE_FORCED)) { + var RegExpWrapper = function RegExp(pattern, flags) { + var thisIsRegExp = isPrototypeOf(RegExpPrototype, this); + var patternIsRegExp = isRegExp$2(pattern); + var flagsAreUndefined = flags === undefined; + var groups = []; + var rawPattern = pattern; + var rawFlags, dotAll, sticky, handled, result, state; + + if (!thisIsRegExp && patternIsRegExp && flagsAreUndefined && pattern.constructor === RegExpWrapper) { + return pattern; + } + + if (patternIsRegExp || isPrototypeOf(RegExpPrototype, pattern)) { + pattern = pattern.source; + if (flagsAreUndefined) flags = getRegExpFlags(rawPattern); + } + + pattern = pattern === undefined ? '' : toString$7(pattern); + flags = flags === undefined ? '' : toString$7(flags); + rawPattern = pattern; + + if (UNSUPPORTED_DOT_ALL && 'dotAll' in re1) { + dotAll = !!flags && stringIndexOf$1(flags, 's') > -1; + if (dotAll) flags = replace$3(flags, /s/g, ''); + } + + rawFlags = flags; + + if (MISSED_STICKY && 'sticky' in re1) { + sticky = !!flags && stringIndexOf$1(flags, 'y') > -1; + if (sticky && UNSUPPORTED_Y$1) flags = replace$3(flags, /y/g, ''); + } + + if (UNSUPPORTED_NCG) { + handled = handleNCG(pattern); + pattern = handled[0]; + groups = handled[1]; + } + + result = inheritIfRequired(NativeRegExp(pattern, flags), thisIsRegExp ? this : RegExpPrototype, RegExpWrapper); + + if (dotAll || sticky || groups.length) { + state = enforceInternalState$1(result); + if (dotAll) { + state.dotAll = true; + state.raw = RegExpWrapper(handleDotAll(pattern), rawFlags); + } + if (sticky) state.sticky = true; + if (groups.length) state.groups = groups; + } + + if (pattern !== rawPattern) try { + // fails in old engines, but we have no alternatives for unsupported regex syntax + createNonEnumerableProperty(result, 'source', rawPattern === '' ? '(?:)' : rawPattern); + } catch (error) { /* empty */ } + + return result; + }; + + for (var keys = getOwnPropertyNames(NativeRegExp), index = 0; keys.length > index;) { + proxyAccessor(RegExpWrapper, NativeRegExp, keys[index++]); + } + + RegExpPrototype.constructor = RegExpWrapper; + RegExpWrapper.prototype = RegExpPrototype; + defineBuiltIn$2(global$5, 'RegExp', RegExpWrapper, { constructor: true }); + } + + // https://tc39.es/ecma262/#sec-get-regexp-@@species + setSpecies$1('RegExp'); + + var $$o = _export; + var $some = arrayIteration.some; + var arrayMethodIsStrict = arrayMethodIsStrict$8; + + var STRICT_METHOD = arrayMethodIsStrict('some'); + + // `Array.prototype.some` method + // https://tc39.es/ecma262/#sec-array.prototype.some + $$o({ target: 'Array', proto: true, forced: !STRICT_METHOD }, { + some: function some(callbackfn /* , thisArg */) { + return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var $$n = _export; + + // `Number.isNaN` method + // https://tc39.es/ecma262/#sec-number.isnan + $$n({ target: 'Number', stat: true }, { + isNaN: function isNaN(number) { + // eslint-disable-next-line no-self-compare -- NaN check + return number !== number; + } + }); + + var $$m = _export; + var DESCRIPTORS$5 = descriptors; + var defineProperties = objectDefineProperties.f; + + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + // eslint-disable-next-line es/no-object-defineproperties -- safe + $$m({ target: 'Object', stat: true, forced: Object.defineProperties !== defineProperties, sham: !DESCRIPTORS$5 }, { + defineProperties: defineProperties + }); + + var $$l = _export; + var DESCRIPTORS$4 = descriptors; + var ownKeys = ownKeys$2; + var toIndexedObject$1 = toIndexedObject$e; + var getOwnPropertyDescriptorModule$1 = objectGetOwnPropertyDescriptor; + var createProperty$1 = createProperty$6; + + // `Object.getOwnPropertyDescriptors` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors + $$l({ target: 'Object', stat: true, sham: !DESCRIPTORS$4 }, { + getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) { + var O = toIndexedObject$1(object); + var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$1.f; + var keys = ownKeys(O); + var result = {}; + var index = 0; + var key, descriptor; + while (keys.length > index) { + descriptor = getOwnPropertyDescriptor(O, key = keys[index++]); + if (descriptor !== undefined) createProperty$1(result, key, descriptor); + } + return result; + } + }); + + var DESCRIPTORS$3 = descriptors; + var fails$6 = fails$_; + var uncurryThis$b = functionUncurryThis; + var objectGetPrototypeOf = objectGetPrototypeOf$1; + var objectKeys = objectKeys$4; + var toIndexedObject = toIndexedObject$e; + var $propertyIsEnumerable = objectPropertyIsEnumerable.f; + + var propertyIsEnumerable = uncurryThis$b($propertyIsEnumerable); + var push$4 = uncurryThis$b([].push); + + // in some IE versions, `propertyIsEnumerable` returns incorrect result on integer keys + // of `null` prototype objects + var IE_BUG = DESCRIPTORS$3 && fails$6(function () { + // eslint-disable-next-line es/no-object-create -- safe + var O = Object.create(null); + O[2] = 2; + return !propertyIsEnumerable(O, 2); + }); + + // `Object.{ entries, values }` methods implementation + var createMethod$1 = function (TO_ENTRIES) { + return function (it) { + var O = toIndexedObject(it); + var keys = objectKeys(O); + var IE_WORKAROUND = IE_BUG && objectGetPrototypeOf(O) === null; + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) { + key = keys[i++]; + if (!DESCRIPTORS$3 || (IE_WORKAROUND ? key in O : propertyIsEnumerable(O, key))) { + push$4(result, TO_ENTRIES ? [key, O[key]] : O[key]); + } + } + return result; + }; + }; + + var objectToArray = { + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + entries: createMethod$1(true), + // `Object.values` method + // https://tc39.es/ecma262/#sec-object.values + values: createMethod$1(false) + }; + + var $$k = _export; + var $values = objectToArray.values; + + // `Object.values` method + // https://tc39.es/ecma262/#sec-object.values + $$k({ target: 'Object', stat: true }, { + values: function values(O) { + return $values(O); + } + }); + + var isRegExp$1 = isRegexp; + + var $TypeError = TypeError; + + var notARegexp = function (it) { + if (isRegExp$1(it)) { + throw new $TypeError("The method doesn't accept regular expressions"); + } return it; + }; + + var wellKnownSymbol$3 = wellKnownSymbol$x; + + var MATCH = wellKnownSymbol$3('match'); + + var correctIsRegexpLogic = function (METHOD_NAME) { + var regexp = /./; + try { + '/./'[METHOD_NAME](regexp); + } catch (error1) { + try { + regexp[MATCH] = false; + return '/./'[METHOD_NAME](regexp); + } catch (error2) { /* empty */ } + } return false; + }; + + var $$j = _export; + var uncurryThis$a = functionUncurryThis; + var notARegExp$2 = notARegexp; + var requireObjectCoercible$6 = requireObjectCoercible$f; + var toString$6 = toString$n; + var correctIsRegExpLogic$2 = correctIsRegexpLogic; + + var stringIndexOf = uncurryThis$a(''.indexOf); + + // `String.prototype.includes` method + // https://tc39.es/ecma262/#sec-string.prototype.includes + $$j({ target: 'String', proto: true, forced: !correctIsRegExpLogic$2('includes') }, { + includes: function includes(searchString /* , position = 0 */) { + return !!~stringIndexOf( + toString$6(requireObjectCoercible$6(this)), + toString$6(notARegExp$2(searchString)), + arguments.length > 1 ? arguments[1] : undefined + ); + } + }); + + var createTypedArrayConstructor$7 = typedArrayConstructorExports; + + // `Int8Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$7('Int8', function (init) { + return function Int8Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor$6 = typedArrayConstructorExports; + + // `Uint8ClampedArray` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$6('Uint8', function (init) { + return function Uint8ClampedArray(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }, true); + + var createTypedArrayConstructor$5 = typedArrayConstructorExports; + + // `Int16Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$5('Int16', function (init) { + return function Int16Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor$4 = typedArrayConstructorExports; + + // `Uint16Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$4('Uint16', function (init) { + return function Uint16Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor$3 = typedArrayConstructorExports; + + // `Int32Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$3('Int32', function (init) { + return function Int32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor$2 = typedArrayConstructorExports; + + // `Uint32Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$2('Uint32', function (init) { + return function Uint32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor$1 = typedArrayConstructorExports; + + // `Float32Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor$1('Float32', function (init) { + return function Float32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var createTypedArrayConstructor = typedArrayConstructorExports; + + // `Float64Array` constructor + // https://tc39.es/ecma262/#sec-typedarray-objects + createTypedArrayConstructor('Float64', function (init) { + return function Float64Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; + }); + + var defineWellKnownSymbol = wellKnownSymbolDefine; + + // `Symbol.hasInstance` well-known symbol + // https://tc39.es/ecma262/#sec-symbol.hasinstance + defineWellKnownSymbol('hasInstance'); + + var isCallable$1 = isCallable$w; + var isObject$5 = isObject$t; + var definePropertyModule = objectDefineProperty; + var getPrototypeOf$1 = objectGetPrototypeOf$1; + var wellKnownSymbol$2 = wellKnownSymbol$x; + var makeBuiltIn = makeBuiltInExports; + + var HAS_INSTANCE = wellKnownSymbol$2('hasInstance'); + var FunctionPrototype = Function.prototype; + + // `Function.prototype[@@hasInstance]` method + // https://tc39.es/ecma262/#sec-function.prototype-@@hasinstance + if (!(HAS_INSTANCE in FunctionPrototype)) { + definePropertyModule.f(FunctionPrototype, HAS_INSTANCE, { value: makeBuiltIn(function (O) { + if (!isCallable$1(this) || !isObject$5(O)) return false; + var P = this.prototype; + if (!isObject$5(P)) return O instanceof this; + // for environment w/o native `@@hasInstance` logic enough `instanceof`, but add this: + while (O = getPrototypeOf$1(O)) if (P === O) return true; + return false; + }, HAS_INSTANCE) }); + } + + var $$i = _export; + var uncurryThis$9 = functionUncurryThisClause; + var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f; + var toLength$3 = toLength$c; + var toString$5 = toString$n; + var notARegExp$1 = notARegexp; + var requireObjectCoercible$5 = requireObjectCoercible$f; + var correctIsRegExpLogic$1 = correctIsRegexpLogic; + + // eslint-disable-next-line es/no-string-prototype-startswith -- safe + var nativeStartsWith = uncurryThis$9(''.startsWith); + var stringSlice$4 = uncurryThis$9(''.slice); + var min$2 = Math.min; + + var CORRECT_IS_REGEXP_LOGIC$1 = correctIsRegExpLogic$1('startsWith'); + // https://github.com/zloirock/core-js/pull/702 + var MDN_POLYFILL_BUG$1 = !CORRECT_IS_REGEXP_LOGIC$1 && !!function () { + var descriptor = getOwnPropertyDescriptor$2(String.prototype, 'startsWith'); + return descriptor && !descriptor.writable; + }(); + + // `String.prototype.startsWith` method + // https://tc39.es/ecma262/#sec-string.prototype.startswith + $$i({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG$1 && !CORRECT_IS_REGEXP_LOGIC$1 }, { + startsWith: function startsWith(searchString /* , position = 0 */) { + var that = toString$5(requireObjectCoercible$5(this)); + notARegExp$1(searchString); + var index = toLength$3(min$2(arguments.length > 1 ? arguments[1] : undefined, that.length)); + var search = toString$5(searchString); + return nativeStartsWith + ? nativeStartsWith(that, search, index) + : stringSlice$4(that, index, index + search.length) === search; + } + }); + + var $$h = _export; + var uncurryThis$8 = functionUncurryThisClause; + var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f; + var toLength$2 = toLength$c; + var toString$4 = toString$n; + var notARegExp = notARegexp; + var requireObjectCoercible$4 = requireObjectCoercible$f; + var correctIsRegExpLogic = correctIsRegexpLogic; + + // eslint-disable-next-line es/no-string-prototype-endswith -- safe + var nativeEndsWith = uncurryThis$8(''.endsWith); + var slice = uncurryThis$8(''.slice); + var min$1 = Math.min; + + var CORRECT_IS_REGEXP_LOGIC = correctIsRegExpLogic('endsWith'); + // https://github.com/zloirock/core-js/pull/702 + var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () { + var descriptor = getOwnPropertyDescriptor$1(String.prototype, 'endsWith'); + return descriptor && !descriptor.writable; + }(); + + // `String.prototype.endsWith` method + // https://tc39.es/ecma262/#sec-string.prototype.endswith + $$h({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, { + endsWith: function endsWith(searchString /* , endPosition = @length */) { + var that = toString$4(requireObjectCoercible$4(this)); + notARegExp(searchString); + var endPosition = arguments.length > 1 ? arguments[1] : undefined; + var len = that.length; + var end = endPosition === undefined ? len : min$1(toLength$2(endPosition), len); + var search = toString$4(searchString); + return nativeEndsWith + ? nativeEndsWith(that, search, end) + : slice(that, end - search.length, end) === search; + } + }); + + var anObject$5 = anObject$p; + var iteratorClose = iteratorClose$2; + + // call something on iterator step with safe closing on error + var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) { + try { + return ENTRIES ? fn(anObject$5(value)[0], value[1]) : fn(value); + } catch (error) { + iteratorClose(iterator, 'throw', error); + } + }; + + var bind$2 = functionBindContext; + var call$5 = functionCall; + var toObject$1 = toObject$h; + var callWithSafeIterationClosing = callWithSafeIterationClosing$1; + var isArrayIteratorMethod = isArrayIteratorMethod$3; + var isConstructor = isConstructor$4; + var lengthOfArrayLike = lengthOfArrayLike$g; + var createProperty = createProperty$6; + var getIterator$1 = getIterator$4; + var getIteratorMethod$1 = getIteratorMethod$5; + + var $Array = Array; + + // `Array.from` method implementation + // https://tc39.es/ecma262/#sec-array.from + var arrayFrom$1 = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { + var O = toObject$1(arrayLike); + var IS_CONSTRUCTOR = isConstructor(this); + var argumentsLength = arguments.length; + var mapfn = argumentsLength > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; + if (mapping) mapfn = bind$2(mapfn, argumentsLength > 2 ? arguments[2] : undefined); + var iteratorMethod = getIteratorMethod$1(O); + var index = 0; + var length, result, step, iterator, next, value; + // if the target is not iterable or it's an array with the default iterator - use a simple case + if (iteratorMethod && !(this === $Array && isArrayIteratorMethod(iteratorMethod))) { + iterator = getIterator$1(O, iteratorMethod); + next = iterator.next; + result = IS_CONSTRUCTOR ? new this() : []; + for (;!(step = call$5(next, iterator)).done; index++) { + value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value; + createProperty(result, index, value); + } + } else { + length = lengthOfArrayLike(O); + result = IS_CONSTRUCTOR ? new this(length) : $Array(length); + for (;length > index; index++) { + value = mapping ? mapfn(O[index], index) : O[index]; + createProperty(result, index, value); + } + } + result.length = index; + return result; + }; + + var $$g = _export; + var from = arrayFrom$1; + var checkCorrectnessOfIteration = checkCorrectnessOfIteration$4; + + var INCORRECT_ITERATION = !checkCorrectnessOfIteration(function (iterable) { + // eslint-disable-next-line es/no-array-from -- required for testing + Array.from(iterable); + }); + + // `Array.from` method + // https://tc39.es/ecma262/#sec-array.from + $$g({ target: 'Array', stat: true, forced: INCORRECT_ITERATION }, { + from: from + }); + + var apply = functionApply; + var call$4 = functionCall; + var uncurryThis$7 = functionUncurryThis; + var fixRegExpWellKnownSymbolLogic$1 = fixRegexpWellKnownSymbolLogic; + var anObject$4 = anObject$p; + var isNullOrUndefined$2 = isNullOrUndefined$c; + var isRegExp = isRegexp; + var requireObjectCoercible$3 = requireObjectCoercible$f; + var speciesConstructor = speciesConstructor$4; + var advanceStringIndex = advanceStringIndex$3; + var toLength$1 = toLength$c; + var toString$3 = toString$n; + var getMethod$1 = getMethod$8; + var arraySlice$1 = arraySliceSimple; + var callRegExpExec = regexpExecAbstract; + var regexpExec = regexpExec$3; + var stickyHelpers = regexpStickyHelpers; + var fails$5 = fails$_; + + var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y; + var MAX_UINT32 = 0xFFFFFFFF; + var min = Math.min; + var $push = [].push; + var exec$2 = uncurryThis$7(/./.exec); + var push$3 = uncurryThis$7($push); + var stringSlice$3 = uncurryThis$7(''.slice); + + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + // Weex JS has frozen built-in prototypes, so use try / catch wrapper + var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails$5(function () { + // eslint-disable-next-line regexp/no-empty-group -- required for testing + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b'; + }); + + // @@split logic + fixRegExpWellKnownSymbolLogic$1('split', function (SPLIT, nativeSplit, maybeCallNative) { + var internalSplit; + if ( + 'abbc'.split(/(b)*/)[1] === 'c' || + // eslint-disable-next-line regexp/no-empty-group -- required for testing + 'test'.split(/(?:)/, -1).length !== 4 || + 'ab'.split(/(?:ab)*/).length !== 2 || + '.'.split(/(.?)(.?)/).length !== 4 || + // eslint-disable-next-line regexp/no-empty-capturing-group, regexp/no-empty-group -- required for testing + '.'.split(/()()/).length > 1 || + ''.split(/.?/).length + ) { + // based on es5-shim implementation, need to rework it + internalSplit = function (separator, limit) { + var string = toString$3(requireObjectCoercible$3(this)); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (separator === undefined) return [string]; + // If `separator` is not a regex, use native split + if (!isRegExp(separator)) { + return call$4(nativeSplit, string, separator, lim); + } + var output = []; + var flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.unicode ? 'u' : '') + + (separator.sticky ? 'y' : ''); + var lastLastIndex = 0; + // Make `global` and avoid `lastIndex` issues by working with a copy + var separatorCopy = new RegExp(separator.source, flags + 'g'); + var match, lastIndex, lastLength; + while (match = call$4(regexpExec, separatorCopy, string)) { + lastIndex = separatorCopy.lastIndex; + if (lastIndex > lastLastIndex) { + push$3(output, stringSlice$3(string, lastLastIndex, match.index)); + if (match.length > 1 && match.index < string.length) apply($push, output, arraySlice$1(match, 1)); + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= lim) break; + } + if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop + } + if (lastLastIndex === string.length) { + if (lastLength || !exec$2(separatorCopy, '')) push$3(output, ''); + } else push$3(output, stringSlice$3(string, lastLastIndex)); + return output.length > lim ? arraySlice$1(output, 0, lim) : output; + }; + // Chakra, V8 + } else if ('0'.split(undefined, 0).length) { + internalSplit = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : call$4(nativeSplit, this, separator, limit); + }; + } else internalSplit = nativeSplit; + + return [ + // `String.prototype.split` method + // https://tc39.es/ecma262/#sec-string.prototype.split + function split(separator, limit) { + var O = requireObjectCoercible$3(this); + var splitter = isNullOrUndefined$2(separator) ? undefined : getMethod$1(separator, SPLIT); + return splitter + ? call$4(splitter, separator, O, limit) + : call$4(internalSplit, toString$3(O), separator, limit); + }, + // `RegExp.prototype[@@split]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@split + // + // NOTE: This cannot be properly polyfilled in engines that don't support + // the 'y' flag. + function (string, limit) { + var rx = anObject$4(this); + var S = toString$3(string); + var res = maybeCallNative(internalSplit, rx, S, limit, internalSplit !== nativeSplit); + + if (res.done) return res.value; + + var C = speciesConstructor(rx, RegExp); + + var unicodeMatching = rx.unicode; + var flags = (rx.ignoreCase ? 'i' : '') + + (rx.multiline ? 'm' : '') + + (rx.unicode ? 'u' : '') + + (UNSUPPORTED_Y ? 'g' : 'y'); + + // ^(? + rx + ) is needed, in combination with some S slicing, to + // simulate the 'y' flag. + var splitter = new C(UNSUPPORTED_Y ? '^(?:' + rx.source + ')' : rx, flags); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : []; + var p = 0; + var q = 0; + var A = []; + while (q < S.length) { + splitter.lastIndex = UNSUPPORTED_Y ? 0 : q; + var z = callRegExpExec(splitter, UNSUPPORTED_Y ? stringSlice$3(S, q) : S); + var e; + if ( + z === null || + (e = min(toLength$1(splitter.lastIndex + (UNSUPPORTED_Y ? q : 0)), S.length)) === p + ) { + q = advanceStringIndex(S, q, unicodeMatching); + } else { + push$3(A, stringSlice$3(S, p, q)); + if (A.length === lim) return A; + for (var i = 1; i <= z.length - 1; i++) { + push$3(A, z[i]); + if (A.length === lim) return A; + } + q = p = e; + } + } + push$3(A, stringSlice$3(S, p)); + return A; + } + ]; + }, !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y); + + var $$f = _export; + var lastIndexOf = arrayLastIndexOf; + + // `Array.prototype.lastIndexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.lastindexof + // eslint-disable-next-line es/no-array-prototype-lastindexof -- required for testing + $$f({ target: 'Array', proto: true, forced: lastIndexOf !== [].lastIndexOf }, { + lastIndexOf: lastIndexOf + }); + + var $$e = _export; + var global$4 = global$O; + var arrayBufferModule = arrayBuffer; + var setSpecies = setSpecies$5; + + var ARRAY_BUFFER = 'ArrayBuffer'; + var ArrayBuffer$1 = arrayBufferModule[ARRAY_BUFFER]; + var NativeArrayBuffer = global$4[ARRAY_BUFFER]; + + // `ArrayBuffer` constructor + // https://tc39.es/ecma262/#sec-arraybuffer-constructor + $$e({ global: true, constructor: true, forced: NativeArrayBuffer !== ArrayBuffer$1 }, { + ArrayBuffer: ArrayBuffer$1 + }); + + setSpecies(ARRAY_BUFFER); + + var $$d = _export; + var fill = arrayFill$1; + var addToUnscopables = addToUnscopables$4; + + // `Array.prototype.fill` method + // https://tc39.es/ecma262/#sec-array.prototype.fill + $$d({ target: 'Array', proto: true }, { + fill: fill + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables('fill'); + + var $$c = _export; + var fails$4 = fails$_; + var toObject = toObject$h; + var toPrimitive = toPrimitive$4; + + var FORCED$1 = fails$4(function () { + return new Date(NaN).toJSON() !== null + || Date.prototype.toJSON.call({ toISOString: function () { return 1; } }) !== 1; + }); + + // `Date.prototype.toJSON` method + // https://tc39.es/ecma262/#sec-date.prototype.tojson + $$c({ target: 'Date', proto: true, arity: 1, forced: FORCED$1 }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + toJSON: function toJSON(key) { + var O = toObject(this); + var pv = toPrimitive(O, 'number'); + return typeof pv == 'number' && !isFinite(pv) ? null : O.toISOString(); + } + }); + + var $$b = _export; + var call$3 = functionCall; + + // `URL.prototype.toJSON` method + // https://url.spec.whatwg.org/#dom-url-tojson + $$b({ target: 'URL', proto: true, enumerable: true }, { + toJSON: function toJSON() { + return call$3(URL.prototype.toString, this); + } + }); + + var toIntegerOrInfinity = toIntegerOrInfinity$a; + var toString$2 = toString$n; + var requireObjectCoercible$2 = requireObjectCoercible$f; + + var $RangeError$2 = RangeError; + + // `String.prototype.repeat` method implementation + // https://tc39.es/ecma262/#sec-string.prototype.repeat + var stringRepeat = function repeat(count) { + var str = toString$2(requireObjectCoercible$2(this)); + var result = ''; + var n = toIntegerOrInfinity(count); + if (n < 0 || n === Infinity) throw new $RangeError$2('Wrong number of repetitions'); + for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str; + return result; + }; + + var $$a = _export; + var repeat$1 = stringRepeat; + + // `String.prototype.repeat` method + // https://tc39.es/ecma262/#sec-string.prototype.repeat + $$a({ target: 'String', proto: true }, { + repeat: repeat$1 + }); + + var uncurryThis$6 = functionUncurryThis; + var defineBuiltIns$2 = defineBuiltIns$5; + var getWeakData = internalMetadataExports.getWeakData; + var anInstance$2 = anInstance$8; + var anObject$3 = anObject$p; + var isNullOrUndefined$1 = isNullOrUndefined$c; + var isObject$4 = isObject$t; + var iterate = iterate$5; + var ArrayIterationModule = arrayIteration; + var hasOwn$3 = hasOwnProperty_1; + var InternalStateModule$2 = internalState; + + var setInternalState$2 = InternalStateModule$2.set; + var internalStateGetterFor = InternalStateModule$2.getterFor; + var find$1 = ArrayIterationModule.find; + var findIndex = ArrayIterationModule.findIndex; + var splice$1 = uncurryThis$6([].splice); + var id = 0; + + // fallback for uncaught frozen keys + var uncaughtFrozenStore = function (state) { + return state.frozen || (state.frozen = new UncaughtFrozenStore()); + }; + + var UncaughtFrozenStore = function () { + this.entries = []; + }; + + var findUncaughtFrozen = function (store, key) { + return find$1(store.entries, function (it) { + return it[0] === key; + }); + }; + + UncaughtFrozenStore.prototype = { + get: function (key) { + var entry = findUncaughtFrozen(this, key); + if (entry) return entry[1]; + }, + has: function (key) { + return !!findUncaughtFrozen(this, key); + }, + set: function (key, value) { + var entry = findUncaughtFrozen(this, key); + if (entry) entry[1] = value; + else this.entries.push([key, value]); + }, + 'delete': function (key) { + var index = findIndex(this.entries, function (it) { + return it[0] === key; + }); + if (~index) splice$1(this.entries, index, 1); + return !!~index; + } + }; + + var collectionWeak$2 = { + getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) { + var Constructor = wrapper(function (that, iterable) { + anInstance$2(that, Prototype); + setInternalState$2(that, { + type: CONSTRUCTOR_NAME, + id: id++, + frozen: undefined + }); + if (!isNullOrUndefined$1(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP }); + }); + + var Prototype = Constructor.prototype; + + var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME); + + var define = function (that, key, value) { + var state = getInternalState(that); + var data = getWeakData(anObject$3(key), true); + if (data === true) uncaughtFrozenStore(state).set(key, value); + else data[state.id] = value; + return that; + }; + + defineBuiltIns$2(Prototype, { + // `{ WeakMap, WeakSet }.prototype.delete(key)` methods + // https://tc39.es/ecma262/#sec-weakmap.prototype.delete + // https://tc39.es/ecma262/#sec-weakset.prototype.delete + 'delete': function (key) { + var state = getInternalState(this); + if (!isObject$4(key)) return false; + var data = getWeakData(key); + if (data === true) return uncaughtFrozenStore(state)['delete'](key); + return data && hasOwn$3(data, state.id) && delete data[state.id]; + }, + // `{ WeakMap, WeakSet }.prototype.has(key)` methods + // https://tc39.es/ecma262/#sec-weakmap.prototype.has + // https://tc39.es/ecma262/#sec-weakset.prototype.has + has: function has(key) { + var state = getInternalState(this); + if (!isObject$4(key)) return false; + var data = getWeakData(key); + if (data === true) return uncaughtFrozenStore(state).has(key); + return data && hasOwn$3(data, state.id); + } + }); + + defineBuiltIns$2(Prototype, IS_MAP ? { + // `WeakMap.prototype.get(key)` method + // https://tc39.es/ecma262/#sec-weakmap.prototype.get + get: function get(key) { + var state = getInternalState(this); + if (isObject$4(key)) { + var data = getWeakData(key); + if (data === true) return uncaughtFrozenStore(state).get(key); + return data ? data[state.id] : undefined; + } + }, + // `WeakMap.prototype.set(key, value)` method + // https://tc39.es/ecma262/#sec-weakmap.prototype.set + set: function set(key, value) { + return define(this, key, value); + } + } : { + // `WeakSet.prototype.add(value)` method + // https://tc39.es/ecma262/#sec-weakset.prototype.add + add: function add(value) { + return define(this, value, true); + } + }); + + return Constructor; + } + }; + + var FREEZING = freezing; + var global$3 = global$O; + var uncurryThis$5 = functionUncurryThis; + var defineBuiltIns$1 = defineBuiltIns$5; + var InternalMetadataModule = internalMetadataExports; + var collection$1 = collection$4; + var collectionWeak$1 = collectionWeak$2; + var isObject$3 = isObject$t; + var enforceInternalState = internalState.enforce; + var fails$3 = fails$_; + var NATIVE_WEAK_MAP = weakMapBasicDetection; + + var $Object = Object; + // eslint-disable-next-line es/no-array-isarray -- safe + var isArray = Array.isArray; + // eslint-disable-next-line es/no-object-isextensible -- safe + var isExtensible = $Object.isExtensible; + // eslint-disable-next-line es/no-object-isfrozen -- safe + var isFrozen = $Object.isFrozen; + // eslint-disable-next-line es/no-object-issealed -- safe + var isSealed = $Object.isSealed; + // eslint-disable-next-line es/no-object-freeze -- safe + var freeze = $Object.freeze; + // eslint-disable-next-line es/no-object-seal -- safe + var seal = $Object.seal; + + var FROZEN = {}; + var SEALED = {}; + var IS_IE11 = !global$3.ActiveXObject && 'ActiveXObject' in global$3; + var InternalWeakMap; + + var wrapper = function (init) { + return function WeakMap() { + return init(this, arguments.length ? arguments[0] : undefined); + }; + }; + + // `WeakMap` constructor + // https://tc39.es/ecma262/#sec-weakmap-constructor + var $WeakMap = collection$1('WeakMap', wrapper, collectionWeak$1); + var WeakMapPrototype = $WeakMap.prototype; + var nativeSet = uncurryThis$5(WeakMapPrototype.set); + + // Chakra Edge bug: adding frozen arrays to WeakMap unfreeze them + var hasMSEdgeFreezingBug = function () { + return FREEZING && fails$3(function () { + var frozenArray = freeze([]); + nativeSet(new $WeakMap(), frozenArray, 1); + return !isFrozen(frozenArray); + }); + }; + + // IE11 WeakMap frozen keys fix + // We can't use feature detection because it crash some old IE builds + // https://github.com/zloirock/core-js/issues/485 + if (NATIVE_WEAK_MAP) if (IS_IE11) { + InternalWeakMap = collectionWeak$1.getConstructor(wrapper, 'WeakMap', true); + InternalMetadataModule.enable(); + var nativeDelete = uncurryThis$5(WeakMapPrototype['delete']); + var nativeHas = uncurryThis$5(WeakMapPrototype.has); + var nativeGet = uncurryThis$5(WeakMapPrototype.get); + defineBuiltIns$1(WeakMapPrototype, { + 'delete': function (key) { + if (isObject$3(key) && !isExtensible(key)) { + var state = enforceInternalState(this); + if (!state.frozen) state.frozen = new InternalWeakMap(); + return nativeDelete(this, key) || state.frozen['delete'](key); + } return nativeDelete(this, key); + }, + has: function has(key) { + if (isObject$3(key) && !isExtensible(key)) { + var state = enforceInternalState(this); + if (!state.frozen) state.frozen = new InternalWeakMap(); + return nativeHas(this, key) || state.frozen.has(key); + } return nativeHas(this, key); + }, + get: function get(key) { + if (isObject$3(key) && !isExtensible(key)) { + var state = enforceInternalState(this); + if (!state.frozen) state.frozen = new InternalWeakMap(); + return nativeHas(this, key) ? nativeGet(this, key) : state.frozen.get(key); + } return nativeGet(this, key); + }, + set: function set(key, value) { + if (isObject$3(key) && !isExtensible(key)) { + var state = enforceInternalState(this); + if (!state.frozen) state.frozen = new InternalWeakMap(); + nativeHas(this, key) ? nativeSet(this, key, value) : state.frozen.set(key, value); + } else nativeSet(this, key, value); + return this; + } + }); + // Chakra Edge frozen keys fix + } else if (hasMSEdgeFreezingBug()) { + defineBuiltIns$1(WeakMapPrototype, { + set: function set(key, value) { + var arrayIntegrityLevel; + if (isArray(key)) { + if (isFrozen(key)) arrayIntegrityLevel = FROZEN; + else if (isSealed(key)) arrayIntegrityLevel = SEALED; + } + nativeSet(this, key, value); + if (arrayIntegrityLevel === FROZEN) freeze(key); + if (arrayIntegrityLevel === SEALED) seal(key); + return this; + } + }); + } + + var collection = collection$4; + var collectionWeak = collectionWeak$2; + + // `WeakSet` constructor + // https://tc39.es/ecma262/#sec-weakset-constructor + collection('WeakSet', function (init) { + return function WeakSet() { return init(this, arguments.length ? arguments[0] : undefined); }; + }, collectionWeak); + + var $$9 = _export; + var ArrayBufferModule = arrayBuffer; + var NATIVE_ARRAY_BUFFER = arrayBufferBasicDetection; + + // `DataView` constructor + // https://tc39.es/ecma262/#sec-dataview-constructor + $$9({ global: true, constructor: true, forced: !NATIVE_ARRAY_BUFFER }, { + DataView: ArrayBufferModule.DataView + }); + + var $$8 = _export; + var $entries = objectToArray.entries; + + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + $$8({ target: 'Object', stat: true }, { + entries: function entries(O) { + return $entries(O); + } + }); + + // `SameValue` abstract operation + // https://tc39.es/ecma262/#sec-samevalue + // eslint-disable-next-line es/no-object-is -- safe + var sameValue$1 = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare -- NaN check + return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; + }; + + var call$2 = functionCall; + var fixRegExpWellKnownSymbolLogic = fixRegexpWellKnownSymbolLogic; + var anObject$2 = anObject$p; + var isNullOrUndefined = isNullOrUndefined$c; + var requireObjectCoercible$1 = requireObjectCoercible$f; + var sameValue = sameValue$1; + var toString$1 = toString$n; + var getMethod = getMethod$8; + var regExpExec = regexpExecAbstract; + + // @@search logic + fixRegExpWellKnownSymbolLogic('search', function (SEARCH, nativeSearch, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.es/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = requireObjectCoercible$1(this); + var searcher = isNullOrUndefined(regexp) ? undefined : getMethod(regexp, SEARCH); + return searcher ? call$2(searcher, regexp, O) : new RegExp(regexp)[SEARCH](toString$1(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@search + function (string) { + var rx = anObject$2(this); + var S = toString$1(string); + var res = maybeCallNative(nativeSearch, rx, S); + + if (res.done) return res.value; + + var previousLastIndex = rx.lastIndex; + if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = regExpExec(rx, S); + if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; + }); + + var fails$2 = fails$_; + var wellKnownSymbol$1 = wellKnownSymbol$x; + var DESCRIPTORS$2 = descriptors; + var IS_PURE = isPure; + + var ITERATOR$1 = wellKnownSymbol$1('iterator'); + + var urlConstructorDetection = !fails$2(function () { + // eslint-disable-next-line unicorn/relative-url-style -- required for testing + var url = new URL('b?a=1&b=2&c=3', 'http://a'); + var params = url.searchParams; + var params2 = new URLSearchParams('a=1&a=2&b=3'); + var result = ''; + url.pathname = 'c%20d'; + params.forEach(function (value, key) { + params['delete']('b'); + result += key + value; + }); + params2['delete']('a', 2); + // `undefined` case is a Chromium 117 bug + // https://bugs.chromium.org/p/v8/issues/detail?id=14222 + params2['delete']('b', undefined); + return (IS_PURE && (!url.toJSON || !params2.has('a', 1) || params2.has('a', 2) || !params2.has('a', undefined) || params2.has('b'))) + || (!params.size && (IS_PURE || !DESCRIPTORS$2)) + || !params.sort + || url.href !== 'http://a/c%20d?a=1&c=3' + || params.get('c') !== '3' + || String(new URLSearchParams('?a=1')) !== 'a=1' + || !params[ITERATOR$1] + // throws in Edge + || new URL('https://a@b').username !== 'a' + || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b' + // not punycoded in Edge + || new URL('http://тест').host !== 'xn--e1aybc' + // not escaped in Chrome 62- + || new URL('http://a#б').hash !== '#%D0%B1' + // fails in Chrome 66- + || result !== 'a1c3' + // throws in Safari + || new URL('http://x', undefined).host !== 'x'; + }); + + // based on https://github.com/bestiejs/punycode.js/blob/master/punycode.js + var uncurryThis$4 = functionUncurryThis; + + var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 + var base = 36; + var tMin = 1; + var tMax = 26; + var skew = 38; + var damp = 700; + var initialBias = 72; + var initialN = 128; // 0x80 + var delimiter = '-'; // '\x2D' + var regexNonASCII = /[^\0-\u007E]/; // non-ASCII chars + var regexSeparators = /[.\u3002\uFF0E\uFF61]/g; // RFC 3490 separators + var OVERFLOW_ERROR = 'Overflow: input needs wider integers to process'; + var baseMinusTMin = base - tMin; + + var $RangeError$1 = RangeError; + var exec$1 = uncurryThis$4(regexSeparators.exec); + var floor$1 = Math.floor; + var fromCharCode = String.fromCharCode; + var charCodeAt = uncurryThis$4(''.charCodeAt); + var join$2 = uncurryThis$4([].join); + var push$2 = uncurryThis$4([].push); + var replace$2 = uncurryThis$4(''.replace); + var split$2 = uncurryThis$4(''.split); + var toLowerCase$1 = uncurryThis$4(''.toLowerCase); + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + */ + var ucs2decode = function (string) { + var output = []; + var counter = 0; + var length = string.length; + while (counter < length) { + var value = charCodeAt(string, counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // It's a high surrogate, and there is a next character. + var extra = charCodeAt(string, counter++); + if ((extra & 0xFC00) === 0xDC00) { // Low surrogate. + push$2(output, ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // It's an unmatched surrogate; only append this code unit, in case the + // next code unit is the high surrogate of a surrogate pair. + push$2(output, value); + counter--; + } + } else { + push$2(output, value); + } + } + return output; + }; + + /** + * Converts a digit/integer into a basic code point. + */ + var digitToBasic = function (digit) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26); + }; + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + */ + var adapt = function (delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor$1(delta / damp) : delta >> 1; + delta += floor$1(delta / numPoints); + while (delta > baseMinusTMin * tMax >> 1) { + delta = floor$1(delta / baseMinusTMin); + k += base; + } + return floor$1(k + (baseMinusTMin + 1) * delta / (delta + skew)); + }; + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + */ + var encode = function (input) { + var output = []; + + // Convert the input in UCS-2 to an array of Unicode code points. + input = ucs2decode(input); + + // Cache the length. + var inputLength = input.length; + + // Initialize the state. + var n = initialN; + var delta = 0; + var bias = initialBias; + var i, currentValue; + + // Handle the basic code points. + for (i = 0; i < input.length; i++) { + currentValue = input[i]; + if (currentValue < 0x80) { + push$2(output, fromCharCode(currentValue)); + } + } + + var basicLength = output.length; // number of basic code points. + var handledCPCount = basicLength; // number of code points that have been handled; + + // Finish the basic string with a delimiter unless it's empty. + if (basicLength) { + push$2(output, delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + // All non-basic code points < n have been handled already. Find the next larger one: + var m = maxInt; + for (i = 0; i < input.length; i++) { + currentValue = input[i]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , but guard against overflow. + var handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor$1((maxInt - delta) / handledCPCountPlusOne)) { + throw new $RangeError$1(OVERFLOW_ERROR); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (i = 0; i < input.length; i++) { + currentValue = input[i]; + if (currentValue < n && ++delta > maxInt) { + throw new $RangeError$1(OVERFLOW_ERROR); + } + if (currentValue === n) { + // Represent delta as a generalized variable-length integer. + var q = delta; + var k = base; + while (true) { + var t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias; + if (q < t) break; + var qMinusT = q - t; + var baseMinusT = base - t; + push$2(output, fromCharCode(digitToBasic(t + qMinusT % baseMinusT))); + q = floor$1(qMinusT / baseMinusT); + k += base; + } + + push$2(output, fromCharCode(digitToBasic(q))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength); + delta = 0; + handledCPCount++; + } + } + + delta++; + n++; + } + return join$2(output, ''); + }; + + var stringPunycodeToAscii = function (input) { + var encoded = []; + var labels = split$2(replace$2(toLowerCase$1(input), regexSeparators, '\u002E'), '.'); + var i, label; + for (i = 0; i < labels.length; i++) { + label = labels[i]; + push$2(encoded, exec$1(regexNonASCII, label) ? 'xn--' + encode(label) : label); + } + return join$2(encoded, '.'); + }; + + // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` + + var $$7 = _export; + var global$2 = global$O; + var call$1 = functionCall; + var uncurryThis$3 = functionUncurryThis; + var DESCRIPTORS$1 = descriptors; + var USE_NATIVE_URL$1 = urlConstructorDetection; + var defineBuiltIn$1 = defineBuiltIn$i; + var defineBuiltInAccessor$1 = defineBuiltInAccessor$b; + var defineBuiltIns = defineBuiltIns$5; + var setToStringTag$1 = setToStringTag$b; + var createIteratorConstructor = iteratorCreateConstructor; + var InternalStateModule$1 = internalState; + var anInstance$1 = anInstance$8; + var isCallable = isCallable$w; + var hasOwn$2 = hasOwnProperty_1; + var bind$1 = functionBindContext; + var classof$1 = classof$i; + var anObject$1 = anObject$p; + var isObject$2 = isObject$t; + var $toString$1 = toString$n; + var create = objectCreate; + var createPropertyDescriptor = createPropertyDescriptor$7; + var getIterator = getIterator$4; + var getIteratorMethod = getIteratorMethod$5; + var validateArgumentsLength$1 = validateArgumentsLength$4; + var wellKnownSymbol = wellKnownSymbol$x; + var arraySort = arraySort$1; + + var ITERATOR = wellKnownSymbol('iterator'); + var URL_SEARCH_PARAMS = 'URLSearchParams'; + var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator'; + var setInternalState$1 = InternalStateModule$1.set; + var getInternalParamsState = InternalStateModule$1.getterFor(URL_SEARCH_PARAMS); + var getInternalIteratorState = InternalStateModule$1.getterFor(URL_SEARCH_PARAMS_ITERATOR); + // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + + // Avoid NodeJS experimental warning + var safeGetBuiltIn = function (name) { + if (!DESCRIPTORS$1) return global$2[name]; + var descriptor = getOwnPropertyDescriptor(global$2, name); + return descriptor && descriptor.value; + }; + + var nativeFetch = safeGetBuiltIn('fetch'); + var NativeRequest = safeGetBuiltIn('Request'); + var Headers = safeGetBuiltIn('Headers'); + var RequestPrototype = NativeRequest && NativeRequest.prototype; + var HeadersPrototype = Headers && Headers.prototype; + var RegExp$1 = global$2.RegExp; + var TypeError$2 = global$2.TypeError; + var decodeURIComponent$1 = global$2.decodeURIComponent; + var encodeURIComponent$1 = global$2.encodeURIComponent; + var charAt$1 = uncurryThis$3(''.charAt); + var join$1 = uncurryThis$3([].join); + var push$1 = uncurryThis$3([].push); + var replace$1 = uncurryThis$3(''.replace); + var shift$1 = uncurryThis$3([].shift); + var splice = uncurryThis$3([].splice); + var split$1 = uncurryThis$3(''.split); + var stringSlice$2 = uncurryThis$3(''.slice); + + var plus = /\+/g; + var sequences = Array(4); + + var percentSequence = function (bytes) { + return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp$1('((?:%[\\da-f]{2}){' + bytes + '})', 'gi')); + }; + + var percentDecode = function (sequence) { + try { + return decodeURIComponent$1(sequence); + } catch (error) { + return sequence; + } + }; + + var deserialize = function (it) { + var result = replace$1(it, plus, ' '); + var bytes = 4; + try { + return decodeURIComponent$1(result); + } catch (error) { + while (bytes) { + result = replace$1(result, percentSequence(bytes--), percentDecode); + } + return result; + } + }; + + var find = /[!'()~]|%20/g; + + var replacements = { + '!': '%21', + "'": '%27', + '(': '%28', + ')': '%29', + '~': '%7E', + '%20': '+' + }; + + var replacer = function (match) { + return replacements[match]; + }; + + var serialize = function (it) { + return replace$1(encodeURIComponent$1(it), find, replacer); + }; + + var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) { + setInternalState$1(this, { + type: URL_SEARCH_PARAMS_ITERATOR, + iterator: getIterator(getInternalParamsState(params).entries), + kind: kind + }); + }, 'Iterator', function next() { + var state = getInternalIteratorState(this); + var kind = state.kind; + var step = state.iterator.next(); + var entry = step.value; + if (!step.done) { + step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value]; + } return step; + }, true); + + var URLSearchParamsState = function (init) { + this.entries = []; + this.url = null; + + if (init !== undefined) { + if (isObject$2(init)) this.parseObject(init); + else this.parseQuery(typeof init == 'string' ? charAt$1(init, 0) === '?' ? stringSlice$2(init, 1) : init : $toString$1(init)); + } + }; + + URLSearchParamsState.prototype = { + type: URL_SEARCH_PARAMS, + bindURL: function (url) { + this.url = url; + this.update(); + }, + parseObject: function (object) { + var iteratorMethod = getIteratorMethod(object); + var iterator, next, step, entryIterator, entryNext, first, second; + + if (iteratorMethod) { + iterator = getIterator(object, iteratorMethod); + next = iterator.next; + while (!(step = call$1(next, iterator)).done) { + entryIterator = getIterator(anObject$1(step.value)); + entryNext = entryIterator.next; + if ( + (first = call$1(entryNext, entryIterator)).done || + (second = call$1(entryNext, entryIterator)).done || + !call$1(entryNext, entryIterator).done + ) throw new TypeError$2('Expected sequence with length 2'); + push$1(this.entries, { key: $toString$1(first.value), value: $toString$1(second.value) }); + } + } else for (var key in object) if (hasOwn$2(object, key)) { + push$1(this.entries, { key: key, value: $toString$1(object[key]) }); + } + }, + parseQuery: function (query) { + if (query) { + var attributes = split$1(query, '&'); + var index = 0; + var attribute, entry; + while (index < attributes.length) { + attribute = attributes[index++]; + if (attribute.length) { + entry = split$1(attribute, '='); + push$1(this.entries, { + key: deserialize(shift$1(entry)), + value: deserialize(join$1(entry, '=')) + }); + } + } + } + }, + serialize: function () { + var entries = this.entries; + var result = []; + var index = 0; + var entry; + while (index < entries.length) { + entry = entries[index++]; + push$1(result, serialize(entry.key) + '=' + serialize(entry.value)); + } return join$1(result, '&'); + }, + update: function () { + this.entries.length = 0; + this.parseQuery(this.url.query); + }, + updateURL: function () { + if (this.url) this.url.update(); + } + }; + + // `URLSearchParams` constructor + // https://url.spec.whatwg.org/#interface-urlsearchparams + var URLSearchParamsConstructor = function URLSearchParams(/* init */) { + anInstance$1(this, URLSearchParamsPrototype); + var init = arguments.length > 0 ? arguments[0] : undefined; + var state = setInternalState$1(this, new URLSearchParamsState(init)); + if (!DESCRIPTORS$1) this.size = state.entries.length; + }; + + var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype; + + defineBuiltIns(URLSearchParamsPrototype, { + // `URLSearchParams.prototype.append` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-append + append: function append(name, value) { + var state = getInternalParamsState(this); + validateArgumentsLength$1(arguments.length, 2); + push$1(state.entries, { key: $toString$1(name), value: $toString$1(value) }); + if (!DESCRIPTORS$1) this.length++; + state.updateURL(); + }, + // `URLSearchParams.prototype.delete` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-delete + 'delete': function (name /* , value */) { + var state = getInternalParamsState(this); + var length = validateArgumentsLength$1(arguments.length, 1); + var entries = state.entries; + var key = $toString$1(name); + var $value = length < 2 ? undefined : arguments[1]; + var value = $value === undefined ? $value : $toString$1($value); + var index = 0; + while (index < entries.length) { + var entry = entries[index]; + if (entry.key === key && (value === undefined || entry.value === value)) { + splice(entries, index, 1); + if (value !== undefined) break; + } else index++; + } + if (!DESCRIPTORS$1) this.size = entries.length; + state.updateURL(); + }, + // `URLSearchParams.prototype.get` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-get + get: function get(name) { + var entries = getInternalParamsState(this).entries; + validateArgumentsLength$1(arguments.length, 1); + var key = $toString$1(name); + var index = 0; + for (; index < entries.length; index++) { + if (entries[index].key === key) return entries[index].value; + } + return null; + }, + // `URLSearchParams.prototype.getAll` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-getall + getAll: function getAll(name) { + var entries = getInternalParamsState(this).entries; + validateArgumentsLength$1(arguments.length, 1); + var key = $toString$1(name); + var result = []; + var index = 0; + for (; index < entries.length; index++) { + if (entries[index].key === key) push$1(result, entries[index].value); + } + return result; + }, + // `URLSearchParams.prototype.has` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-has + has: function has(name /* , value */) { + var entries = getInternalParamsState(this).entries; + var length = validateArgumentsLength$1(arguments.length, 1); + var key = $toString$1(name); + var $value = length < 2 ? undefined : arguments[1]; + var value = $value === undefined ? $value : $toString$1($value); + var index = 0; + while (index < entries.length) { + var entry = entries[index++]; + if (entry.key === key && (value === undefined || entry.value === value)) return true; + } + return false; + }, + // `URLSearchParams.prototype.set` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-set + set: function set(name, value) { + var state = getInternalParamsState(this); + validateArgumentsLength$1(arguments.length, 1); + var entries = state.entries; + var found = false; + var key = $toString$1(name); + var val = $toString$1(value); + var index = 0; + var entry; + for (; index < entries.length; index++) { + entry = entries[index]; + if (entry.key === key) { + if (found) splice(entries, index--, 1); + else { + found = true; + entry.value = val; + } + } + } + if (!found) push$1(entries, { key: key, value: val }); + if (!DESCRIPTORS$1) this.size = entries.length; + state.updateURL(); + }, + // `URLSearchParams.prototype.sort` method + // https://url.spec.whatwg.org/#dom-urlsearchparams-sort + sort: function sort() { + var state = getInternalParamsState(this); + arraySort(state.entries, function (a, b) { + return a.key > b.key ? 1 : -1; + }); + state.updateURL(); + }, + // `URLSearchParams.prototype.forEach` method + forEach: function forEach(callback /* , thisArg */) { + var entries = getInternalParamsState(this).entries; + var boundFunction = bind$1(callback, arguments.length > 1 ? arguments[1] : undefined); + var index = 0; + var entry; + while (index < entries.length) { + entry = entries[index++]; + boundFunction(entry.value, entry.key, this); + } + }, + // `URLSearchParams.prototype.keys` method + keys: function keys() { + return new URLSearchParamsIterator(this, 'keys'); + }, + // `URLSearchParams.prototype.values` method + values: function values() { + return new URLSearchParamsIterator(this, 'values'); + }, + // `URLSearchParams.prototype.entries` method + entries: function entries() { + return new URLSearchParamsIterator(this, 'entries'); + } + }, { enumerable: true }); + + // `URLSearchParams.prototype[@@iterator]` method + defineBuiltIn$1(URLSearchParamsPrototype, ITERATOR, URLSearchParamsPrototype.entries, { name: 'entries' }); + + // `URLSearchParams.prototype.toString` method + // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior + defineBuiltIn$1(URLSearchParamsPrototype, 'toString', function toString() { + return getInternalParamsState(this).serialize(); + }, { enumerable: true }); + + // `URLSearchParams.prototype.size` getter + // https://github.com/whatwg/url/pull/734 + if (DESCRIPTORS$1) defineBuiltInAccessor$1(URLSearchParamsPrototype, 'size', { + get: function size() { + return getInternalParamsState(this).entries.length; + }, + configurable: true, + enumerable: true + }); + + setToStringTag$1(URLSearchParamsConstructor, URL_SEARCH_PARAMS); + + $$7({ global: true, constructor: true, forced: !USE_NATIVE_URL$1 }, { + URLSearchParams: URLSearchParamsConstructor + }); + + // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams` + if (!USE_NATIVE_URL$1 && isCallable(Headers)) { + var headersHas = uncurryThis$3(HeadersPrototype.has); + var headersSet = uncurryThis$3(HeadersPrototype.set); + + var wrapRequestOptions = function (init) { + if (isObject$2(init)) { + var body = init.body; + var headers; + if (classof$1(body) === URL_SEARCH_PARAMS) { + headers = init.headers ? new Headers(init.headers) : new Headers(); + if (!headersHas(headers, 'content-type')) { + headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); + } + return create(init, { + body: createPropertyDescriptor(0, $toString$1(body)), + headers: createPropertyDescriptor(0, headers) + }); + } + } return init; + }; + + if (isCallable(nativeFetch)) { + $$7({ global: true, enumerable: true, dontCallGetSet: true, forced: true }, { + fetch: function fetch(input /* , init */) { + return nativeFetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {}); + } + }); + } + + if (isCallable(NativeRequest)) { + var RequestConstructor = function Request(input /* , init */) { + anInstance$1(this, RequestPrototype); + return new NativeRequest(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {}); + }; + + RequestPrototype.constructor = RequestConstructor; + RequestConstructor.prototype = RequestPrototype; + + $$7({ global: true, constructor: true, dontCallGetSet: true, forced: true }, { + Request: RequestConstructor + }); + } + } + + var web_urlSearchParams_constructor = { + URLSearchParams: URLSearchParamsConstructor, + getState: getInternalParamsState + }; + + // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` + + var $$6 = _export; + var DESCRIPTORS = descriptors; + var USE_NATIVE_URL = urlConstructorDetection; + var global$1 = global$O; + var bind = functionBindContext; + var uncurryThis$2 = functionUncurryThis; + var defineBuiltIn = defineBuiltIn$i; + var defineBuiltInAccessor = defineBuiltInAccessor$b; + var anInstance = anInstance$8; + var hasOwn$1 = hasOwnProperty_1; + var assign = objectAssign; + var arrayFrom = arrayFrom$1; + var arraySlice = arraySliceSimple; + var codeAt = stringMultibyte.codeAt; + var toASCII = stringPunycodeToAscii; + var $toString = toString$n; + var setToStringTag = setToStringTag$b; + var validateArgumentsLength = validateArgumentsLength$4; + var URLSearchParamsModule = web_urlSearchParams_constructor; + var InternalStateModule = internalState; + + var setInternalState = InternalStateModule.set; + var getInternalURLState = InternalStateModule.getterFor('URL'); + var URLSearchParams$1 = URLSearchParamsModule.URLSearchParams; + var getInternalSearchParamsState = URLSearchParamsModule.getState; + + var NativeURL = global$1.URL; + var TypeError$1 = global$1.TypeError; + var parseInt$1 = global$1.parseInt; + var floor = Math.floor; + var pow = Math.pow; + var charAt = uncurryThis$2(''.charAt); + var exec = uncurryThis$2(/./.exec); + var join = uncurryThis$2([].join); + var numberToString = uncurryThis$2(1.0.toString); + var pop = uncurryThis$2([].pop); + var push = uncurryThis$2([].push); + var replace = uncurryThis$2(''.replace); + var shift = uncurryThis$2([].shift); + var split = uncurryThis$2(''.split); + var stringSlice$1 = uncurryThis$2(''.slice); + var toLowerCase = uncurryThis$2(''.toLowerCase); + var unshift = uncurryThis$2([].unshift); + + var INVALID_AUTHORITY = 'Invalid authority'; + var INVALID_SCHEME = 'Invalid scheme'; + var INVALID_HOST = 'Invalid host'; + var INVALID_PORT = 'Invalid port'; + + var ALPHA = /[a-z]/i; + // eslint-disable-next-line regexp/no-obscure-range -- safe + var ALPHANUMERIC = /[\d+-.a-z]/i; + var DIGIT = /\d/; + var HEX_START = /^0x/i; + var OCT = /^[0-7]+$/; + var DEC = /^\d+$/; + var HEX = /^[\da-f]+$/i; + /* eslint-disable regexp/no-control-character -- safe */ + var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/; + var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/; + var LEADING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+/; + var TRAILING_C0_CONTROL_OR_SPACE = /(^|[^\u0000-\u0020])[\u0000-\u0020]+$/; + var TAB_AND_NEW_LINE = /[\t\n\r]/g; + /* eslint-enable regexp/no-control-character -- safe */ + var EOF; + + // https://url.spec.whatwg.org/#ipv4-number-parser + var parseIPv4 = function (input) { + var parts = split(input, '.'); + var partsLength, numbers, index, part, radix, number, ipv4; + if (parts.length && parts[parts.length - 1] === '') { + parts.length--; + } + partsLength = parts.length; + if (partsLength > 4) return input; + numbers = []; + for (index = 0; index < partsLength; index++) { + part = parts[index]; + if (part === '') return input; + radix = 10; + if (part.length > 1 && charAt(part, 0) === '0') { + radix = exec(HEX_START, part) ? 16 : 8; + part = stringSlice$1(part, radix === 8 ? 1 : 2); + } + if (part === '') { + number = 0; + } else { + if (!exec(radix === 10 ? DEC : radix === 8 ? OCT : HEX, part)) return input; + number = parseInt$1(part, radix); + } + push(numbers, number); + } + for (index = 0; index < partsLength; index++) { + number = numbers[index]; + if (index === partsLength - 1) { + if (number >= pow(256, 5 - partsLength)) return null; + } else if (number > 255) return null; + } + ipv4 = pop(numbers); + for (index = 0; index < numbers.length; index++) { + ipv4 += numbers[index] * pow(256, 3 - index); + } + return ipv4; + }; + + // https://url.spec.whatwg.org/#concept-ipv6-parser + // eslint-disable-next-line max-statements -- TODO + var parseIPv6 = function (input) { + var address = [0, 0, 0, 0, 0, 0, 0, 0]; + var pieceIndex = 0; + var compress = null; + var pointer = 0; + var value, length, numbersSeen, ipv4Piece, number, swaps, swap; + + var chr = function () { + return charAt(input, pointer); + }; + + if (chr() === ':') { + if (charAt(input, 1) !== ':') return; + pointer += 2; + pieceIndex++; + compress = pieceIndex; + } + while (chr()) { + if (pieceIndex === 8) return; + if (chr() === ':') { + if (compress !== null) return; + pointer++; + pieceIndex++; + compress = pieceIndex; + continue; + } + value = length = 0; + while (length < 4 && exec(HEX, chr())) { + value = value * 16 + parseInt$1(chr(), 16); + pointer++; + length++; + } + if (chr() === '.') { + if (length === 0) return; + pointer -= length; + if (pieceIndex > 6) return; + numbersSeen = 0; + while (chr()) { + ipv4Piece = null; + if (numbersSeen > 0) { + if (chr() === '.' && numbersSeen < 4) pointer++; + else return; + } + if (!exec(DIGIT, chr())) return; + while (exec(DIGIT, chr())) { + number = parseInt$1(chr(), 10); + if (ipv4Piece === null) ipv4Piece = number; + else if (ipv4Piece === 0) return; + else ipv4Piece = ipv4Piece * 10 + number; + if (ipv4Piece > 255) return; + pointer++; + } + address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece; + numbersSeen++; + if (numbersSeen === 2 || numbersSeen === 4) pieceIndex++; + } + if (numbersSeen !== 4) return; + break; + } else if (chr() === ':') { + pointer++; + if (!chr()) return; + } else if (chr()) return; + address[pieceIndex++] = value; + } + if (compress !== null) { + swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + swap = address[pieceIndex]; + address[pieceIndex--] = address[compress + swaps - 1]; + address[compress + --swaps] = swap; + } + } else if (pieceIndex !== 8) return; + return address; + }; + + var findLongestZeroSequence = function (ipv6) { + var maxIndex = null; + var maxLength = 1; + var currStart = null; + var currLength = 0; + var index = 0; + for (; index < 8; index++) { + if (ipv6[index] !== 0) { + if (currLength > maxLength) { + maxIndex = currStart; + maxLength = currLength; + } + currStart = null; + currLength = 0; + } else { + if (currStart === null) currStart = index; + ++currLength; + } + } + if (currLength > maxLength) { + maxIndex = currStart; + maxLength = currLength; + } + return maxIndex; + }; + + // https://url.spec.whatwg.org/#host-serializing + var serializeHost = function (host) { + var result, index, compress, ignore0; + // ipv4 + if (typeof host == 'number') { + result = []; + for (index = 0; index < 4; index++) { + unshift(result, host % 256); + host = floor(host / 256); + } return join(result, '.'); + // ipv6 + } else if (typeof host == 'object') { + result = ''; + compress = findLongestZeroSequence(host); + for (index = 0; index < 8; index++) { + if (ignore0 && host[index] === 0) continue; + if (ignore0) ignore0 = false; + if (compress === index) { + result += index ? ':' : '::'; + ignore0 = true; + } else { + result += numberToString(host[index], 16); + if (index < 7) result += ':'; + } + } + return '[' + result + ']'; + } return host; + }; + + var C0ControlPercentEncodeSet = {}; + var fragmentPercentEncodeSet = assign({}, C0ControlPercentEncodeSet, { + ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1 + }); + var pathPercentEncodeSet = assign({}, fragmentPercentEncodeSet, { + '#': 1, '?': 1, '{': 1, '}': 1 + }); + var userinfoPercentEncodeSet = assign({}, pathPercentEncodeSet, { + '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1 + }); + + var percentEncode = function (chr, set) { + var code = codeAt(chr, 0); + return code > 0x20 && code < 0x7F && !hasOwn$1(set, chr) ? chr : encodeURIComponent(chr); + }; + + // https://url.spec.whatwg.org/#special-scheme + var specialSchemes = { + ftp: 21, + file: null, + http: 80, + https: 443, + ws: 80, + wss: 443 + }; + + // https://url.spec.whatwg.org/#windows-drive-letter + var isWindowsDriveLetter = function (string, normalized) { + var second; + return string.length === 2 && exec(ALPHA, charAt(string, 0)) + && ((second = charAt(string, 1)) === ':' || (!normalized && second === '|')); + }; + + // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter + var startsWithWindowsDriveLetter = function (string) { + var third; + return string.length > 1 && isWindowsDriveLetter(stringSlice$1(string, 0, 2)) && ( + string.length === 2 || + ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#') + ); + }; + + // https://url.spec.whatwg.org/#single-dot-path-segment + var isSingleDot = function (segment) { + return segment === '.' || toLowerCase(segment) === '%2e'; + }; + + // https://url.spec.whatwg.org/#double-dot-path-segment + var isDoubleDot = function (segment) { + segment = toLowerCase(segment); + return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e'; + }; + + // States: + var SCHEME_START = {}; + var SCHEME = {}; + var NO_SCHEME = {}; + var SPECIAL_RELATIVE_OR_AUTHORITY = {}; + var PATH_OR_AUTHORITY = {}; + var RELATIVE = {}; + var RELATIVE_SLASH = {}; + var SPECIAL_AUTHORITY_SLASHES = {}; + var SPECIAL_AUTHORITY_IGNORE_SLASHES = {}; + var AUTHORITY = {}; + var HOST = {}; + var HOSTNAME = {}; + var PORT = {}; + var FILE = {}; + var FILE_SLASH = {}; + var FILE_HOST = {}; + var PATH_START = {}; + var PATH = {}; + var CANNOT_BE_A_BASE_URL_PATH = {}; + var QUERY = {}; + var FRAGMENT = {}; + + var URLState = function (url, isBase, base) { + var urlString = $toString(url); + var baseState, failure, searchParams; + if (isBase) { + failure = this.parse(urlString); + if (failure) throw new TypeError$1(failure); + this.searchParams = null; + } else { + if (base !== undefined) baseState = new URLState(base, true); + failure = this.parse(urlString, null, baseState); + if (failure) throw new TypeError$1(failure); + searchParams = getInternalSearchParamsState(new URLSearchParams$1()); + searchParams.bindURL(this); + this.searchParams = searchParams; + } + }; + + URLState.prototype = { + type: 'URL', + // https://url.spec.whatwg.org/#url-parsing + // eslint-disable-next-line max-statements -- TODO + parse: function (input, stateOverride, base) { + var url = this; + var state = stateOverride || SCHEME_START; + var pointer = 0; + var buffer = ''; + var seenAt = false; + var seenBracket = false; + var seenPasswordToken = false; + var codePoints, chr, bufferCodePoints, failure; + + input = $toString(input); + + if (!stateOverride) { + url.scheme = ''; + url.username = ''; + url.password = ''; + url.host = null; + url.port = null; + url.path = []; + url.query = null; + url.fragment = null; + url.cannotBeABaseURL = false; + input = replace(input, LEADING_C0_CONTROL_OR_SPACE, ''); + input = replace(input, TRAILING_C0_CONTROL_OR_SPACE, '$1'); + } + + input = replace(input, TAB_AND_NEW_LINE, ''); + + codePoints = arrayFrom(input); + + while (pointer <= codePoints.length) { + chr = codePoints[pointer]; + switch (state) { + case SCHEME_START: + if (chr && exec(ALPHA, chr)) { + buffer += toLowerCase(chr); + state = SCHEME; + } else if (!stateOverride) { + state = NO_SCHEME; + continue; + } else return INVALID_SCHEME; + break; + + case SCHEME: + if (chr && (exec(ALPHANUMERIC, chr) || chr === '+' || chr === '-' || chr === '.')) { + buffer += toLowerCase(chr); + } else if (chr === ':') { + if (stateOverride && ( + (url.isSpecial() !== hasOwn$1(specialSchemes, buffer)) || + (buffer === 'file' && (url.includesCredentials() || url.port !== null)) || + (url.scheme === 'file' && !url.host) + )) return; + url.scheme = buffer; + if (stateOverride) { + if (url.isSpecial() && specialSchemes[url.scheme] === url.port) url.port = null; + return; + } + buffer = ''; + if (url.scheme === 'file') { + state = FILE; + } else if (url.isSpecial() && base && base.scheme === url.scheme) { + state = SPECIAL_RELATIVE_OR_AUTHORITY; + } else if (url.isSpecial()) { + state = SPECIAL_AUTHORITY_SLASHES; + } else if (codePoints[pointer + 1] === '/') { + state = PATH_OR_AUTHORITY; + pointer++; + } else { + url.cannotBeABaseURL = true; + push(url.path, ''); + state = CANNOT_BE_A_BASE_URL_PATH; + } + } else if (!stateOverride) { + buffer = ''; + state = NO_SCHEME; + pointer = 0; + continue; + } else return INVALID_SCHEME; + break; + + case NO_SCHEME: + if (!base || (base.cannotBeABaseURL && chr !== '#')) return INVALID_SCHEME; + if (base.cannotBeABaseURL && chr === '#') { + url.scheme = base.scheme; + url.path = arraySlice(base.path); + url.query = base.query; + url.fragment = ''; + url.cannotBeABaseURL = true; + state = FRAGMENT; + break; + } + state = base.scheme === 'file' ? FILE : RELATIVE; + continue; + + case SPECIAL_RELATIVE_OR_AUTHORITY: + if (chr === '/' && codePoints[pointer + 1] === '/') { + state = SPECIAL_AUTHORITY_IGNORE_SLASHES; + pointer++; + } else { + state = RELATIVE; + continue; + } break; + + case PATH_OR_AUTHORITY: + if (chr === '/') { + state = AUTHORITY; + break; + } else { + state = PATH; + continue; + } + + case RELATIVE: + url.scheme = base.scheme; + if (chr === EOF) { + url.username = base.username; + url.password = base.password; + url.host = base.host; + url.port = base.port; + url.path = arraySlice(base.path); + url.query = base.query; + } else if (chr === '/' || (chr === '\\' && url.isSpecial())) { + state = RELATIVE_SLASH; + } else if (chr === '?') { + url.username = base.username; + url.password = base.password; + url.host = base.host; + url.port = base.port; + url.path = arraySlice(base.path); + url.query = ''; + state = QUERY; + } else if (chr === '#') { + url.username = base.username; + url.password = base.password; + url.host = base.host; + url.port = base.port; + url.path = arraySlice(base.path); + url.query = base.query; + url.fragment = ''; + state = FRAGMENT; + } else { + url.username = base.username; + url.password = base.password; + url.host = base.host; + url.port = base.port; + url.path = arraySlice(base.path); + url.path.length--; + state = PATH; + continue; + } break; + + case RELATIVE_SLASH: + if (url.isSpecial() && (chr === '/' || chr === '\\')) { + state = SPECIAL_AUTHORITY_IGNORE_SLASHES; + } else if (chr === '/') { + state = AUTHORITY; + } else { + url.username = base.username; + url.password = base.password; + url.host = base.host; + url.port = base.port; + state = PATH; + continue; + } break; + + case SPECIAL_AUTHORITY_SLASHES: + state = SPECIAL_AUTHORITY_IGNORE_SLASHES; + if (chr !== '/' || charAt(buffer, pointer + 1) !== '/') continue; + pointer++; + break; + + case SPECIAL_AUTHORITY_IGNORE_SLASHES: + if (chr !== '/' && chr !== '\\') { + state = AUTHORITY; + continue; + } break; + + case AUTHORITY: + if (chr === '@') { + if (seenAt) buffer = '%40' + buffer; + seenAt = true; + bufferCodePoints = arrayFrom(buffer); + for (var i = 0; i < bufferCodePoints.length; i++) { + var codePoint = bufferCodePoints[i]; + if (codePoint === ':' && !seenPasswordToken) { + seenPasswordToken = true; + continue; + } + var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet); + if (seenPasswordToken) url.password += encodedCodePoints; + else url.username += encodedCodePoints; + } + buffer = ''; + } else if ( + chr === EOF || chr === '/' || chr === '?' || chr === '#' || + (chr === '\\' && url.isSpecial()) + ) { + if (seenAt && buffer === '') return INVALID_AUTHORITY; + pointer -= arrayFrom(buffer).length + 1; + buffer = ''; + state = HOST; + } else buffer += chr; + break; + + case HOST: + case HOSTNAME: + if (stateOverride && url.scheme === 'file') { + state = FILE_HOST; + continue; + } else if (chr === ':' && !seenBracket) { + if (buffer === '') return INVALID_HOST; + failure = url.parseHost(buffer); + if (failure) return failure; + buffer = ''; + state = PORT; + if (stateOverride === HOSTNAME) return; + } else if ( + chr === EOF || chr === '/' || chr === '?' || chr === '#' || + (chr === '\\' && url.isSpecial()) + ) { + if (url.isSpecial() && buffer === '') return INVALID_HOST; + if (stateOverride && buffer === '' && (url.includesCredentials() || url.port !== null)) return; + failure = url.parseHost(buffer); + if (failure) return failure; + buffer = ''; + state = PATH_START; + if (stateOverride) return; + continue; + } else { + if (chr === '[') seenBracket = true; + else if (chr === ']') seenBracket = false; + buffer += chr; + } break; + + case PORT: + if (exec(DIGIT, chr)) { + buffer += chr; + } else if ( + chr === EOF || chr === '/' || chr === '?' || chr === '#' || + (chr === '\\' && url.isSpecial()) || + stateOverride + ) { + if (buffer !== '') { + var port = parseInt$1(buffer, 10); + if (port > 0xFFFF) return INVALID_PORT; + url.port = (url.isSpecial() && port === specialSchemes[url.scheme]) ? null : port; + buffer = ''; + } + if (stateOverride) return; + state = PATH_START; + continue; + } else return INVALID_PORT; + break; + + case FILE: + url.scheme = 'file'; + if (chr === '/' || chr === '\\') state = FILE_SLASH; + else if (base && base.scheme === 'file') { + switch (chr) { + case EOF: + url.host = base.host; + url.path = arraySlice(base.path); + url.query = base.query; + break; + case '?': + url.host = base.host; + url.path = arraySlice(base.path); + url.query = ''; + state = QUERY; + break; + case '#': + url.host = base.host; + url.path = arraySlice(base.path); + url.query = base.query; + url.fragment = ''; + state = FRAGMENT; + break; + default: + if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) { + url.host = base.host; + url.path = arraySlice(base.path); + url.shortenPath(); + } + state = PATH; + continue; + } + } else { + state = PATH; + continue; + } break; + + case FILE_SLASH: + if (chr === '/' || chr === '\\') { + state = FILE_HOST; + break; + } + if (base && base.scheme === 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) { + if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]); + else url.host = base.host; + } + state = PATH; + continue; + + case FILE_HOST: + if (chr === EOF || chr === '/' || chr === '\\' || chr === '?' || chr === '#') { + if (!stateOverride && isWindowsDriveLetter(buffer)) { + state = PATH; + } else if (buffer === '') { + url.host = ''; + if (stateOverride) return; + state = PATH_START; + } else { + failure = url.parseHost(buffer); + if (failure) return failure; + if (url.host === 'localhost') url.host = ''; + if (stateOverride) return; + buffer = ''; + state = PATH_START; + } continue; + } else buffer += chr; + break; + + case PATH_START: + if (url.isSpecial()) { + state = PATH; + if (chr !== '/' && chr !== '\\') continue; + } else if (!stateOverride && chr === '?') { + url.query = ''; + state = QUERY; + } else if (!stateOverride && chr === '#') { + url.fragment = ''; + state = FRAGMENT; + } else if (chr !== EOF) { + state = PATH; + if (chr !== '/') continue; + } break; + + case PATH: + if ( + chr === EOF || chr === '/' || + (chr === '\\' && url.isSpecial()) || + (!stateOverride && (chr === '?' || chr === '#')) + ) { + if (isDoubleDot(buffer)) { + url.shortenPath(); + if (chr !== '/' && !(chr === '\\' && url.isSpecial())) { + push(url.path, ''); + } + } else if (isSingleDot(buffer)) { + if (chr !== '/' && !(chr === '\\' && url.isSpecial())) { + push(url.path, ''); + } + } else { + if (url.scheme === 'file' && !url.path.length && isWindowsDriveLetter(buffer)) { + if (url.host) url.host = ''; + buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter + } + push(url.path, buffer); + } + buffer = ''; + if (url.scheme === 'file' && (chr === EOF || chr === '?' || chr === '#')) { + while (url.path.length > 1 && url.path[0] === '') { + shift(url.path); + } + } + if (chr === '?') { + url.query = ''; + state = QUERY; + } else if (chr === '#') { + url.fragment = ''; + state = FRAGMENT; + } + } else { + buffer += percentEncode(chr, pathPercentEncodeSet); + } break; + + case CANNOT_BE_A_BASE_URL_PATH: + if (chr === '?') { + url.query = ''; + state = QUERY; + } else if (chr === '#') { + url.fragment = ''; + state = FRAGMENT; + } else if (chr !== EOF) { + url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet); + } break; + + case QUERY: + if (!stateOverride && chr === '#') { + url.fragment = ''; + state = FRAGMENT; + } else if (chr !== EOF) { + if (chr === "'" && url.isSpecial()) url.query += '%27'; + else if (chr === '#') url.query += '%23'; + else url.query += percentEncode(chr, C0ControlPercentEncodeSet); + } break; + + case FRAGMENT: + if (chr !== EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet); + break; + } + + pointer++; + } + }, + // https://url.spec.whatwg.org/#host-parsing + parseHost: function (input) { + var result, codePoints, index; + if (charAt(input, 0) === '[') { + if (charAt(input, input.length - 1) !== ']') return INVALID_HOST; + result = parseIPv6(stringSlice$1(input, 1, -1)); + if (!result) return INVALID_HOST; + this.host = result; + // opaque host + } else if (!this.isSpecial()) { + if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST; + result = ''; + codePoints = arrayFrom(input); + for (index = 0; index < codePoints.length; index++) { + result += percentEncode(codePoints[index], C0ControlPercentEncodeSet); + } + this.host = result; + } else { + input = toASCII(input); + if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST; + result = parseIPv4(input); + if (result === null) return INVALID_HOST; + this.host = result; + } + }, + // https://url.spec.whatwg.org/#cannot-have-a-username-password-port + cannotHaveUsernamePasswordPort: function () { + return !this.host || this.cannotBeABaseURL || this.scheme === 'file'; + }, + // https://url.spec.whatwg.org/#include-credentials + includesCredentials: function () { + return this.username !== '' || this.password !== ''; + }, + // https://url.spec.whatwg.org/#is-special + isSpecial: function () { + return hasOwn$1(specialSchemes, this.scheme); + }, + // https://url.spec.whatwg.org/#shorten-a-urls-path + shortenPath: function () { + var path = this.path; + var pathSize = path.length; + if (pathSize && (this.scheme !== 'file' || pathSize !== 1 || !isWindowsDriveLetter(path[0], true))) { + path.length--; + } + }, + // https://url.spec.whatwg.org/#concept-url-serializer + serialize: function () { + var url = this; + var scheme = url.scheme; + var username = url.username; + var password = url.password; + var host = url.host; + var port = url.port; + var path = url.path; + var query = url.query; + var fragment = url.fragment; + var output = scheme + ':'; + if (host !== null) { + output += '//'; + if (url.includesCredentials()) { + output += username + (password ? ':' + password : '') + '@'; + } + output += serializeHost(host); + if (port !== null) output += ':' + port; + } else if (scheme === 'file') output += '//'; + output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : ''; + if (query !== null) output += '?' + query; + if (fragment !== null) output += '#' + fragment; + return output; + }, + // https://url.spec.whatwg.org/#dom-url-href + setHref: function (href) { + var failure = this.parse(href); + if (failure) throw new TypeError$1(failure); + this.searchParams.update(); + }, + // https://url.spec.whatwg.org/#dom-url-origin + getOrigin: function () { + var scheme = this.scheme; + var port = this.port; + if (scheme === 'blob') try { + return new URLConstructor(scheme.path[0]).origin; + } catch (error) { + return 'null'; + } + if (scheme === 'file' || !this.isSpecial()) return 'null'; + return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : ''); + }, + // https://url.spec.whatwg.org/#dom-url-protocol + getProtocol: function () { + return this.scheme + ':'; + }, + setProtocol: function (protocol) { + this.parse($toString(protocol) + ':', SCHEME_START); + }, + // https://url.spec.whatwg.org/#dom-url-username + getUsername: function () { + return this.username; + }, + setUsername: function (username) { + var codePoints = arrayFrom($toString(username)); + if (this.cannotHaveUsernamePasswordPort()) return; + this.username = ''; + for (var i = 0; i < codePoints.length; i++) { + this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet); + } + }, + // https://url.spec.whatwg.org/#dom-url-password + getPassword: function () { + return this.password; + }, + setPassword: function (password) { + var codePoints = arrayFrom($toString(password)); + if (this.cannotHaveUsernamePasswordPort()) return; + this.password = ''; + for (var i = 0; i < codePoints.length; i++) { + this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet); + } + }, + // https://url.spec.whatwg.org/#dom-url-host + getHost: function () { + var host = this.host; + var port = this.port; + return host === null ? '' + : port === null ? serializeHost(host) + : serializeHost(host) + ':' + port; + }, + setHost: function (host) { + if (this.cannotBeABaseURL) return; + this.parse(host, HOST); + }, + // https://url.spec.whatwg.org/#dom-url-hostname + getHostname: function () { + var host = this.host; + return host === null ? '' : serializeHost(host); + }, + setHostname: function (hostname) { + if (this.cannotBeABaseURL) return; + this.parse(hostname, HOSTNAME); + }, + // https://url.spec.whatwg.org/#dom-url-port + getPort: function () { + var port = this.port; + return port === null ? '' : $toString(port); + }, + setPort: function (port) { + if (this.cannotHaveUsernamePasswordPort()) return; + port = $toString(port); + if (port === '') this.port = null; + else this.parse(port, PORT); + }, + // https://url.spec.whatwg.org/#dom-url-pathname + getPathname: function () { + var path = this.path; + return this.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : ''; + }, + setPathname: function (pathname) { + if (this.cannotBeABaseURL) return; + this.path = []; + this.parse(pathname, PATH_START); + }, + // https://url.spec.whatwg.org/#dom-url-search + getSearch: function () { + var query = this.query; + return query ? '?' + query : ''; + }, + setSearch: function (search) { + search = $toString(search); + if (search === '') { + this.query = null; + } else { + if (charAt(search, 0) === '?') search = stringSlice$1(search, 1); + this.query = ''; + this.parse(search, QUERY); + } + this.searchParams.update(); + }, + // https://url.spec.whatwg.org/#dom-url-searchparams + getSearchParams: function () { + return this.searchParams.facade; + }, + // https://url.spec.whatwg.org/#dom-url-hash + getHash: function () { + var fragment = this.fragment; + return fragment ? '#' + fragment : ''; + }, + setHash: function (hash) { + hash = $toString(hash); + if (hash === '') { + this.fragment = null; + return; + } + if (charAt(hash, 0) === '#') hash = stringSlice$1(hash, 1); + this.fragment = ''; + this.parse(hash, FRAGMENT); + }, + update: function () { + this.query = this.searchParams.serialize() || null; + } + }; + + // `URL` constructor + // https://url.spec.whatwg.org/#url-class + var URLConstructor = function URL(url /* , base */) { + var that = anInstance(this, URLPrototype); + var base = validateArgumentsLength(arguments.length, 1) > 1 ? arguments[1] : undefined; + var state = setInternalState(that, new URLState(url, false, base)); + if (!DESCRIPTORS) { + that.href = state.serialize(); + that.origin = state.getOrigin(); + that.protocol = state.getProtocol(); + that.username = state.getUsername(); + that.password = state.getPassword(); + that.host = state.getHost(); + that.hostname = state.getHostname(); + that.port = state.getPort(); + that.pathname = state.getPathname(); + that.search = state.getSearch(); + that.searchParams = state.getSearchParams(); + that.hash = state.getHash(); + } + }; + + var URLPrototype = URLConstructor.prototype; + + var accessorDescriptor = function (getter, setter) { + return { + get: function () { + return getInternalURLState(this)[getter](); + }, + set: setter && function (value) { + return getInternalURLState(this)[setter](value); + }, + configurable: true, + enumerable: true + }; + }; + + if (DESCRIPTORS) { + // `URL.prototype.href` accessors pair + // https://url.spec.whatwg.org/#dom-url-href + defineBuiltInAccessor(URLPrototype, 'href', accessorDescriptor('serialize', 'setHref')); + // `URL.prototype.origin` getter + // https://url.spec.whatwg.org/#dom-url-origin + defineBuiltInAccessor(URLPrototype, 'origin', accessorDescriptor('getOrigin')); + // `URL.prototype.protocol` accessors pair + // https://url.spec.whatwg.org/#dom-url-protocol + defineBuiltInAccessor(URLPrototype, 'protocol', accessorDescriptor('getProtocol', 'setProtocol')); + // `URL.prototype.username` accessors pair + // https://url.spec.whatwg.org/#dom-url-username + defineBuiltInAccessor(URLPrototype, 'username', accessorDescriptor('getUsername', 'setUsername')); + // `URL.prototype.password` accessors pair + // https://url.spec.whatwg.org/#dom-url-password + defineBuiltInAccessor(URLPrototype, 'password', accessorDescriptor('getPassword', 'setPassword')); + // `URL.prototype.host` accessors pair + // https://url.spec.whatwg.org/#dom-url-host + defineBuiltInAccessor(URLPrototype, 'host', accessorDescriptor('getHost', 'setHost')); + // `URL.prototype.hostname` accessors pair + // https://url.spec.whatwg.org/#dom-url-hostname + defineBuiltInAccessor(URLPrototype, 'hostname', accessorDescriptor('getHostname', 'setHostname')); + // `URL.prototype.port` accessors pair + // https://url.spec.whatwg.org/#dom-url-port + defineBuiltInAccessor(URLPrototype, 'port', accessorDescriptor('getPort', 'setPort')); + // `URL.prototype.pathname` accessors pair + // https://url.spec.whatwg.org/#dom-url-pathname + defineBuiltInAccessor(URLPrototype, 'pathname', accessorDescriptor('getPathname', 'setPathname')); + // `URL.prototype.search` accessors pair + // https://url.spec.whatwg.org/#dom-url-search + defineBuiltInAccessor(URLPrototype, 'search', accessorDescriptor('getSearch', 'setSearch')); + // `URL.prototype.searchParams` getter + // https://url.spec.whatwg.org/#dom-url-searchparams + defineBuiltInAccessor(URLPrototype, 'searchParams', accessorDescriptor('getSearchParams')); + // `URL.prototype.hash` accessors pair + // https://url.spec.whatwg.org/#dom-url-hash + defineBuiltInAccessor(URLPrototype, 'hash', accessorDescriptor('getHash', 'setHash')); + } + + // `URL.prototype.toJSON` method + // https://url.spec.whatwg.org/#dom-url-tojson + defineBuiltIn(URLPrototype, 'toJSON', function toJSON() { + return getInternalURLState(this).serialize(); + }, { enumerable: true }); + + // `URL.prototype.toString` method + // https://url.spec.whatwg.org/#URL-stringification-behavior + defineBuiltIn(URLPrototype, 'toString', function toString() { + return getInternalURLState(this).serialize(); + }, { enumerable: true }); + + if (NativeURL) { + var nativeCreateObjectURL = NativeURL.createObjectURL; + var nativeRevokeObjectURL = NativeURL.revokeObjectURL; + // `URL.createObjectURL` method + // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL + if (nativeCreateObjectURL) defineBuiltIn(URLConstructor, 'createObjectURL', bind(nativeCreateObjectURL, NativeURL)); + // `URL.revokeObjectURL` method + // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL + if (nativeRevokeObjectURL) defineBuiltIn(URLConstructor, 'revokeObjectURL', bind(nativeRevokeObjectURL, NativeURL)); + } + + setToStringTag(URLConstructor, 'URL'); + + $$6({ global: true, constructor: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, { + URL: URLConstructor + }); + + var $$5 = _export; + var setPrototypeOf = objectSetPrototypeOf; + + // `Object.setPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.setprototypeof + $$5({ target: 'Object', stat: true }, { + setPrototypeOf: setPrototypeOf + }); + + var $$4 = _export; + var $isExtensible = objectIsExtensible; + + // `Object.isExtensible` method + // https://tc39.es/ecma262/#sec-object.isextensible + // eslint-disable-next-line es/no-object-isextensible -- safe + $$4({ target: 'Object', stat: true, forced: Object.isExtensible !== $isExtensible }, { + isExtensible: $isExtensible + }); + + var $$3 = _export; + + // `Reflect.has` method + // https://tc39.es/ecma262/#sec-reflect.has + $$3({ target: 'Reflect', stat: true }, { + has: function has(target, propertyKey) { + return propertyKey in target; + } + }); + + var hasOwn = hasOwnProperty_1; + + var isDataDescriptor$1 = function (descriptor) { + return descriptor !== undefined && (hasOwn(descriptor, 'value') || hasOwn(descriptor, 'writable')); + }; + + var $$2 = _export; + var call = functionCall; + var isObject$1 = isObject$t; + var anObject = anObject$p; + var isDataDescriptor = isDataDescriptor$1; + var getOwnPropertyDescriptorModule = objectGetOwnPropertyDescriptor; + var getPrototypeOf = objectGetPrototypeOf$1; + + // `Reflect.get` method + // https://tc39.es/ecma262/#sec-reflect.get + function get(target, propertyKey /* , receiver */) { + var receiver = arguments.length < 3 ? target : arguments[2]; + var descriptor, prototype; + if (anObject(target) === receiver) return target[propertyKey]; + descriptor = getOwnPropertyDescriptorModule.f(target, propertyKey); + if (descriptor) return isDataDescriptor(descriptor) + ? descriptor.value + : descriptor.get === undefined ? undefined : call(descriptor.get, receiver); + if (isObject$1(prototype = getPrototypeOf(target))) return get(prototype, propertyKey, receiver); + } + + $$2({ target: 'Reflect', stat: true }, { + get: get + }); + + // https://github.com/tc39/proposal-string-pad-start-end + var uncurryThis$1 = functionUncurryThis; + var toLength = toLength$c; + var toString = toString$n; + var $repeat = stringRepeat; + var requireObjectCoercible = requireObjectCoercible$f; + + var repeat = uncurryThis$1($repeat); + var stringSlice = uncurryThis$1(''.slice); + var ceil = Math.ceil; + + // `String.prototype.{ padStart, padEnd }` methods implementation + var createMethod = function (IS_END) { + return function ($this, maxLength, fillString) { + var S = toString(requireObjectCoercible($this)); + var intMaxLength = toLength(maxLength); + var stringLength = S.length; + var fillStr = fillString === undefined ? ' ' : toString(fillString); + var fillLen, stringFiller; + if (intMaxLength <= stringLength || fillStr === '') return S; + fillLen = intMaxLength - stringLength; + stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length)); + if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen); + return IS_END ? S + stringFiller : stringFiller + S; + }; + }; + + var stringPad = { + // `String.prototype.padStart` method + // https://tc39.es/ecma262/#sec-string.prototype.padstart + start: createMethod(false), + // `String.prototype.padEnd` method + // https://tc39.es/ecma262/#sec-string.prototype.padend + end: createMethod(true) + }; + + var uncurryThis = functionUncurryThis; + var fails$1 = fails$_; + var padStart = stringPad.start; + + var $RangeError = RangeError; + var $isFinite = isFinite; + var abs = Math.abs; + var DatePrototype = Date.prototype; + var nativeDateToISOString = DatePrototype.toISOString; + var thisTimeValue = uncurryThis(DatePrototype.getTime); + var getUTCDate = uncurryThis(DatePrototype.getUTCDate); + var getUTCFullYear = uncurryThis(DatePrototype.getUTCFullYear); + var getUTCHours = uncurryThis(DatePrototype.getUTCHours); + var getUTCMilliseconds = uncurryThis(DatePrototype.getUTCMilliseconds); + var getUTCMinutes = uncurryThis(DatePrototype.getUTCMinutes); + var getUTCMonth = uncurryThis(DatePrototype.getUTCMonth); + var getUTCSeconds = uncurryThis(DatePrototype.getUTCSeconds); + + // `Date.prototype.toISOString` method implementation + // https://tc39.es/ecma262/#sec-date.prototype.toisostring + // PhantomJS / old WebKit fails here: + var dateToIsoString = (fails$1(function () { + return nativeDateToISOString.call(new Date(-5e13 - 1)) !== '0385-07-25T07:06:39.999Z'; + }) || !fails$1(function () { + nativeDateToISOString.call(new Date(NaN)); + })) ? function toISOString() { + if (!$isFinite(thisTimeValue(this))) throw new $RangeError('Invalid time value'); + var date = this; + var year = getUTCFullYear(date); + var milliseconds = getUTCMilliseconds(date); + var sign = year < 0 ? '-' : year > 9999 ? '+' : ''; + return sign + padStart(abs(year), sign ? 6 : 4, 0) + + '-' + padStart(getUTCMonth(date) + 1, 2, 0) + + '-' + padStart(getUTCDate(date), 2, 0) + + 'T' + padStart(getUTCHours(date), 2, 0) + + ':' + padStart(getUTCMinutes(date), 2, 0) + + ':' + padStart(getUTCSeconds(date), 2, 0) + + '.' + padStart(milliseconds, 3, 0) + + 'Z'; + } : nativeDateToISOString; + + var $$1 = _export; + var toISOString = dateToIsoString; + + // `Date.prototype.toISOString` method + // https://tc39.es/ecma262/#sec-date.prototype.toisostring + // PhantomJS / old WebKit has a broken implementations + $$1({ target: 'Date', proto: true, forced: Date.prototype.toISOString !== toISOString }, { + toISOString: toISOString + }); + + var $ = _export; + var fails = fails$_; + var isObject = isObject$t; + var classof = classofRaw$2; + var ARRAY_BUFFER_NON_EXTENSIBLE = arrayBufferNonExtensible; + + // eslint-disable-next-line es/no-object-isfrozen -- safe + var $isFrozen = Object.isFrozen; + + var FORCED = ARRAY_BUFFER_NON_EXTENSIBLE || fails(function () { $isFrozen(1); }); + + // `Object.isFrozen` method + // https://tc39.es/ecma262/#sec-object.isfrozen + $({ target: 'Object', stat: true, forced: FORCED }, { + isFrozen: function isFrozen(it) { + if (!isObject(it)) return true; + if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) === 'ArrayBuffer') return true; + return $isFrozen ? $isFrozen(it) : false; + } + }); + + var CBTTests$1 = {}; + + function _createSuper(Derived){var hasNativeReflectConstruct=_isNativeReflectConstruct();return function _createSuperInternal(){var Super=_getPrototypeOf(Derived),result;if(hasNativeReflectConstruct){var NewTarget=_getPrototypeOf(this).constructor;result=Reflect.construct(Super,arguments,NewTarget);}else {result=Super.apply(this,arguments);}return _possibleConstructorReturn(this,result);};}function _isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));return true;}catch(e){return false;}}function _createForOfIteratorHelper2(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray2(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return {s:F,n:function n(){if(i>=o.length)return {done:true};return {done:false,value:o[i++]};},e:function e(_e3){throw _e3;},f:F};}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}var normalCompletion=true,didErr=false,err;return {s:function s(){it=it.call(o);},n:function n(){var step=it.next();normalCompletion=step.done;return step;},e:function e(_e4){didErr=true;err=_e4;},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]();}finally{if(didErr)throw err;}}};}function _unsupportedIterableToArray2(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray2(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray2(o,minLen);}function _arrayLikeToArray2(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i":"greater","|":"or","¢":"cent","£":"pound","¤":"currency","¥":"yen","©":"(c)","ª":"a","®":"(r)","º":"o","À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Æ":"AE","Ç":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","Þ":"TH","ß":"ss","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","æ":"ae","ç":"c","è":"e","é":"e","ê":"e","ë":"e","ì":"i","í":"i","î":"i","ï":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","þ":"th","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Č":"C","č":"c","Ď":"D","ď":"d","Đ":"DJ","đ":"dj","Ē":"E","ē":"e","Ė":"E","ė":"e","Ę":"e","ę":"e","Ě":"E","ě":"e","Ğ":"G","ğ":"g","Ģ":"G","ģ":"g","Ĩ":"I","ĩ":"i","Ī":"i","ī":"i","Į":"I","į":"i","İ":"I","ı":"i","Ķ":"k","ķ":"k","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ł":"L","ł":"l","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","Ō":"O","ō":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","Ŕ":"R","ŕ":"r","Ř":"R","ř":"r","Ś":"S","ś":"s","Ş":"S","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","Ť":"T","ť":"t","Ũ":"U","ũ":"u","Ū":"u","ū":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","Ə":"E","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Lj":"LJ","lj":"lj","Nj":"NJ","nj":"nj","Ș":"S","ș":"s","Ț":"T","ț":"t","ə":"e","˚":"o","Ά":"A","Έ":"E","Ή":"H","Ί":"I","Ό":"O","Ύ":"Y","Ώ":"W","ΐ":"i","Α":"A","Β":"B","Γ":"G","Δ":"D","Ε":"E","Ζ":"Z","Η":"H","Θ":"8","Ι":"I","Κ":"K","Λ":"L","Μ":"M","Ν":"N","Ξ":"3","Ο":"O","Π":"P","Ρ":"R","Σ":"S","Τ":"T","Υ":"Y","Φ":"F","Χ":"X","Ψ":"PS","Ω":"W","Ϊ":"I","Ϋ":"Y","ά":"a","έ":"e","ή":"h","ί":"i","ΰ":"y","α":"a","β":"b","γ":"g","δ":"d","ε":"e","ζ":"z","η":"h","θ":"8","ι":"i","κ":"k","λ":"l","μ":"m","ν":"n","ξ":"3","ο":"o","π":"p","ρ":"r","ς":"s","σ":"s","τ":"t","υ":"y","φ":"f","χ":"x","ψ":"ps","ω":"w","ϊ":"i","ϋ":"y","ό":"o","ύ":"y","ώ":"w","Ё":"Yo","Ђ":"DJ","Є":"Ye","І":"I","Ї":"Yi","Ј":"J","Љ":"LJ","Њ":"NJ","Ћ":"C","Џ":"DZ","А":"A","Б":"B","В":"V","Г":"G","Д":"D","Е":"E","Ж":"Zh","З":"Z","И":"I","Й":"J","К":"K","Л":"L","М":"M","Н":"N","О":"O","П":"P","Р":"R","С":"S","Т":"T","У":"U","Ф":"F","Х":"H","Ц":"C","Ч":"Ch","Ш":"Sh","Щ":"Sh","Ъ":"U","Ы":"Y","Ь":"","Э":"E","Ю":"Yu","Я":"Ya","а":"a","б":"b","в":"v","г":"g","д":"d","е":"e","ж":"zh","з":"z","и":"i","й":"j","к":"k","л":"l","м":"m","н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"h","ц":"c","ч":"ch","ш":"sh","щ":"sh","ъ":"u","ы":"y","ь":"","э":"e","ю":"yu","я":"ya","ё":"yo","ђ":"dj","є":"ye","і":"i","ї":"yi","ј":"j","љ":"lj","њ":"nj","ћ":"c","ѝ":"u","џ":"dz","Ґ":"G","ґ":"g","Ғ":"GH","ғ":"gh","Қ":"KH","қ":"kh","Ң":"NG","ң":"ng","Ү":"UE","ү":"ue","Ұ":"U","ұ":"u","Һ":"H","һ":"h","Ә":"AE","ә":"ae","Ө":"OE","ө":"oe","Ա":"A","Բ":"B","Գ":"G","Դ":"D","Ե":"E","Զ":"Z","Է":"E\'","Ը":"Y\'","Թ":"T\'","Ժ":"JH","Ի":"I","Լ":"L","Խ":"X","Ծ":"C\'","Կ":"K","Հ":"H","Ձ":"D\'","Ղ":"GH","Ճ":"TW","Մ":"M","Յ":"Y","Ն":"N","Շ":"SH","Չ":"CH","Պ":"P","Ջ":"J","Ռ":"R\'","Ս":"S","Վ":"V","Տ":"T","Ր":"R","Ց":"C","Փ":"P\'","Ք":"Q\'","Օ":"O\'\'","Ֆ":"F","և":"EV","ء":"a","آ":"aa","أ":"a","ؤ":"u","إ":"i","ئ":"e","ا":"a","ب":"b","ة":"h","ت":"t","ث":"th","ج":"j","ح":"h","خ":"kh","د":"d","ذ":"th","ر":"r","ز":"z","س":"s","ش":"sh","ص":"s","ض":"dh","ط":"t","ظ":"z","ع":"a","غ":"gh","ف":"f","ق":"q","ك":"k","ل":"l","م":"m","ن":"n","ه":"h","و":"w","ى":"a","ي":"y","ً":"an","ٌ":"on","ٍ":"en","َ":"a","ُ":"u","ِ":"e","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","پ":"p","چ":"ch","ژ":"zh","ک":"k","گ":"g","ی":"y","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","฿":"baht","ა":"a","ბ":"b","გ":"g","დ":"d","ე":"e","ვ":"v","ზ":"z","თ":"t","ი":"i","კ":"k","ლ":"l","მ":"m","ნ":"n","ო":"o","პ":"p","ჟ":"zh","რ":"r","ს":"s","ტ":"t","უ":"u","ფ":"f","ქ":"k","ღ":"gh","ყ":"q","შ":"sh","ჩ":"ch","ც":"ts","ძ":"dz","წ":"ts","ჭ":"ch","ხ":"kh","ჯ":"j","ჰ":"h","Ṣ":"S","ṣ":"s","Ẁ":"W","ẁ":"w","Ẃ":"W","ẃ":"w","Ẅ":"W","ẅ":"w","ẞ":"SS","Ạ":"A","ạ":"a","Ả":"A","ả":"a","Ấ":"A","ấ":"a","Ầ":"A","ầ":"a","Ẩ":"A","ẩ":"a","Ẫ":"A","ẫ":"a","Ậ":"A","ậ":"a","Ắ":"A","ắ":"a","Ằ":"A","ằ":"a","Ẳ":"A","ẳ":"a","Ẵ":"A","ẵ":"a","Ặ":"A","ặ":"a","Ẹ":"E","ẹ":"e","Ẻ":"E","ẻ":"e","Ẽ":"E","ẽ":"e","Ế":"E","ế":"e","Ề":"E","ề":"e","Ể":"E","ể":"e","Ễ":"E","ễ":"e","Ệ":"E","ệ":"e","Ỉ":"I","ỉ":"i","Ị":"I","ị":"i","Ọ":"O","ọ":"o","Ỏ":"O","ỏ":"o","Ố":"O","ố":"o","Ồ":"O","ồ":"o","Ổ":"O","ổ":"o","Ỗ":"O","ỗ":"o","Ộ":"O","ộ":"o","Ớ":"O","ớ":"o","Ờ":"O","ờ":"o","Ở":"O","ở":"o","Ỡ":"O","ỡ":"o","Ợ":"O","ợ":"o","Ụ":"U","ụ":"u","Ủ":"U","ủ":"u","Ứ":"U","ứ":"u","Ừ":"U","ừ":"u","Ử":"U","ử":"u","Ữ":"U","ữ":"u","Ự":"U","ự":"u","Ỳ":"Y","ỳ":"y","Ỵ":"Y","ỵ":"y","Ỷ":"Y","ỷ":"y","Ỹ":"Y","ỹ":"y","–":"-","‘":"\'","’":"\'","“":"\\\"","”":"\\\"","„":"\\\"","†":"+","•":"*","…":"...","₠":"ecu","₢":"cruzeiro","₣":"french franc","₤":"lira","₥":"mill","₦":"naira","₧":"peseta","₨":"rupee","₩":"won","₪":"new shequel","₫":"dong","€":"euro","₭":"kip","₮":"tugrik","₯":"drachma","₰":"penny","₱":"peso","₲":"guarani","₳":"austral","₴":"hryvnia","₵":"cedi","₸":"kazakhstani tenge","₹":"indian rupee","₺":"turkish lira","₽":"russian ruble","₿":"bitcoin","℠":"sm","™":"tm","∂":"d","∆":"delta","∑":"sum","∞":"infinity","♥":"love","元":"yuan","円":"yen","﷼":"rial","ﻵ":"laa","ﻷ":"laa","ﻹ":"lai","ﻻ":"la"}');var locales=JSON.parse('{"bg":{"Й":"Y","Ц":"Ts","Щ":"Sht","Ъ":"A","Ь":"Y","й":"y","ц":"ts","щ":"sht","ъ":"a","ь":"y"},"de":{"Ä":"AE","ä":"ae","Ö":"OE","ö":"oe","Ü":"UE","ü":"ue","ß":"ss","%":"prozent","&":"und","|":"oder","∑":"summe","∞":"unendlich","♥":"liebe"},"es":{"%":"por ciento","&":"y","<":"menor que",">":"mayor que","|":"o","¢":"centavos","£":"libras","¤":"moneda","₣":"francos","∑":"suma","∞":"infinito","♥":"amor"},"fr":{"%":"pourcent","&":"et","<":"plus petit",">":"plus grand","|":"ou","¢":"centime","£":"livre","¤":"devise","₣":"franc","∑":"somme","∞":"infini","♥":"amour"},"pt":{"%":"porcento","&":"e","<":"menor",">":"maior","|":"ou","¢":"centavo","∑":"soma","£":"libra","∞":"infinito","♥":"amor"},"uk":{"И":"Y","и":"y","Й":"Y","й":"y","Ц":"Ts","ц":"ts","Х":"Kh","х":"kh","Щ":"Shch","щ":"shch","Г":"H","г":"h"},"vi":{"Đ":"D","đ":"d"},"da":{"Ø":"OE","ø":"oe","Å":"AA","å":"aa","%":"procent","&":"og","|":"eller","$":"dollar","<":"mindre end",">":"større end"},"nb":{"&":"og","Å":"AA","Æ":"AE","Ø":"OE","å":"aa","æ":"ae","ø":"oe"},"it":{"&":"e"},"nl":{"&":"en"},"sv":{"&":"och","Å":"AA","Ä":"AE","Ö":"OE","å":"aa","ä":"ae","ö":"oe"}}');function replace(string,options){if(typeof string!=='string'){throw new Error('slugify: string argument expected');}options=typeof options==='string'?{replacement:options}:options||{};var locale=locales[options.locale]||{};var replacement=options.replacement===undefined?'-':options.replacement;var trim=options.trim===undefined?true:options.trim;var slug=string.normalize().split('')// replace characters based on charMap + .reduce(function(result,ch){var appendChar=locale[ch];if(appendChar===undefined)appendChar=charMap[ch];if(appendChar===undefined)appendChar=ch;if(appendChar===replacement)appendChar=' ';return result+appendChar// remove not allowed characters + .replace(options.remove||/[^\w\s$*_+~.()'"!\-:@]+/g,'');},'');if(options.strict){slug=slug.replace(/[^A-Za-z0-9\s]/g,'');}if(trim){slug=slug.trim();}// Replace spaces with replacement character, treating multiple consecutive + // spaces as a single space. + slug=slug.replace(/\s+/g,replacement);if(options.lower){slug=slug.toLowerCase();}return slug;}replace.extend=function(customMap){Object.assign(charMap,customMap);};return replace;});})(slugify$1,slugify$1.exports);var slugifyExports=slugify$1.exports;var slugify=/*@__PURE__*/getDefaultExportFromCjs(slugifyExports);var version="2.23.4";var Constants={sdkVersion:version,sdkVendor:'mparticle',platform:'web',Messages:{DeprecationMessages:{MethodIsDeprecatedPostfix:'is a deprecated method and will be removed in future releases',AlternativeMethodPrefix:'Please use the alternate method:'},ErrorMessages:{NoToken:'A token must be specified.',EventNameInvalidType:'Event name must be a valid string value.',EventDataInvalidType:'Event data must be a valid object hash.',LoggingDisabled:'Event logging is currently disabled.',CookieParseError:'Could not parse cookie',EventEmpty:'Event object is null or undefined, cancelling send',APIRequestEmpty:'APIRequest is null or undefined, cancelling send',NoEventType:'Event type must be specified.',TransactionIdRequired:'Transaction ID is required',TransactionRequired:'A transaction attributes object is required',PromotionIdRequired:'Promotion ID is required',BadAttribute:'Attribute value cannot be object or array',BadKey:'Key value cannot be object or array',BadLogPurchase:'Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions'},InformationMessages:{CookieSearch:'Searching for cookie',CookieFound:'Cookie found, parsing values',CookieNotFound:'Cookies not found',CookieSet:'Setting cookie',CookieSync:'Performing cookie sync',SendBegin:'Starting to send event',SendIdentityBegin:'Starting to send event to identity server',SendWindowsPhone:'Sending event to Windows Phone container',SendIOS:'Calling iOS path: ',SendAndroid:'Calling Android JS interface method: ',SendHttp:'Sending event to mParticle HTTP service',SendAliasHttp:'Sending alias request to mParticle HTTP service',SendIdentityHttp:'Sending event to mParticle HTTP service',StartingNewSession:'Starting new Session',StartingLogEvent:'Starting to log event',StartingLogOptOut:'Starting to log user opt in/out',StartingEndSession:'Starting to end session',StartingInitialization:'Starting to initialize',StartingLogCommerceEvent:'Starting to log commerce event',StartingAliasRequest:'Starting to Alias MPIDs',LoadingConfig:'Loading configuration options',AbandonLogEvent:'Cannot log event, logging disabled or developer token not set',AbandonAliasUsers:'Cannot Alias Users, logging disabled or developer token not set',AbandonStartSession:'Cannot start session, logging disabled or developer token not set',AbandonEndSession:'Cannot end session, logging disabled or developer token not set',NoSessionToEnd:'Cannot end session, no active session found'},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:'identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again',IdentityRequesetInvalidKey:'There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.',OnUserAliasType:'The onUserAlias value must be a function.',UserIdentities:'The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.',UserIdentitiesInvalidKey:'There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.',UserIdentitiesInvalidValues:'All user identity values must be strings or null. Request not sent to server. Please fix and try again.',AliasMissingMpid:'Alias Request must contain both a destinationMpid and a sourceMpid',AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:'Alias Request must have both a startTime and an endTime',AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:'logEvent',SetUserTag:'setUserTag',RemoveUserTag:'removeUserTag',SetUserAttribute:'setUserAttribute',RemoveUserAttribute:'removeUserAttribute',SetSessionAttribute:'setSessionAttribute',AddToCart:'addToCart',RemoveFromCart:'removeFromCart',ClearCart:'clearCart',LogOut:'logOut',SetUserAttributeList:'setUserAttributeList',RemoveAllUserAttributes:'removeAllUserAttributes',GetUserAttributesLists:'getUserAttributesLists',GetAllUserAttributes:'getAllUserAttributes',Identify:'identify',Logout:'logout',Login:'login',Modify:'modify',Alias:'aliasUsers',Upload:'upload'},StorageNames:{localStorageName:'mprtcl-api',localStorageNameV3:'mprtcl-v3',cookieName:'mprtcl-api',cookieNameV2:'mprtcl-v2',cookieNameV3:'mprtcl-v3',localStorageNameV4:'mprtcl-v4',localStorageProductsV4:'mprtcl-prodv4',cookieNameV4:'mprtcl-v4',currentStorageName:'mprtcl-v4',currentStorageProductsName:'mprtcl-prodv4'},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,maxProducts:20,forwarderStatsTimeout:5000,integrationDelayTimeout:5000,maxCookieSize:3000,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload + },DefaultUrls:{v1SecureServiceUrl:'jssdks.mparticle.com/v1/JS/',v2SecureServiceUrl:'jssdks.mparticle.com/v2/JS/',v3SecureServiceUrl:'jssdks.mparticle.com/v3/JS/',configUrl:'jssdkcdns.mparticle.com/JS/v2/',identityUrl:'identity.mparticle.com/v1/',aliasUrl:'jssdks.mparticle.com/v1/identity/'},Base64CookieKeys:{csm:1,sa:1,ss:1,ua:1,ui:1,csd:1,ia:1,con:1},SDKv2NonMPIDCookieKeys:{gs:1,cu:1,l:1,globalSettings:1,currentUserMPID:1},HTTPCodes:{noHttpCoverage:-1,activeIdentityRequest:-2,activeSession:-3,validationIssue:-4,nativeIdentityRequest:-5,loggingDisabledOrMissingAPIKey:-6,tooManyRequests:429},FeatureFlags:{ReportBatching:'reportBatching',EventBatchingIntervalMillis:'eventBatchingIntervalMillis',OfflineStorage:'offlineStorage'},DefaultInstance:'default_instance',CCPAPurpose:'data_sale_opt_out'};var createCookieString=function createCookieString(value){return replaceCommasWithPipes(replaceQuotesWithApostrophes(value));};var revertCookieString=function revertCookieString(value){return replacePipesWithCommas(replaceApostrophesWithQuotes(value));};var inArray=function inArray(items,name){var i=0;if(Array.prototype.indexOf){return items.indexOf(name,0)>=0;}else {for(var n=items.length;i>a/4).toString(16);}return (a^Math.random()*16>>a/4).toString(16);};var generateUniqueId=function generateUniqueId(a){// https://gist.github.com/jed/982883 + // Added support for crypto for better random + if(a===void 0){a='';}return a// if the placeholder was passed, return + ?generateRandomValue()// if the placeholder was passed, return + :// [1e7] -> // 10000000 + + // -1e3 -> // -1000 + + // -4e3 -> // -4000 + + // -8e3 -> // -80000000 + + // -1e11 -> //-100000000000, + "".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with + generateUniqueId// random hex digits + );};/** + * Returns a value between 1-100 inclusive. + */var getRampNumber=function getRampNumber(value){if(!value){return 100;}var hash=generateHash(value);return Math.abs(hash%100)+1;};var isObject=function isObject(value){var objType=Object.prototype.toString.call(value);return objType==='[object Object]'||objType==='[object Error]';};var parseNumber=function parseNumber(value){if(isNaN(value)||!isFinite(value)){return 0;}var floatValue=parseFloat(value);return isNaN(floatValue)?0:floatValue;};var parseStringOrNumber=function parseStringOrNumber(value){if(isStringOrNumber(value)){return value;}else {return null;}};var replaceCommasWithPipes=function replaceCommasWithPipes(value){return value.replace(/,/g,'|');};var replacePipesWithCommas=function replacePipesWithCommas(value){return value.replace(/\|/g,',');};var replaceApostrophesWithQuotes=function replaceApostrophesWithQuotes(value){return value.replace(/\'/g,'"');};var replaceQuotesWithApostrophes=function replaceQuotesWithApostrophes(value){return value.replace(/\"/g,"'");};// FIXME: REFACTOR for V3 + // only used in store.js to sanitize server-side formatting of + // booleans when checking for `isDevelopmentMode` + // Should be removed in v3 + var returnConvertedBoolean=function returnConvertedBoolean(data){if(data==='false'||data==='0'){return false;}else {return Boolean(data);}};var decoded$1=function decoded(s){return decodeURIComponent(s.replace(/\+/g,' '));};var converted$1=function converted(s){if(s.indexOf('"')===0){s=s.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,'\\');}return s;};var isString=function isString(value){return typeof value==='string';};var isNumber=function isNumber(value){return typeof value==='number';};var isFunction=function isFunction(fn){return typeof fn==='function';};// TODO: Refactor this to a regex + var isDataPlanSlug=function isDataPlanSlug(str){return isString(str)&&str===slugify(str);};var isStringOrNumber=function isStringOrNumber(value){return isString(value)||isNumber(value);};var isEmpty=function isEmpty(value){return value==null||!(Object.keys(value)||value).length;};var pluses=/\+/g,getLocalStorageProducts$3=function getLocalStorageProducts(){return JSON.parse(atob(localStorage.getItem(mParticle.getInstance()._Helpers.createProductStorageName(workspaceToken))));},decoded=function decoded(s){return decodeURIComponent(s.replace(pluses,' '));},converted=function converted(s){if(s.indexOf('"')===0){s=s.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,'\\');}return s;},getCookieDomain=function getCookieDomain(){var rootDomain=getDomain(document,location.hostname);if(rootDomain===''){return '';}else {return '.'+rootDomain;}},getDomain=function getDomain(doc,locationHostname){var i,testParts,mpTest='mptest=cookie',hostname=locationHostname.split('.');for(i=hostname.length-1;i>=0;i--){testParts=hostname.slice(i).join('.');doc.cookie=mpTest+';domain=.'+testParts+';';if(doc.cookie.indexOf(mpTest)>-1){doc.cookie=mpTest.split('=')[0]+'=;domain=.'+testParts+';expires=Thu, 01 Jan 1970 00:00:01 GMT;';return testParts;}}return '';},findCookie$2=function findCookie(cookieName){var cookie;if(cookieName===v4CookieKey||!cookieName){cookie=mParticle.getInstance()._Persistence.getCookie();}else if(cookieName===v3CookieKey){cookie=JSON.parse(replacePipesWithCommas(findEncodedCookie(cookieName)));}else {cookie=JSON.parse(findEncodedCookie(cookieName));}if(cookie){return cookie;}else {return null;}},findEncodedCookie=function findEncodedCookie(cookieName){var cookies=document.cookie.split('; ');for(var i=0,l=cookies.length;i-1?cookie.substr(0,eqPos):cookie;document.cookie=name+"=;expires=Thu, 01 Jan 1970 00:00:00 GMT";}};var TestsCore={getLocalStorageProducts:getLocalStorageProducts$3,findCookie:findCookie$2,setCookie:setCookie$2,setLocalStorage:setLocalStorage$5,getLocalStorage:getLocalStorage$5,findRequestURL:findRequestURL$1,findBatch:findBatch$7,findEventFromRequest:findEventFromRequest$8,findEventFromBatch:findEventFromBatch,getForwarderEvent:getForwarderEvent$1,findRequest:findRequest$1,getIdentityEvent:getIdentityEvent$2,MockForwarder:MockForwarder$7,MockSideloadedKit:MockSideloadedKit$2,mParticleAndroid:mParticleAndroid$1,mParticleIOS:mParticleIOS$1,v4CookieKey:v4CookieKey,v4LSKey:v4LSKey,workspaceToken:workspaceToken,workspaceCookieName:workspaceCookieName,forwarderDefaultConfiguration:forwarderDefaultConfiguration$5,deleteAllCookies:deleteAllCookies};function createSDKConfig(config){// TODO: Refactor to create a default config object + var sdkConfig={};for(var prop in Constants.DefaultConfig){if(Constants.DefaultConfig.hasOwnProperty(prop)){sdkConfig[prop]=Constants.DefaultConfig[prop];}}if(config){for(var prop in config){if(config.hasOwnProperty(prop)){sdkConfig[prop]=config[prop];}}}for(var prop in Constants.DefaultUrls){sdkConfig[prop]=Constants.DefaultUrls[prop];}return sdkConfig;}// TODO: Merge this with SDKStoreApi in sdkRuntimeModels + function Store(config,mpInstance){var defaultStore={isEnabled:true,sessionAttributes:{},currentSessionMPIDs:[],consentState:null,sessionId:null,isFirstRun:null,clientId:null,deviceId:null,devToken:null,serverSettings:{},dateLastEventSent:null,sessionStartDate:null,currentPosition:null,isTracking:false,watchPositionId:null,cartProducts:[],eventQueue:[],currencyCode:null,globalTimer:null,context:null,configurationLoaded:false,identityCallInFlight:false,SDKConfig:{},nonCurrentUserMPIDs:{},identifyCalled:false,isLoggedIn:false,cookieSyncDates:{},integrationAttributes:{},requireDelay:true,isLocalStorageAvailable:null,storageName:null,prodStorageName:null,activeForwarders:[],kits:{},sideloadedKits:[],configuredForwarders:[],pixelConfigurations:[],wrapperSDKInfo:{name:'none',version:null,isInfoSet:false}};for(var key in defaultStore){this[key]=defaultStore[key];}this.integrationDelayTimeoutStart=Date.now();this.SDKConfig=createSDKConfig(config);// Set configuration to default settings + if(config){if(config.deviceId){this.deviceId=config.deviceId;}if(config.hasOwnProperty('isDevelopmentMode')){this.SDKConfig.isDevelopmentMode=mpInstance._Helpers.returnConvertedBoolean(config.isDevelopmentMode);}else {this.SDKConfig.isDevelopmentMode=false;}if(config.hasOwnProperty('v1SecureServiceUrl')){this.SDKConfig.v1SecureServiceUrl=config.v1SecureServiceUrl;}if(config.hasOwnProperty('v2SecureServiceUrl')){this.SDKConfig.v2SecureServiceUrl=config.v2SecureServiceUrl;}if(config.hasOwnProperty('v3SecureServiceUrl')){this.SDKConfig.v3SecureServiceUrl=config.v3SecureServiceUrl;}if(config.hasOwnProperty('identityUrl')){this.SDKConfig.identityUrl=config.identityUrl;}if(config.hasOwnProperty('aliasUrl')){this.SDKConfig.aliasUrl=config.aliasUrl;}if(config.hasOwnProperty('configUrl')){this.SDKConfig.configUrl=config.configUrl;}if(config.hasOwnProperty('logLevel')){this.SDKConfig.logLevel=config.logLevel;}this.SDKConfig.useNativeSdk=!!config.useNativeSdk;this.SDKConfig.kits=config.kits||{};this.SDKConfig.sideloadedKits=config.sideloadedKits||[];if(config.hasOwnProperty('isIOS')){this.SDKConfig.isIOS=config.isIOS;}else {this.SDKConfig.isIOS=window.mParticle&&window.mParticle.isIOS?window.mParticle.isIOS:false;}if(config.hasOwnProperty('useCookieStorage')){this.SDKConfig.useCookieStorage=config.useCookieStorage;}else {this.SDKConfig.useCookieStorage=false;}if(config.hasOwnProperty('maxProducts')){this.SDKConfig.maxProducts=config.maxProducts;}else {this.SDKConfig.maxProducts=Constants.DefaultConfig.maxProducts;}if(config.hasOwnProperty('maxCookieSize')){this.SDKConfig.maxCookieSize=config.maxCookieSize;}else {this.SDKConfig.maxCookieSize=Constants.DefaultConfig.maxCookieSize;}if(config.hasOwnProperty('appName')){this.SDKConfig.appName=config.appName;}if(config.hasOwnProperty('package')){this.SDKConfig["package"]=config["package"];}if(config.hasOwnProperty('integrationDelayTimeout')){this.SDKConfig.integrationDelayTimeout=config.integrationDelayTimeout;}else {this.SDKConfig.integrationDelayTimeout=Constants.DefaultConfig.integrationDelayTimeout;}if(config.hasOwnProperty('identifyRequest')){this.SDKConfig.identifyRequest=config.identifyRequest;}if(config.hasOwnProperty('identityCallback')){var callback=config.identityCallback;if(mpInstance._Helpers.Validators.isFunction(callback)){this.SDKConfig.identityCallback=config.identityCallback;}else {mpInstance.Logger.warning('The optional callback must be a function. You tried entering a(n) '+_typeof(callback)+' . Callback not set. Please set your callback again.');}}if(config.hasOwnProperty('appVersion')){this.SDKConfig.appVersion=config.appVersion;}if(config.hasOwnProperty('appName')){this.SDKConfig.appName=config.appName;}if(config.hasOwnProperty('sessionTimeout')){this.SDKConfig.sessionTimeout=config.sessionTimeout;}if(config.hasOwnProperty('dataPlan')){this.SDKConfig.dataPlan={PlanVersion:null,PlanId:null};var dataPlan=config.dataPlan;if(dataPlan.planId){if(isDataPlanSlug(dataPlan.planId)){this.SDKConfig.dataPlan.PlanId=dataPlan.planId;}else {mpInstance.Logger.error('Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)');}}if(dataPlan.planVersion){if(isNumber(dataPlan.planVersion)){this.SDKConfig.dataPlan.PlanVersion=dataPlan.planVersion;}else {mpInstance.Logger.error('Your data plan version must be a number');}}}else {this.SDKConfig.dataPlan={};}if(config.hasOwnProperty('forceHttps')){this.SDKConfig.forceHttps=config.forceHttps;}else {this.SDKConfig.forceHttps=true;}// Some forwarders require custom flags on initialization, so allow them to be set using config object + this.SDKConfig.customFlags=config.customFlags||{};if(config.hasOwnProperty('minWebviewBridgeVersion')){this.SDKConfig.minWebviewBridgeVersion=config.minWebviewBridgeVersion;}else {this.SDKConfig.minWebviewBridgeVersion=1;}if(config.hasOwnProperty('aliasMaxWindow')){this.SDKConfig.aliasMaxWindow=config.aliasMaxWindow;}else {this.SDKConfig.aliasMaxWindow=Constants.DefaultConfig.aliasMaxWindow;}if(config.hasOwnProperty('dataPlanOptions')){var dataPlanOptions=config.dataPlanOptions;if(!dataPlanOptions.hasOwnProperty('dataPlanVersion')||!dataPlanOptions.hasOwnProperty('blockUserAttributes')||!dataPlanOptions.hasOwnProperty('blockEventAttributes')||!dataPlanOptions.hasOwnProperty('blockEvents')||!dataPlanOptions.hasOwnProperty('blockUserIdentities')){mpInstance.Logger.error('Ensure your config.dataPlanOptions object has the following keys: a "dataPlanVersion" object, and "blockUserAttributes", "blockEventAttributes", "blockEvents", "blockUserIdentities" booleans');}}if(config.hasOwnProperty('onCreateBatch')){if(typeof config.onCreateBatch==='function'){this.SDKConfig.onCreateBatch=config.onCreateBatch;}else {mpInstance.Logger.error('config.onCreateBatch must be a function');// set to undefined because all items are set on createSDKConfig + this.SDKConfig.onCreateBatch=undefined;}}if(!config.hasOwnProperty('flags')){this.SDKConfig.flags={};}if(!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.EventBatchingIntervalMillis)){this.SDKConfig.flags[Constants.FeatureFlags.EventBatchingIntervalMillis]=Constants.DefaultConfig.uploadInterval;}if(!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.ReportBatching)){this.SDKConfig.flags[Constants.FeatureFlags.ReportBatching]=false;}if(!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.OfflineStorage)){this.SDKConfig.flags[Constants.FeatureFlags.OfflineStorage]=0;}}}function commonjsRequire(path){throw new Error('Could not dynamically require "'+path+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');}var sinon$3={exports:{}};/* Sinon.JS 16.1.0, 2023-10-05, @license BSD-3 */sinon$3.exports;(function(module,exports){(function(f){{module.exports=f();}})(function(){return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof commonjsRequire&&commonjsRequire;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof commonjsRequire&&commonjsRequire,i=0;i=0){return args[callArgAt];}var argumentList;if(callArgAt===useLeftMostCallback){argumentList=args;}if(callArgAt===useRightMostCallback){argumentList=reverse(slice(args));}var callArgProp=behavior.callArgProp;for(var i=0,l=argumentList.length;i0){msg+=" Received [".concat(join(args,", "),"]");}return msg;}return "argument at index ".concat(behavior.callArgAt," is not a function: ").concat(func);}function ensureArgs(name,behavior,args){// map function name to internal property + // callsArg => callArgAt + var property=name.replace(/sArg/,"ArgAt");var index=behavior[property];if(index>=args.length){throw new TypeError("".concat(name," failed: ").concat(index+1," arguments required but only ").concat(args.length," present"));}}function callCallback(behavior,args){if(typeof behavior.callArgAt==="number"){ensureArgs("callsArg",behavior,args);var func=getCallback(behavior,args);if(typeof func!=="function"){throw new TypeError(getCallbackError(behavior,func,args));}if(behavior.callbackAsync){nextTick(function(){func.apply(behavior.callbackContext,behavior.callbackArguments);});}else {return func.apply(behavior.callbackContext,behavior.callbackArguments);}}return undefined;}var proto={create:function create(stub){var behavior=extend({},proto);delete behavior.create;delete behavior.addBehavior;delete behavior.createBehavior;behavior.stub=stub;if(stub.defaultBehavior&&stub.defaultBehavior.promiseLibrary){behavior.promiseLibrary=stub.defaultBehavior.promiseLibrary;}return behavior;},isPresent:function isPresent(){return typeof this.callArgAt==="number"||this.exception||this.exceptionCreator||typeof this.returnArgAt==="number"||this.returnThis||typeof this.resolveArgAt==="number"||this.resolveThis||typeof this.throwArgAt==="number"||this.fakeFn||this.returnValueDefined;},/*eslint complexity: ["error", 20]*/invoke:function invoke(context,args){/* + * callCallback (conditionally) calls ensureArgs + * + * Note: callCallback intentionally happens before + * everything else and cannot be moved lower + */var returnValue=callCallback(this,args);if(this.exception){throw this.exception;}else if(this.exceptionCreator){this.exception=this.exceptionCreator();this.exceptionCreator=undefined;throw this.exception;}else if(typeof this.returnArgAt==="number"){ensureArgs("returnsArg",this,args);return args[this.returnArgAt];}else if(this.returnThis){return context;}else if(typeof this.throwArgAt==="number"){ensureArgs("throwsArg",this,args);throw args[this.throwArgAt];}else if(this.fakeFn){return this.fakeFn.apply(context,args);}else if(typeof this.resolveArgAt==="number"){ensureArgs("resolvesArg",this,args);return (this.promiseLibrary||Promise).resolve(args[this.resolveArgAt]);}else if(this.resolveThis){return (this.promiseLibrary||Promise).resolve(context);}else if(this.resolve){return (this.promiseLibrary||Promise).resolve(this.returnValue);}else if(this.reject){return (this.promiseLibrary||Promise).reject(this.returnValue);}else if(this.callsThrough){var wrappedMethod=this.effectiveWrappedMethod();return wrappedMethod.apply(context,args);}else if(this.callsThroughWithNew){// Get the original method (assumed to be a constructor in this case) + var WrappedClass=this.effectiveWrappedMethod();// Turn the arguments object into a normal array + var argsArray=slice(args);// Call the constructor + var F=WrappedClass.bind.apply(WrappedClass,concat([null],argsArray));return new F();}else if(typeof this.returnValue!=="undefined"){return this.returnValue;}else if(typeof this.callArgAt==="number"){return returnValue;}return this.returnValue;},effectiveWrappedMethod:function effectiveWrappedMethod(){for(var stubb=this.stub;stubb;stubb=stubb.parent){if(stubb.wrappedMethod){return stubb.wrappedMethod;}}throw new Error("Unable to find wrapped method");},onCall:function onCall(index){return this.stub.onCall(index);},onFirstCall:function onFirstCall(){return this.stub.onFirstCall();},onSecondCall:function onSecondCall(){return this.stub.onSecondCall();},onThirdCall:function onThirdCall(){return this.stub.onThirdCall();},withArgs:function withArgs(/* arguments */){throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" '+'is not supported. Use "stub.withArgs(...).onCall(...)" '+"to define sequential behavior for calls with certain arguments.");}};function createBehavior(behaviorMethod){return function(){this.defaultBehavior=this.defaultBehavior||proto.create(this);this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior,arguments);return this;};}function addBehavior(stub,name,fn){proto[name]=function(){fn.apply(this,concat([this],slice(arguments)));return this.stub||this;};stub[name]=createBehavior(name);}proto.addBehavior=addBehavior;proto.createBehavior=createBehavior;var asyncBehaviors=exportAsyncBehaviors(proto);module.exports=extend.nonEnum({},proto,asyncBehaviors);},{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/next-tick":33,"@sinonjs/commons":47}],4:[function(require,module,exports){var walk=require("./util/core/walk");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var push=require("@sinonjs/commons").prototypes.array.push;function collectMethod(methods,object,prop,propOwner){if(typeof getPropertyDescriptor(propOwner,prop).value==="function"&&hasOwnProperty(object,prop)){push(methods,object[prop]);}}// This function returns an array of all the own methods on the passed object + function collectOwnMethods(object){var methods=[];walk(object,collectMethod.bind(null,methods,object));return methods;}module.exports=collectOwnMethods;},{"./util/core/get-property-descriptor":28,"./util/core/walk":38,"@sinonjs/commons":47}],5:[function(require,module,exports){var supportsColor=require("supports-color");function colorize(str,color){if(supportsColor.stdout===false){return str;}return "\x1B[".concat(color,"m").concat(str,"\x1B[0m");}exports.red=function(str){return colorize(str,31);};exports.green=function(str){return colorize(str,32);};exports.cyan=function(str){return colorize(str,96);};exports.white=function(str){return colorize(str,39);};exports.bold=function(str){return colorize(str,1);};},{"supports-color":149}],6:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var Sandbox=require("./sandbox");var forEach=arrayProto.forEach;var push=arrayProto.push;function prepareSandboxFromConfig(config){var sandbox=new Sandbox();if(config.useFakeServer){if(_typeof$1(config.useFakeServer)==="object"){sandbox.serverPrototype=config.useFakeServer;}sandbox.useFakeServer();}if(config.useFakeTimers){if(_typeof$1(config.useFakeTimers)==="object"){sandbox.useFakeTimers(config.useFakeTimers);}else {sandbox.useFakeTimers();}}return sandbox;}function exposeValue(sandbox,config,key,value){if(!value){return;}if(config.injectInto&&!(key in config.injectInto)){config.injectInto[key]=value;push(sandbox.injectedKeys,key);}else {push(sandbox.args,value);}}function createSandbox(config){if(!config){return new Sandbox();}var configuredSandbox=prepareSandboxFromConfig(config);configuredSandbox.args=configuredSandbox.args||[];configuredSandbox.injectedKeys=[];configuredSandbox.injectInto=config.injectInto;var exposed=configuredSandbox.inject({});if(config.properties){forEach(config.properties,function(prop){var value=exposed[prop]||prop==="sandbox"&&configuredSandbox;exposeValue(configuredSandbox,config,prop,value);});}else {exposeValue(configuredSandbox,config,"sandbox");}return configuredSandbox;}module.exports=createSandbox;},{"./sandbox":18,"@sinonjs/commons":47}],7:[function(require,module,exports){var stub=require("./stub");var sinonType=require("./util/core/sinon-type");var forEach=require("@sinonjs/commons").prototypes.array.forEach;function isStub(value){return sinonType.get(value)==="stub";}module.exports=function createStubInstance(constructor,overrides){if(typeof constructor!=="function"){throw new TypeError("The constructor should be a function.");}var stubInstance=Object.create(constructor.prototype);sinonType.set(stubInstance,"stub-instance");var stubbedObject=stub(stubInstance);forEach(Object.keys(overrides||{}),function(propertyName){if(propertyName in stubbedObject){var value=overrides[propertyName];if(isStub(value)){stubbedObject[propertyName]=value;}else {stubbedObject[propertyName].returns(value);}}else {throw new Error("Cannot stub ".concat(propertyName,". Property does not exist!"));}});return stubbedObject;};},{"./stub":21,"./util/core/sinon-type":34,"@sinonjs/commons":47}],8:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var isPropertyConfigurable=require("./util/core/is-property-configurable");var exportAsyncBehaviors=require("./util/core/export-async-behaviors");var extend=require("./util/core/extend");var slice=arrayProto.slice;var useLeftMostCallback=-1;var useRightMostCallback=-2;function throwsException(fake,error,message){if(typeof error==="function"){fake.exceptionCreator=error;}else if(typeof error==="string"){fake.exceptionCreator=function(){var newException=new Error(message||"Sinon-provided ".concat(error));newException.name=error;return newException;};}else if(!error){fake.exceptionCreator=function(){return new Error("Error");};}else {fake.exception=error;}}var defaultBehaviors={callsFake:function callsFake(fake,fn){fake.fakeFn=fn;fake.exception=undefined;fake.exceptionCreator=undefined;},callsArg:function callsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOn:function callsArgOn(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgWith:function callsArgWith(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOnWith:function callsArgWith(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},usingPromise:function usingPromise(fake,promiseLibrary){fake.promiseLibrary=promiseLibrary;},yields:function yields(fake){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsRight:function yieldsRight(fake){fake.callArgAt=useRightMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsOn:function yieldsOn(fake,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsTo:function yieldsTo(fake,prop){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsToOn:function yieldsToOn(fake,prop,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},"throws":throwsException,throwsException:throwsException,returns:function returns(fake,value){fake.returnValue=value;fake.resolve=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},returnsArg:function returnsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.returnArgAt=index;},throwsArg:function throwsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.throwArgAt=index;},returnsThis:function returnsThis(fake){fake.returnThis=true;},resolves:function resolves(fake,value){fake.returnValue=value;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},resolvesArg:function resolvesArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.resolveArgAt=index;fake.returnValue=undefined;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},rejects:function rejects(fake,error,message){var reason;if(typeof error==="string"){reason=new Error(message||"");reason.name=error;}else if(!error){reason=new Error("Error");}else {reason=error;}fake.returnValue=reason;fake.resolve=false;fake.resolveThis=false;fake.reject=true;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;return fake;},resolvesThis:function resolvesThis(fake){fake.returnValue=undefined;fake.resolve=false;fake.resolveThis=true;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},callThrough:function callThrough(fake){fake.callsThrough=true;},callThroughWithNew:function callThroughWithNew(fake){fake.callsThroughWithNew=true;},get:function get(fake,getterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{get:getterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},set:function set(fake,setterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,// eslint-disable-next-line accessor-pairs + {set:setterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},value:function value(fake,newVal){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{value:newVal,enumerable:true,writable:true,configurable:rootStub.shadowsPropOnPrototype||isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;}};var asyncBehaviors=exportAsyncBehaviors(defaultBehaviors);module.exports=extend({},defaultBehaviors,asyncBehaviors);},{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/is-property-configurable":31,"@sinonjs/commons":47}],9:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var createProxy=require("./proxy");var nextTick=require("./util/core/next-tick");var slice=arrayProto.slice;var promiseLib=Promise;module.exports=fake;/** + * Returns a `fake` that records all calls, arguments and return values. + * + * When an `f` argument is supplied, this implementation will be used. + * + * @example + * // create an empty fake + * var f1 = sinon.fake(); + * + * f1(); + * + * f1.calledOnce() + * // true + * + * @example + * function greet(greeting) { + * console.log(`Hello ${greeting}`); + * } + * + * // create a fake with implementation + * var f2 = sinon.fake(greet); + * + * // Hello world + * f2("world"); + * + * f2.calledWith("world"); + * // true + * + * @param {Function|undefined} f + * @returns {Function} + * @namespace + */function fake(f){if(arguments.length>0&&typeof f!=="function"){throw new TypeError("Expected f argument to be a Function");}return wrapFunc(f);}/** + * Creates a `fake` that returns the provided `value`, as well as recording all + * calls, arguments and return values. + * + * @example + * var f1 = sinon.fake.returns(42); + * + * f1(); + * // 42 + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.returns=function returns(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return value;}return wrapFunc(f);};/** + * Creates a `fake` that throws an Error. + * If the `value` argument does not have Error in its prototype chain, it will + * be used for creating a new error. + * + * @example + * var f1 = sinon.fake.throws("hello"); + * + * f1(); + * // Uncaught Error: hello + * + * @example + * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); + * + * f2(); + * // Uncaught TypeError: Invalid argument + * + * @memberof fake + * @param {*|Error} value + * @returns {Function} + */fake["throws"]=function _throws(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){throw getError(value);}return wrapFunc(f);};/** + * Creates a `fake` that returns a promise that resolves to the passed `value` + * argument. + * + * @example + * var f1 = sinon.fake.resolves("apple pie"); + * + * await f1(); + * // "apple pie" + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.resolves=function resolves(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return promiseLib.resolve(value);}return wrapFunc(f);};/** + * Creates a `fake` that returns a promise that rejects to the passed `value` + * argument. When `value` does not have Error in its prototype chain, it will be + * wrapped in an Error. + * + * @example + * var f1 = sinon.fake.rejects(":("); + * + * try { + * await ft(); + * } catch (error) { + * console.log(error); + * // ":(" + * } + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.rejects=function rejects(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return promiseLib.reject(getError(value));}return wrapFunc(f);};/** + * Causes `fake` to use a custom Promise implementation, instead of the native + * Promise implementation. + * + * @example + * const bluebird = require("bluebird"); + * sinon.fake.usingPromise(bluebird); + * + * @memberof fake + * @param {*} promiseLibrary + * @returns {Function} + */fake.usingPromise=function usingPromise(promiseLibrary){promiseLib=promiseLibrary;return fake;};/** + * Returns a `fake` that calls the callback with the defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * // "apple*pie" + * + * @memberof fake + * @returns {Function} + */fake.yields=function yields(){var values=slice(arguments);// eslint-disable-next-line jsdoc/require-jsdoc + function f(){var callback=arguments[arguments.length-1];if(typeof callback!=="function"){throw new TypeError("Expected last argument to be a function");}callback.apply(null,values);}return wrapFunc(f);};/** + * Returns a `fake` that calls the callback **asynchronously** with the + * defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * + * setTimeout(() => { + * // "apple*pie" + * }); + * + * @memberof fake + * @returns {Function} + */fake.yieldsAsync=function yieldsAsync(){var values=slice(arguments);// eslint-disable-next-line jsdoc/require-jsdoc + function f(){var callback=arguments[arguments.length-1];if(typeof callback!=="function"){throw new TypeError("Expected last argument to be a function");}nextTick(function(){callback.apply(null,values);});}return wrapFunc(f);};var uuid=0;/** + * Creates a proxy (sinon concept) from the passed function. + * + * @private + * @param {Function} f + * @returns {Function} + */function wrapFunc(f){var fakeInstance=function fakeInstance(){var firstArg,lastArg;if(arguments.length>0){firstArg=arguments[0];lastArg=arguments[arguments.length-1];}var callback=lastArg&&typeof lastArg==="function"?lastArg:undefined;/* eslint-disable no-use-before-define */proxy.firstArg=firstArg;proxy.lastArg=lastArg;proxy.callback=callback;return f&&f.apply(this,arguments);};var proxy=createProxy(fakeInstance,f||fakeInstance);proxy.displayName="fake";proxy.id="fake#".concat(uuid++);return proxy;}/** + * Returns an Error instance from the passed value, if the value is not + * already an Error instance. + * + * @private + * @param {*} value [description] + * @returns {Error} [description] + */function getError(value){return value instanceof Error?value:new Error(value);}},{"./proxy":16,"./util/core/next-tick":33,"@sinonjs/commons":47}],10:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var proxyInvoke=require("./proxy-invoke");var proxyCallToString=require("./proxy-call").toString;var timesInWords=require("./util/core/times-in-words");var extend=require("./util/core/extend");var match=require("@sinonjs/samsam").createMatcher;var stub=require("./stub");var assert=require("./assert");var deepEqual=require("@sinonjs/samsam").deepEqual;var inspect=require("util").inspect;var valueToString=require("@sinonjs/commons").valueToString;var every=arrayProto.every;var forEach=arrayProto.forEach;var push=arrayProto.push;var slice=arrayProto.slice;function callCountInWords(callCount){if(callCount===0){return "never called";}return "called ".concat(timesInWords(callCount));}function expectedCallCountInWords(expectation){var min=expectation.minCalls;var max=expectation.maxCalls;if(typeof min==="number"&&typeof max==="number"){var str=timesInWords(min);if(min!==max){str="at least ".concat(str," and at most ").concat(timesInWords(max));}return str;}if(typeof min==="number"){return "at least ".concat(timesInWords(min));}return "at most ".concat(timesInWords(max));}function receivedMinCalls(expectation){var hasMinLimit=typeof expectation.minCalls==="number";return !hasMinLimit||expectation.callCount>=expectation.minCalls;}function receivedMaxCalls(expectation){if(typeof expectation.maxCalls!=="number"){return false;}return expectation.callCount===expectation.maxCalls;}function verifyMatcher(possibleMatcher,arg){var isMatcher=match.isMatcher(possibleMatcher);return isMatcher&&possibleMatcher.test(arg)||true;}var mockExpectation={minCalls:1,maxCalls:1,create:function create(methodName){var expectation=extend.nonEnum(stub(),mockExpectation);delete expectation.create;expectation.method=methodName;return expectation;},invoke:function invoke(func,thisValue,args){this.verifyCallAllowed(thisValue,args);return proxyInvoke.apply(this,arguments);},atLeast:function atLeast(num){if(typeof num!=="number"){throw new TypeError("'".concat(valueToString(num),"' is not number"));}if(!this.limitsSet){this.maxCalls=null;this.limitsSet=true;}this.minCalls=num;return this;},atMost:function atMost(num){if(typeof num!=="number"){throw new TypeError("'".concat(valueToString(num),"' is not number"));}if(!this.limitsSet){this.minCalls=null;this.limitsSet=true;}this.maxCalls=num;return this;},never:function never(){return this.exactly(0);},once:function once(){return this.exactly(1);},twice:function twice(){return this.exactly(2);},thrice:function thrice(){return this.exactly(3);},exactly:function exactly(num){if(typeof num!=="number"){throw new TypeError("'".concat(valueToString(num),"' is not a number"));}this.atLeast(num);return this.atMost(num);},met:function met(){return !this.failed&&receivedMinCalls(this);},verifyCallAllowed:function verifyCallAllowed(thisValue,args){var expectedArguments=this.expectedArguments;if(receivedMaxCalls(this)){this.failed=true;mockExpectation.fail("".concat(this.method," already called ").concat(timesInWords(this.maxCalls)));}if("expectedThis"in this&&this.expectedThis!==thisValue){mockExpectation.fail("".concat(this.method," called with ").concat(valueToString(thisValue)," as thisValue, expected ").concat(valueToString(this.expectedThis)));}if(!("expectedArguments"in this)){return;}if(!args){mockExpectation.fail("".concat(this.method," received no arguments, expected ").concat(inspect(expectedArguments)));}if(args.length0){mockExpectation.fail(join(concat(messages,met),"\n"));}else if(met.length>0){mockExpectation.pass(join(concat(messages,met),"\n"));}return true;},usingPromise:function usingPromise(promiseLibrary){this.promiseLibrary=promiseLibrary;return this;},invokeMethod:function invokeMethod(method,thisValue,args){/* if we cannot find any matching files we will explicitly call mockExpection#fail with error messages */ /* eslint consistent-return: "off" */var expectations=this.expectations&&this.expectations[method]?this.expectations[method]:[];var currentArgs=args||[];var available;var expectationsWithMatchingArgs=filter(expectations,function(expectation){var expectedArgs=expectation.expectedArguments||[];return arrayEquals(expectedArgs,currentArgs,expectation.expectsExactArgCount);});var expectationsToApply=filter(expectationsWithMatchingArgs,function(expectation){return !expectation.met()&&expectation.allowsCall(thisValue,args);});if(expectationsToApply.length>0){return expectationsToApply[0].apply(thisValue,args);}var messages=[];var exhausted=0;forEach(expectationsWithMatchingArgs,function(expectation){if(expectation.allowsCall(thisValue,args)){available=available||expectation;}else {exhausted+=1;}});if(available&&exhausted===0){return available.apply(thisValue,args);}forEach(expectations,function(expectation){push(messages," ".concat(String(expectation)));});unshift(messages,"Unexpected call: ".concat(proxyCallToString.call({proxy:method,args:args})));var err=new Error();if(!err.stack){// PhantomJS does not serialize the stack trace until the error has been thrown + try{throw err;}catch(e){/* empty */}}push(this.failures,"Unexpected call: ".concat(proxyCallToString.call({proxy:method,args:args,stack:err.stack})));mockExpectation.fail(join(messages,"\n"));}});module.exports=mock;},{"./mock-expectation":10,"./proxy-call":14,"./util/core/extend":25,"./util/core/use-promise-library":36,"./util/core/wrap-method":39,"@sinonjs/commons":47,"@sinonjs/samsam":87}],12:[function(require,module,exports){var fake=require("./fake");var isRestorable=require("./util/core/is-restorable");var STATUS_PENDING="pending";var STATUS_RESOLVED="resolved";var STATUS_REJECTED="rejected";/** + * Returns a fake for a given function or undefined. If no function is given, a + * new fake is returned. If the given function is already a fake, it is + * returned as is. Otherwise the given function is wrapped in a new fake. + * + * @param {Function} [executor] The optional executor function. + * @returns {Function} + */function getFakeExecutor(executor){if(isRestorable(executor)){return executor;}if(executor){return fake(executor);}return fake();}/** + * Returns a new promise that exposes it's internal `status`, `resolvedValue` + * and `rejectedValue` and can be resolved or rejected from the outside by + * calling `resolve(value)` or `reject(reason)`. + * + * @param {Function} [executor] The optional executor function. + * @returns {Promise} + */function promise(executor){var fakeExecutor=getFakeExecutor(executor);var sinonPromise=new Promise(fakeExecutor);sinonPromise.status=STATUS_PENDING;sinonPromise.then(function(value){sinonPromise.status=STATUS_RESOLVED;sinonPromise.resolvedValue=value;})["catch"](function(reason){sinonPromise.status=STATUS_REJECTED;sinonPromise.rejectedValue=reason;});/** + * Resolves or rejects the promise with the given status and value. + * + * @param {string} status + * @param {*} value + * @param {Function} callback + */function finalize(status,value,callback){if(sinonPromise.status!==STATUS_PENDING){throw new Error("Promise already ".concat(sinonPromise.status));}sinonPromise.status=status;callback(value);}sinonPromise.resolve=function(value){finalize(STATUS_RESOLVED,value,fakeExecutor.firstCall.args[0]);// Return the promise so that callers can await it: + return sinonPromise;};sinonPromise.reject=function(reason){finalize(STATUS_REJECTED,reason,fakeExecutor.firstCall.args[1]);// Return a new promise that resolves when the sinon promise was + // rejected, so that callers can await it: + return new Promise(function(resolve){sinonPromise["catch"](function(){return resolve();});});};return sinonPromise;}module.exports=promise;},{"./fake":9,"./util/core/is-restorable":32}],13:[function(require,module,exports){var push=require("@sinonjs/commons").prototypes.array.push;exports.incrementCallCount=function incrementCallCount(proxy){proxy.called=true;proxy.callCount+=1;proxy.notCalled=false;proxy.calledOnce=proxy.callCount===1;proxy.calledTwice=proxy.callCount===2;proxy.calledThrice=proxy.callCount===3;};exports.createCallProperties=function createCallProperties(proxy){proxy.firstCall=proxy.getCall(0);proxy.secondCall=proxy.getCall(1);proxy.thirdCall=proxy.getCall(2);proxy.lastCall=proxy.getCall(proxy.callCount-1);};exports.delegateToCalls=function delegateToCalls(proxy,method,matchAny,actual,returnsValues,notCalled,totalCallCount){proxy[method]=function(){if(!this.called){if(notCalled){return notCalled.apply(this,arguments);}return false;}if(totalCallCount!==undefined&&this.callCount!==totalCallCount){return false;}var currentCall;var matches=0;var returnValues=[];for(var i=0,l=this.callCount;iself.args.length){return false;}return reduce(calledWithArgs,function(prev,arg,i){return prev&&deepEqual(self.args[i],arg);},true);},calledWithMatch:function calledWithMatch(){var self=this;var calledWithMatchArgs=slice(arguments);if(calledWithMatchArgs.length>self.args.length){return false;}return reduce(calledWithMatchArgs,function(prev,expectation,i){var actual=self.args[i];return prev&&match(expectation).test(actual);},true);},calledWithExactly:function calledWithExactly(){return arguments.length===this.args.length&&this.calledWith.apply(this,arguments);},notCalledWith:function notCalledWith(){return !this.calledWith.apply(this,arguments);},notCalledWithMatch:function notCalledWithMatch(){return !this.calledWithMatch.apply(this,arguments);},returned:function returned(value){return deepEqual(this.returnValue,value);},threw:function threw(error){if(typeof error==="undefined"||!this.exception){return Boolean(this.exception);}return this.exception===error||this.exception.name===error;},calledWithNew:function calledWithNew(){return this.proxy.prototype&&this.thisValue instanceof this.proxy;},calledBefore:function calledBefore(other){return this.callIdother.callId;},calledImmediatelyBefore:function calledImmediatelyBefore(other){return this.callId===other.callId-1;},calledImmediatelyAfter:function calledImmediatelyAfter(other){return this.callId===other.callId+1;},callArg:function callArg(pos){this.ensureArgIsAFunction(pos);return this.args[pos]();},callArgOn:function callArgOn(pos,thisValue){this.ensureArgIsAFunction(pos);return this.args[pos].apply(thisValue);},callArgWith:function callArgWith(pos){return this.callArgOnWith.apply(this,concat([pos,null],slice(arguments,1)));},callArgOnWith:function callArgOnWith(pos,thisValue){this.ensureArgIsAFunction(pos);var args=slice(arguments,2);return this.args[pos].apply(thisValue,args);},throwArg:function throwArg(pos){if(pos>this.args.length){throw new TypeError("Not enough arguments: ".concat(pos," required but only ").concat(this.args.length," present"));}throw this.args[pos];},"yield":function _yield(){return this.yieldOn.apply(this,concat([null],slice(arguments,0)));},yieldOn:function yieldOn(thisValue){var args=slice(this.args);var yieldFn=filter(args,function(arg){return typeof arg==="function";})[0];if(!yieldFn){throwYieldError(this.proxy," cannot yield since no callback was passed.",args);}return yieldFn.apply(thisValue,slice(arguments,1));},yieldTo:function yieldTo(prop){return this.yieldToOn.apply(this,concat([prop,null],slice(arguments,1)));},yieldToOn:function yieldToOn(prop,thisValue){var args=slice(this.args);var yieldArg=filter(args,function(arg){return arg&&typeof arg[prop]==="function";})[0];var yieldFn=yieldArg&&yieldArg[prop];if(!yieldFn){throwYieldError(this.proxy," cannot yield to '".concat(valueToString(prop),"' since no callback was passed."),args);}return yieldFn.apply(thisValue,slice(arguments,2));},toString:function toString(){if(!this.args){return ":(";}var callStr=this.proxy?"".concat(String(this.proxy),"("):"";var formattedArgs=map(this.args,function(arg){return inspect(arg);});callStr="".concat(callStr+join(formattedArgs,", "),")");if(typeof this.returnValue!=="undefined"){callStr+=" => ".concat(inspect(this.returnValue));}if(this.exception){callStr+=" !".concat(this.exception.name);if(this.exception.message){callStr+="(".concat(this.exception.message,")");}}if(this.stack){// If we have a stack, add the first frame that's in end-user code + // Skip the first two frames because they will refer to Sinon code + callStr+=(this.stack.split("\n")[3]||"unknown").replace(/^\s*(?:at\s+|@)?/," at ");}return callStr;},ensureArgIsAFunction:function ensureArgIsAFunction(pos){if(typeof this.args[pos]!=="function"){throw new TypeError("Expected argument at position ".concat(pos," to be a Function, but was ").concat(_typeof$1(this.args[pos])));}}};Object.defineProperty(callProto,"stack",{enumerable:true,configurable:true,get:function get(){return this.errorWithCallStack&&this.errorWithCallStack.stack||"";}});callProto.invokeCallback=callProto["yield"];/** + * @param proxy + * @param thisValue + * @param args + * @param returnValue + * @param exception + * @param id + * @param errorWithCallStack + */function createProxyCall(proxy,thisValue,args,returnValue,exception,id,errorWithCallStack){if(typeof id!=="number"){throw new TypeError("Call id is not a number");}var firstArg,lastArg;if(args.length>0){firstArg=args[0];lastArg=args[args.length-1];}var proxyCall=Object.create(callProto);var callback=lastArg&&typeof lastArg==="function"?lastArg:undefined;proxyCall.proxy=proxy;proxyCall.thisValue=thisValue;proxyCall.args=args;proxyCall.firstArg=firstArg;proxyCall.lastArg=lastArg;proxyCall.callback=callback;proxyCall.returnValue=returnValue;proxyCall.exception=exception;proxyCall.callId=id;proxyCall.errorWithCallStack=errorWithCallStack;return proxyCall;}createProxyCall.toString=callProto.toString;// used by mocks + module.exports=createProxyCall;},{"@sinonjs/commons":47,"@sinonjs/samsam":87,"util":112}],15:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var proxyCallUtil=require("./proxy-call-util");var push=arrayProto.push;var forEach=arrayProto.forEach;var concat=arrayProto.concat;var ErrorConstructor=Error.prototype.constructor;var bind=Function.prototype.bind;var callId=0;module.exports=function invoke(func,thisValue,args){var matchings=this.matchingFakes(args);var currentCallId=callId++;var exception,returnValue;proxyCallUtil.incrementCallCount(this);push(this.thisValues,thisValue);push(this.args,args);push(this.callIds,currentCallId);forEach(matchings,function(matching){proxyCallUtil.incrementCallCount(matching);push(matching.thisValues,thisValue);push(matching.args,args);push(matching.callIds,currentCallId);});// Make call properties available from within the spied function: + proxyCallUtil.createCallProperties(this);forEach(matchings,proxyCallUtil.createCallProperties);try{this.invoking=true;var thisCall=this.getCall(this.callCount-1);if(thisCall.calledWithNew()){// Call through with `new` + returnValue=new(bind.apply(this.func||func,concat([thisValue],args)))();if(_typeof$1(returnValue)!=="object"&&typeof returnValue!=="function"){returnValue=thisValue;}}else {returnValue=(this.func||func).apply(thisValue,args);}}catch(e){exception=e;}finally{delete this.invoking;}push(this.exceptions,exception);push(this.returnValues,returnValue);forEach(matchings,function(matching){push(matching.exceptions,exception);push(matching.returnValues,returnValue);});var err=new ErrorConstructor();// 1. Please do not get stack at this point. It may be so very slow, and not actually used + // 2. PhantomJS does not serialize the stack trace until the error has been thrown: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack + try{throw err;}catch(e){/* empty */}push(this.errorsWithCallStack,err);forEach(matchings,function(matching){push(matching.errorsWithCallStack,err);});// Make return value and exception available in the calls: + proxyCallUtil.createCallProperties(this);forEach(matchings,proxyCallUtil.createCallProperties);if(exception!==undefined){throw exception;}return returnValue;};},{"./proxy-call-util":13,"@sinonjs/commons":47}],16:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var extend=require("./util/core/extend");var functionToString=require("./util/core/function-to-string");var proxyCall=require("./proxy-call");var proxyCallUtil=require("./proxy-call-util");var proxyInvoke=require("./proxy-invoke");var inspect=require("util").inspect;var push=arrayProto.push;var forEach=arrayProto.forEach;var slice=arrayProto.slice;var emptyFakes=Object.freeze([]);// Public API + var proxyApi={toString:functionToString,named:function named(name){this.displayName=name;var nameDescriptor=Object.getOwnPropertyDescriptor(this,"name");if(nameDescriptor&&nameDescriptor.configurable){// IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + nameDescriptor.value=name;Object.defineProperty(this,"name",nameDescriptor);}return this;},invoke:proxyInvoke,/* + * Hook for derived implementation to return fake instances matching the + * given arguments. + */matchingFakes:function matchingFakes(/*args, strict*/){return emptyFakes;},getCall:function getCall(index){var i=index;if(i<0){// Negative indices means counting backwards from the last call + i+=this.callCount;}if(i<0||i>=this.callCount){return null;}return proxyCall(this,this.thisValues[i],this.args[i],this.returnValues[i],this.exceptions[i],this.callIds[i],this.errorsWithCallStack[i]);},getCalls:function getCalls(){var calls=[];var i;for(i=0;iproxy.callIds[0];},calledImmediatelyBefore:function calledImmediatelyBefore(proxy){if(!this.called||!proxy.called){return false;}return this.callIds[this.callCount-1]===proxy.callIds[proxy.callCount-1]-1;},calledImmediatelyAfter:function calledImmediatelyAfter(proxy){if(!this.called||!proxy.called){return false;}return this.callIds[this.callCount-1]===proxy.callIds[proxy.callCount-1]+1;},formatters:require("./spy-formatters"),printf:function printf(format){var spyInstance=this;var args=slice(arguments,1);var formatter;return (format||"").replace(/%(.)/g,function(match,specifier){formatter=proxyApi.formatters[specifier];if(typeof formatter==="function"){return String(formatter(spyInstance,args));}else if(!isNaN(parseInt(specifier,10))){return inspect(args[specifier-1]);}return "%".concat(specifier);});},resetHistory:function resetHistory(){if(this.invoking){var err=new Error("Cannot reset Sinon function while invoking it. "+"Move the call to .resetHistory outside of the callback.");err.name="InvalidResetException";throw err;}this.called=false;this.notCalled=true;this.calledOnce=false;this.calledTwice=false;this.calledThrice=false;this.callCount=0;this.firstCall=null;this.secondCall=null;this.thirdCall=null;this.lastCall=null;this.args=[];this.firstArg=null;this.lastArg=null;this.returnValues=[];this.thisValues=[];this.exceptions=[];this.callIds=[];this.errorsWithCallStack=[];if(this.fakes){forEach(this.fakes,function(fake){fake.resetHistory();});}return this;}};var delegateToCalls=proxyCallUtil.delegateToCalls;delegateToCalls(proxyApi,"calledOn",true);delegateToCalls(proxyApi,"alwaysCalledOn",false,"calledOn");delegateToCalls(proxyApi,"calledWith",true);delegateToCalls(proxyApi,"calledOnceWith",true,"calledWith",false,undefined,1);delegateToCalls(proxyApi,"calledWithMatch",true);delegateToCalls(proxyApi,"alwaysCalledWith",false,"calledWith");delegateToCalls(proxyApi,"alwaysCalledWithMatch",false,"calledWithMatch");delegateToCalls(proxyApi,"calledWithExactly",true);delegateToCalls(proxyApi,"calledOnceWithExactly",true,"calledWithExactly",false,undefined,1);delegateToCalls(proxyApi,"calledOnceWithMatch",true,"calledWithMatch",false,undefined,1);delegateToCalls(proxyApi,"alwaysCalledWithExactly",false,"calledWithExactly");delegateToCalls(proxyApi,"neverCalledWith",false,"notCalledWith",false,function(){return true;});delegateToCalls(proxyApi,"neverCalledWithMatch",false,"notCalledWithMatch",false,function(){return true;});delegateToCalls(proxyApi,"threw",true);delegateToCalls(proxyApi,"alwaysThrew",false,"threw");delegateToCalls(proxyApi,"returned",true);delegateToCalls(proxyApi,"alwaysReturned",false,"returned");delegateToCalls(proxyApi,"calledWithNew",true);delegateToCalls(proxyApi,"alwaysCalledWithNew",false,"calledWithNew");function createProxy(func,originalFunc){var proxy=wrapFunction(func,originalFunc);// Inherit function properties: + extend(proxy,func);proxy.prototype=func.prototype;extend.nonEnum(proxy,proxyApi);return proxy;}function wrapFunction(func,originalFunc){var arity=originalFunc.length;var p;// Do not change this to use an eval. Projects that depend on sinon block the use of eval. + // ref: https://github.com/sinonjs/sinon/issues/710 + switch(arity){/*eslint-disable no-unused-vars, max-len*/case 0:p=function proxy(){return p.invoke(func,this,slice(arguments));};break;case 1:p=function proxy(a){return p.invoke(func,this,slice(arguments));};break;case 2:p=function proxy(a,b){return p.invoke(func,this,slice(arguments));};break;case 3:p=function proxy(a,b,c){return p.invoke(func,this,slice(arguments));};break;case 4:p=function proxy(a,b,c,d){return p.invoke(func,this,slice(arguments));};break;case 5:p=function proxy(a,b,c,d,e){return p.invoke(func,this,slice(arguments));};break;case 6:p=function proxy(a,b,c,d,e,f){return p.invoke(func,this,slice(arguments));};break;case 7:p=function proxy(a,b,c,d,e,f,g){return p.invoke(func,this,slice(arguments));};break;case 8:p=function proxy(a,b,c,d,e,f,g,h){return p.invoke(func,this,slice(arguments));};break;case 9:p=function proxy(a,b,c,d,e,f,g,h,i){return p.invoke(func,this,slice(arguments));};break;case 10:p=function proxy(a,b,c,d,e,f,g,h,i,j){return p.invoke(func,this,slice(arguments));};break;case 11:p=function proxy(a,b,c,d,e,f,g,h,i,j,k){return p.invoke(func,this,slice(arguments));};break;case 12:p=function proxy(a,b,c,d,e,f,g,h,i,j,k,l){return p.invoke(func,this,slice(arguments));};break;default:p=function proxy(){return p.invoke(func,this,slice(arguments));};break;/*eslint-enable*/}var nameDescriptor=Object.getOwnPropertyDescriptor(originalFunc,"name");if(nameDescriptor&&nameDescriptor.configurable){// IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + Object.defineProperty(p,"name",nameDescriptor);}extend.nonEnum(p,{isSinonProxy:true,called:false,notCalled:true,calledOnce:false,calledTwice:false,calledThrice:false,callCount:0,firstCall:null,firstArg:null,secondCall:null,thirdCall:null,lastCall:null,lastArg:null,args:[],returnValues:[],thisValues:[],exceptions:[],callIds:[],errorsWithCallStack:[]});return p;}module.exports=createProxy;},{"./proxy-call":14,"./proxy-call-util":13,"./proxy-invoke":15,"./spy-formatters":19,"./util/core/extend":25,"./util/core/function-to-string":26,"@sinonjs/commons":47,"util":112}],17:[function(require,module,exports){var walkObject=require("./util/core/walk-object");function filter(object,property){return object[property].restore&&object[property].restore.sinon;}function restore(object,property){object[property].restore();}function restoreObject(object){return walkObject(restore,object,filter);}module.exports=restoreObject;},{"./util/core/walk-object":37}],18:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var logger=require("@sinonjs/commons").deprecated;var collectOwnMethods=require("./collect-own-methods");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var isPropertyConfigurable=require("./util/core/is-property-configurable");var match=require("@sinonjs/samsam").createMatcher;var sinonAssert=require("./assert");var sinonClock=require("./util/fake-timers");var sinonMock=require("./mock");var sinonSpy=require("./spy");var sinonStub=require("./stub");var sinonCreateStubInstance=require("./create-stub-instance");var sinonFake=require("./fake");var valueToString=require("@sinonjs/commons").valueToString;var fakeServer=require("nise").fakeServer;var fakeXhr=require("nise").fakeXhr;var usePromiseLibrary=require("./util/core/use-promise-library");var DEFAULT_LEAK_THRESHOLD=10000;var filter=arrayProto.filter;var forEach=arrayProto.forEach;var push=arrayProto.push;var reverse=arrayProto.reverse;function applyOnEach(fakes,method){var matchingFakes=filter(fakes,function(fake){return typeof fake[method]==="function";});forEach(matchingFakes,function(fake){fake[method]();});}function throwOnAccessors(descriptor){if(typeof descriptor.get==="function"){throw new Error("Use sandbox.replaceGetter for replacing getters");}if(typeof descriptor.set==="function"){throw new Error("Use sandbox.replaceSetter for replacing setters");}}function verifySameType(object,property,replacement){if(_typeof$1(object[property])!==_typeof$1(replacement)){throw new TypeError("Cannot replace ".concat(_typeof$1(object[property])," with ").concat(_typeof$1(replacement)));}}function checkForValidArguments(descriptor,property,replacement){if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property),". Perhaps you meant sandbox.define()?"));}if(typeof replacement==="undefined"){throw new TypeError("Expected replacement argument to be defined");}}function Sandbox(){var sandbox=this;var fakeRestorers=[];var promiseLib;var collection=[];var loggedLeakWarning=false;sandbox.leakThreshold=DEFAULT_LEAK_THRESHOLD;function addToCollection(object){if(push(collection,object)>sandbox.leakThreshold&&!loggedLeakWarning){// eslint-disable-next-line no-console + logger.printWarning("Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox.");loggedLeakWarning=true;}}sandbox.assert=sinonAssert.createAssertObject();sandbox.serverPrototype=fakeServer;// this is for testing only + sandbox.getFakes=function getFakes(){return collection;};sandbox.createStubInstance=function createStubInstance(){var stubbed=sinonCreateStubInstance.apply(null,arguments);var ownMethods=collectOwnMethods(stubbed);forEach(ownMethods,function(method){addToCollection(method);});usePromiseLibrary(promiseLib,ownMethods);return stubbed;};sandbox.inject=function inject(obj){obj.spy=function(){return sandbox.spy.apply(null,arguments);};obj.stub=function(){return sandbox.stub.apply(null,arguments);};obj.mock=function(){return sandbox.mock.apply(null,arguments);};obj.createStubInstance=function(){return sandbox.createStubInstance.apply(sandbox,arguments);};obj.fake=function(){return sandbox.fake.apply(null,arguments);};obj.define=function(){return sandbox.define.apply(null,arguments);};obj.replace=function(){return sandbox.replace.apply(null,arguments);};obj.replaceSetter=function(){return sandbox.replaceSetter.apply(null,arguments);};obj.replaceGetter=function(){return sandbox.replaceGetter.apply(null,arguments);};if(sandbox.clock){obj.clock=sandbox.clock;}if(sandbox.server){obj.server=sandbox.server;obj.requests=sandbox.server.requests;}obj.match=match;return obj;};sandbox.mock=function mock(){var m=sinonMock.apply(null,arguments);addToCollection(m);usePromiseLibrary(promiseLib,m);return m;};sandbox.reset=function reset(){applyOnEach(collection,"reset");applyOnEach(collection,"resetHistory");};sandbox.resetBehavior=function resetBehavior(){applyOnEach(collection,"resetBehavior");};sandbox.resetHistory=function resetHistory(){function privateResetHistory(f){var method=f.resetHistory||f.reset;if(method){method.call(f);}}forEach(collection,privateResetHistory);};sandbox.restore=function restore(){if(arguments.length){throw new Error("sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()");}reverse(collection);applyOnEach(collection,"restore");collection=[];forEach(fakeRestorers,function(restorer){restorer();});fakeRestorers=[];sandbox.restoreContext();};sandbox.restoreContext=function restoreContext(){if(!sandbox.injectedKeys){return;}forEach(sandbox.injectedKeys,function(injectedKey){delete sandbox.injectInto[injectedKey];});sandbox.injectedKeys.length=0;};/** + * Creates a restorer function for the property + * + * @param {object|Function} object + * @param {string} property + * @param {boolean} forceAssignment + * @returns {Function} restorer function + */function getFakeRestorer(object,property){var forceAssignment=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var descriptor=getPropertyDescriptor(object,property);var value=object[property];function restorer(){if(forceAssignment){object[property]=value;}else if(descriptor!==null&&descriptor!==void 0&&descriptor.isOwn){Object.defineProperty(object,property,descriptor);}else {delete object[property];}}restorer.object=object;restorer.property=property;return restorer;}function verifyNotReplaced(object,property){forEach(fakeRestorers,function(fakeRestorer){if(fakeRestorer.object===object&&fakeRestorer.property===property){throw new TypeError("Attempted to replace ".concat(property," which is already replaced"));}});}/** + * Replace an existing property + * + * @param {object|Function} object + * @param {string} property + * @param {*} replacement a fake, stub, spy or any other value + * @returns {*} + */sandbox.replace=function replace(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);checkForValidArguments(descriptor,property,replacement);throwOnAccessors(descriptor);verifySameType(object,property,replacement);verifyNotReplaced(object,property);// store a function for restoring the replaced property + push(fakeRestorers,getFakeRestorer(object,property));object[property]=replacement;return replacement;};sandbox.replace.usingAccessor=function replaceUsingAccessor(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);checkForValidArguments(descriptor,property,replacement);verifySameType(object,property,replacement);verifyNotReplaced(object,property);// store a function for restoring the replaced property + push(fakeRestorers,getFakeRestorer(object,property,true));object[property]=replacement;return replacement;};sandbox.define=function define(object,property,value){var descriptor=getPropertyDescriptor(object,property);if(descriptor){throw new TypeError("Cannot define the already existing property ".concat(valueToString(property),". Perhaps you meant sandbox.replace()?"));}if(typeof value==="undefined"){throw new TypeError("Expected value argument to be defined");}verifyNotReplaced(object,property);// store a function for restoring the defined property + push(fakeRestorers,getFakeRestorer(object,property));object[property]=value;return value;};sandbox.replaceGetter=function replaceGetter(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property)));}if(typeof replacement!=="function"){throw new TypeError("Expected replacement argument to be a function");}if(typeof descriptor.get!=="function"){throw new Error("`object.property` is not a getter");}verifyNotReplaced(object,property);// store a function for restoring the replaced property + push(fakeRestorers,getFakeRestorer(object,property));Object.defineProperty(object,property,{get:replacement,configurable:isPropertyConfigurable(object,property)});return replacement;};sandbox.replaceSetter=function replaceSetter(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property)));}if(typeof replacement!=="function"){throw new TypeError("Expected replacement argument to be a function");}if(typeof descriptor.set!=="function"){throw new Error("`object.property` is not a setter");}verifyNotReplaced(object,property);// store a function for restoring the replaced property + push(fakeRestorers,getFakeRestorer(object,property));// eslint-disable-next-line accessor-pairs + Object.defineProperty(object,property,{set:replacement,configurable:isPropertyConfigurable(object,property)});return replacement;};function commonPostInitSetup(args,spy){var _args2=_slicedToArray(args,3),object=_args2[0],property=_args2[1],types=_args2[2];var isSpyingOnEntireObject=typeof property==="undefined"&&_typeof$1(object)==="object";if(isSpyingOnEntireObject){var ownMethods=collectOwnMethods(spy);forEach(ownMethods,function(method){addToCollection(method);});usePromiseLibrary(promiseLib,ownMethods);}else if(Array.isArray(types)){var _iterator2=_createForOfIteratorHelper2(types),_step2;try{for(_iterator2.s();!(_step2=_iterator2.n()).done;){var accessorType=_step2.value;addToCollection(spy[accessorType]);usePromiseLibrary(promiseLib,spy[accessorType]);}}catch(err){_iterator2.e(err);}finally{_iterator2.f();}}else {addToCollection(spy);usePromiseLibrary(promiseLib,spy);}return spy;}sandbox.spy=function spy(){var createdSpy=sinonSpy.apply(sinonSpy,arguments);return commonPostInitSetup(arguments,createdSpy);};sandbox.stub=function stub(){var createdStub=sinonStub.apply(sinonStub,arguments);return commonPostInitSetup(arguments,createdStub);};// eslint-disable-next-line no-unused-vars + sandbox.fake=function fake(f){var s=sinonFake.apply(sinonFake,arguments);addToCollection(s);return s;};forEach(Object.keys(sinonFake),function(key){var fakeBehavior=sinonFake[key];if(typeof fakeBehavior==="function"){sandbox.fake[key]=function(){var s=fakeBehavior.apply(fakeBehavior,arguments);addToCollection(s);return s;};}});sandbox.useFakeTimers=function useFakeTimers(args){var clock=sinonClock.useFakeTimers.call(null,args);sandbox.clock=clock;addToCollection(clock);return clock;};sandbox.verify=function verify(){applyOnEach(collection,"verify");};sandbox.verifyAndRestore=function verifyAndRestore(){var exception;try{sandbox.verify();}catch(e){exception=e;}sandbox.restore();if(exception){throw exception;}};sandbox.useFakeServer=function useFakeServer(){var proto=sandbox.serverPrototype||fakeServer;if(!proto||!proto.create){return null;}sandbox.server=proto.create();addToCollection(sandbox.server);return sandbox.server;};sandbox.useFakeXMLHttpRequest=function useFakeXMLHttpRequest(){var xhr=fakeXhr.useFakeXMLHttpRequest();addToCollection(xhr);return xhr;};sandbox.usingPromise=function usingPromise(promiseLibrary){promiseLib=promiseLibrary;collection.promiseLibrary=promiseLibrary;return sandbox;};}Sandbox.prototype.match=match;module.exports=Sandbox;},{"./assert":2,"./collect-own-methods":4,"./create-stub-instance":7,"./fake":9,"./mock":11,"./spy":20,"./stub":21,"./util/core/get-property-descriptor":28,"./util/core/is-property-configurable":31,"./util/core/use-promise-library":36,"./util/fake-timers":40,"@sinonjs/commons":47,"@sinonjs/samsam":87,"nise":127}],19:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var color=require("./color");var match=require("@sinonjs/samsam").createMatcher;var timesInWords=require("./util/core/times-in-words");var inspect=require("util").inspect;var jsDiff=require("diff");var join=arrayProto.join;var map=arrayProto.map;var push=arrayProto.push;var slice=arrayProto.slice;function colorSinonMatchText(matcher,calledArg,calledArgMessage){var calledArgumentMessage=calledArgMessage;var matcherMessage=matcher.message;if(!matcher.test(calledArg)){matcherMessage=color.red(matcher.message);if(calledArgumentMessage){calledArgumentMessage=color.green(calledArgumentMessage);}}return "".concat(calledArgumentMessage," ").concat(matcherMessage);}function colorDiffText(diff){var objects=map(diff,function(part){var text=part.value;if(part.added){text=color.green(text);}else if(part.removed){text=color.red(text);}if(diff.length===2){text+=" ";// format simple diffs + }return text;});return join(objects,"");}function quoteStringValue(value){if(typeof value==="string"){return JSON.stringify(value);}return value;}module.exports={c:function c(spyInstance){return timesInWords(spyInstance.callCount);},n:function n(spyInstance){// eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return spyInstance.toString();},D:function D(spyInstance,args){var message="";for(var i=0,l=spyInstance.callCount;i1){message+="\nCall ".concat(i+1,":");}var calledArgs=spyInstance.getCall(i).args;var expectedArgs=slice(args);for(var j=0;j0?"\n".concat(join(calls,"\n")):"";},t:function t(spyInstance){var objects=[];for(var i=0,l=spyInstance.callCount;i2){throw new TypeError("stub(obj, 'meth', fn) has been removed, see documentation");}if(isEsModule(object)){throw new TypeError("ES Modules cannot be stubbed");}throwOnFalsyObject.apply(null,arguments);if(isNonExistentProperty(object,property)){throw new TypeError("Cannot stub non-existent property ".concat(valueToString(property)));}var actualDescriptor=getPropertyDescriptor(object,property);assertValidPropertyDescriptor(actualDescriptor,property);var isObjectOrFunction=_typeof$1(object)==="object"||typeof object==="function";var isStubbingEntireObject=typeof property==="undefined"&&isObjectOrFunction;var isCreatingNewStub=!object&&typeof property==="undefined";var isStubbingNonFuncProperty=isObjectOrFunction&&typeof property!=="undefined"&&(typeof actualDescriptor==="undefined"||typeof actualDescriptor.value!=="function");if(isStubbingEntireObject){return walkObject(stub,object);}if(isCreatingNewStub){return createStub();}var func=typeof actualDescriptor.value==="function"?actualDescriptor.value:null;var s=createStub(func);extend.nonEnum(s,{rootObj:object,propName:property,shadowsPropOnPrototype:!actualDescriptor.isOwn,restore:function restore(){if(actualDescriptor!==undefined&&actualDescriptor.isOwn){Object.defineProperty(object,property,actualDescriptor);return;}delete object[property];}});return isStubbingNonFuncProperty?s:wrapMethod(object,property,s);}function assertValidPropertyDescriptor(descriptor,property){if(!descriptor||!property){return;}if(descriptor.isOwn&&!descriptor.configurable&&!descriptor.writable){throw new TypeError("Descriptor for property ".concat(property," is non-configurable and non-writable"));}if((descriptor.get||descriptor.set)&&!descriptor.configurable){throw new TypeError("Descriptor for accessor property ".concat(property," is non-configurable"));}if(isDataDescriptor(descriptor)&&!descriptor.writable){throw new TypeError("Descriptor for data property ".concat(property," is non-writable"));}}function isDataDescriptor(descriptor){return !descriptor.value&&!descriptor.writable&&!descriptor.set&&!descriptor.get;}/*eslint-disable no-use-before-define*/function getParentBehaviour(stubInstance){return stubInstance.parent&&getCurrentBehavior(stubInstance.parent);}function getDefaultBehavior(stubInstance){return stubInstance.defaultBehavior||getParentBehaviour(stubInstance)||behavior.create(stubInstance);}function getCurrentBehavior(stubInstance){var currentBehavior=stubInstance.behaviors[stubInstance.callCount-1];return currentBehavior&¤tBehavior.isPresent()?currentBehavior:getDefaultBehavior(stubInstance);}/*eslint-enable no-use-before-define*/var proto={resetBehavior:function resetBehavior(){this.defaultBehavior=null;this.behaviors=[];delete this.returnValue;delete this.returnArgAt;delete this.throwArgAt;delete this.resolveArgAt;delete this.fakeFn;this.returnThis=false;this.resolveThis=false;forEach(this.fakes,function(fake){fake.resetBehavior();});},reset:function reset(){this.resetHistory();this.resetBehavior();},onCall:function onCall(index){if(!this.behaviors[index]){this.behaviors[index]=behavior.create(this);}return this.behaviors[index];},onFirstCall:function onFirstCall(){return this.onCall(0);},onSecondCall:function onSecondCall(){return this.onCall(1);},onThirdCall:function onThirdCall(){return this.onCall(2);},withArgs:function withArgs(){var fake=spy.withArgs.apply(this,arguments);if(this.defaultBehavior&&this.defaultBehavior.promiseLibrary){fake.defaultBehavior=fake.defaultBehavior||behavior.create(fake);fake.defaultBehavior.promiseLibrary=this.defaultBehavior.promiseLibrary;}return fake;}};forEach(Object.keys(behavior),function(method){if(hasOwnProperty(behavior,method)&&!hasOwnProperty(proto,method)&&method!=="create"&&method!=="invoke"){proto[method]=behavior.createBehavior(method);}});forEach(Object.keys(behaviors),function(method){if(hasOwnProperty(behaviors,method)&&!hasOwnProperty(proto,method)){behavior.addBehavior(stub,method,behaviors[method]);}});extend(stub,proto);module.exports=stub;},{"./behavior":3,"./default-behaviors":8,"./proxy":16,"./spy":20,"./throw-on-falsy-object":22,"./util/core/extend":25,"./util/core/get-property-descriptor":28,"./util/core/is-es-module":29,"./util/core/is-non-existent-property":30,"./util/core/sinon-type":34,"./util/core/walk-object":37,"./util/core/wrap-method":39,"@sinonjs/commons":47}],22:[function(require,module,exports){var valueToString=require("@sinonjs/commons").valueToString;function throwOnFalsyObject(object,property){if(property&&!object){var _type=object===null?"null":"undefined";throw new Error("Trying to stub property '".concat(valueToString(property),"' of ").concat(_type));}}module.exports=throwOnFalsyObject;},{"@sinonjs/commons":47}],23:[function(require,module,exports){module.exports={injectInto:null,properties:["spy","stub","mock","clock","server","requests","fake","define","replace","replaceSetter","replaceGetter","createStubInstance"],useFakeTimers:true,useFakeServer:true};},{}],24:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var reduce=arrayProto.reduce;module.exports=function exportAsyncBehaviors(behaviorMethods){return reduce(Object.keys(behaviorMethods),function(acc,method){// need to avoid creating another async versions of the newly added async methods + if(method.match(/^(callsArg|yields)/)&&!method.match(/Async/)){acc["".concat(method,"Async")]=function(){var result=behaviorMethods[method].apply(this,arguments);this.callbackAsync=true;return result;};}return acc;},{});};},{"@sinonjs/commons":47}],25:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var join=arrayProto.join;var push=arrayProto.push;// Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug + var hasDontEnumBug=function(){var obj={constructor:function constructor(){return "0";},toString:function toString(){return "1";},valueOf:function valueOf(){return "2";},toLocaleString:function toLocaleString(){return "3";},prototype:function prototype(){return "4";},isPrototypeOf:function isPrototypeOf(){return "5";},propertyIsEnumerable:function propertyIsEnumerable(){return "6";},hasOwnProperty:function hasOwnProperty(){return "7";},length:function length(){return "8";},unique:function unique(){return "9";}};var result=[];for(var prop in obj){if(hasOwnProperty(obj,prop)){push(result,obj[prop]());}}return join(result,"")!=="0123456789";}();/** + * + * @param target + * @param sources + * @param doCopy + * @returns {*} target + */function extendCommon(target,sources,doCopy){var source,i,prop;for(i=0;i1?_len-1:0),_key2=1;_key2<_len;_key2++){sources[_key2-1]=arguments[_key2];}return extendCommon(target,sources,function copyValue(dest,source,prop){var destOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(dest,prop);var sourceOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(source,prop);if(prop==="name"&&!destOwnPropertyDescriptor.writable){return;}var descriptors={configurable:sourceOwnPropertyDescriptor.configurable,enumerable:sourceOwnPropertyDescriptor.enumerable};/* + if the sorce has an Accessor property copy over the accessor functions (get and set) + data properties has writable attribute where as accessor property don't + REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties + */if(hasOwnProperty(sourceOwnPropertyDescriptor,"writable")){descriptors.writable=sourceOwnPropertyDescriptor.writable;descriptors.value=sourceOwnPropertyDescriptor.value;}else {if(sourceOwnPropertyDescriptor.get){descriptors.get=sourceOwnPropertyDescriptor.get.bind(dest);}if(sourceOwnPropertyDescriptor.set){descriptors.set=sourceOwnPropertyDescriptor.set.bind(dest);}}Object.defineProperty(dest,prop,descriptors);});};/** + * Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will + * override properties in previous sources. Define the properties as non enumerable. + * + * @param {object} target - The Object to extend + * @param {object[]} sources - Objects to copy properties from. + * @returns {object} the extended target + */module.exports.nonEnum=function extendNonEnum(target){for(var _len2=arguments.length,sources=new Array(_len2>1?_len2-1:0),_key3=1;_key3<_len2;_key3++){sources[_key3-1]=arguments[_key3];}return extendCommon(target,sources,function copyProperty(dest,source,prop){Object.defineProperty(dest,prop,{value:source[prop],enumerable:false,configurable:true,writable:true});});};},{"@sinonjs/commons":47}],26:[function(require,module,exports){module.exports=function toString(){var i,prop,thisValue;if(this.getCall&&this.callCount){i=this.callCount;while(i--){thisValue=this.getCall(i).thisValue;// eslint-disable-next-line guard-for-in + for(prop in thisValue){try{if(thisValue[prop]===this){return prop;}}catch(e){// no-op - accessing props can throw an error, nothing to do here + }}}}return this.displayName||"sinon fake";};},{}],27:[function(require,module,exports){/* istanbul ignore next : not testing that setTimeout works */function nextTick(callback){setTimeout(callback,0);}module.exports=function getNextTick(process,setImmediate){if(_typeof$1(process)==="object"&&typeof process.nextTick==="function"){return process.nextTick;}if(typeof setImmediate==="function"){return setImmediate;}return nextTick;};},{}],28:[function(require,module,exports){/* eslint-disable jsdoc/valid-types */ /* + * The following type def is strictly an illegal JSDoc, but the expression forms a + * legal Typescript union type and is understood by Visual Studio and the IntelliJ + * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these + * days for that reason (and the fact that JSDoc is essentially unmaintained) + */ /** + * @typedef {{isOwn: boolean} & PropertyDescriptor} SinonPropertyDescriptor + * a slightly enriched property descriptor + * @property {boolean} isOwn true if the descriptor is owned by this object, false if it comes from the prototype + */ /* eslint-enable jsdoc/valid-types */ /** + * Returns a slightly modified property descriptor that one can tell is from the object or the prototype + * + * @param {*} object + * @param {string} property + * @returns {SinonPropertyDescriptor} + */function getPropertyDescriptor(object,property){var proto=object;var descriptor;var isOwn=Boolean(object&&Object.getOwnPropertyDescriptor(object,property));while(proto&&!(descriptor=Object.getOwnPropertyDescriptor(proto,property))){proto=Object.getPrototypeOf(proto);}if(descriptor){descriptor.isOwn=isOwn;}return descriptor;}module.exports=getPropertyDescriptor;},{}],29:[function(require,module,exports){/** + * Verify if an object is a ECMAScript Module + * + * As the exports from a module is immutable we cannot alter the exports + * using spies or stubs. Let the consumer know this to avoid bug reports + * on weird error messages. + * + * @param {object} object The object to examine + * @returns {boolean} true when the object is a module + */module.exports=function(object){return object&&typeof Symbol!=="undefined"&&object[Symbol.toStringTag]==="Module"&&Object.isSealed(object);};},{}],30:[function(require,module,exports){/** + * @param {*} object + * @param {string} property + * @returns {boolean} whether a prop exists in the prototype chain + */function isNonExistentProperty(object,property){return Boolean(object&&typeof property!=="undefined"&&!(property in object));}module.exports=isNonExistentProperty;},{}],31:[function(require,module,exports){var getPropertyDescriptor=require("./get-property-descriptor");function isPropertyConfigurable(obj,propName){var propertyDescriptor=getPropertyDescriptor(obj,propName);return propertyDescriptor?propertyDescriptor.configurable:true;}module.exports=isPropertyConfigurable;},{"./get-property-descriptor":28}],32:[function(require,module,exports){function isRestorable(obj){return typeof obj==="function"&&typeof obj.restore==="function"&&obj.restore.sinon;}module.exports=isRestorable;},{}],33:[function(require,module,exports){var globalObject=require("@sinonjs/commons").global;var getNextTick=require("./get-next-tick");module.exports=getNextTick(globalObject.process,globalObject.setImmediate);},{"./get-next-tick":27,"@sinonjs/commons":47}],34:[function(require,module,exports){var sinonTypeSymbolProperty=Symbol("SinonType");module.exports={/** + * Set the type of a Sinon object to make it possible to identify it later at runtime + * + * @param {object|Function} object object/function to set the type on + * @param {string} type the named type of the object/function + */set:function set(object,type){Object.defineProperty(object,sinonTypeSymbolProperty,{value:type,configurable:false,enumerable:false});},get:function get(object){return object&&object[sinonTypeSymbolProperty];}};},{}],35:[function(require,module,exports){var array=[null,"once","twice","thrice"];module.exports=function timesInWords(count){return array[count]||"".concat(count||0," times");};},{}],36:[function(require,module,exports){var forEach=Array.prototype.forEach;function usePromiseLibrary(library,fakes){if(typeof library==="undefined"){return;}if(Array.isArray(fakes)){forEach.call(fakes,usePromiseLibrary.bind(null,library));return;}if(typeof fakes.usingPromise==="function"){fakes.usingPromise(library);}}module.exports=usePromiseLibrary;},{}],37:[function(require,module,exports){var functionName=require("@sinonjs/commons").functionName;var getPropertyDescriptor=require("./get-property-descriptor");var walk=require("./walk");/** + * A utility that allows traversing an object, applying mutating functions on the properties + * + * @param {Function} mutator called on each property + * @param {object} object the object we are walking over + * @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property + * @returns {void} nothing + */function walkObject(mutator,object,filter){var called=false;var name=functionName(mutator);if(!object){throw new Error("Trying to ".concat(name," object but received ").concat(String(object)));}walk(object,function(prop,propOwner){// we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object + // is not Object.prototype + if(propOwner!==Object.prototype&&prop!=="constructor"&&typeof getPropertyDescriptor(propOwner,prop).value==="function"){if(filter){if(filter(object,prop)){called=true;mutator(object,prop);}}else {called=true;mutator(object,prop);}}});if(!called){throw new Error("Found no methods on object to which we could apply mutations");}return object;}module.exports=walkObject;},{"./get-property-descriptor":28,"./walk":38,"@sinonjs/commons":47}],38:[function(require,module,exports){var forEach=require("@sinonjs/commons").prototypes.array.forEach;function walkInternal(obj,iterator,context,originalObj,seen){var prop;var proto=Object.getPrototypeOf(obj);if(typeof Object.getOwnPropertyNames!=="function"){// We explicitly want to enumerate through all of the prototype's properties + // in this case, therefore we deliberately leave out an own property check. + /* eslint-disable-next-line guard-for-in */for(prop in obj){iterator.call(context,obj[prop],prop,obj);}return;}forEach(Object.getOwnPropertyNames(obj),function(k){if(seen[k]!==true){seen[k]=true;var target=typeof Object.getOwnPropertyDescriptor(obj,k).get==="function"?originalObj:obj;iterator.call(context,k,target);}});if(proto){walkInternal(proto,iterator,context,originalObj,seen);}}/* Walks the prototype chain of an object and iterates over every own property + * name encountered. The iterator is called in the same fashion that Array.prototype.forEach + * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional + * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will + * default to using a simple for..in loop. + * + * obj - The object to walk the prototype chain for. + * iterator - The function to be called on each pass of the walk. + * context - (Optional) When given, the iterator will be called with this object as the receiver. + */module.exports=function walk(obj,iterator,context){return walkInternal(obj,iterator,context,obj,{});};},{"@sinonjs/commons":47}],39:[function(require,module,exports){// eslint-disable-next-line no-empty-function + var noop=function noop(){};var getPropertyDescriptor=require("./get-property-descriptor");var extend=require("./extend");var sinonType=require("./sinon-type");var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var valueToString=require("@sinonjs/commons").valueToString;var push=require("@sinonjs/commons").prototypes.array.push;function isFunction(obj){return typeof obj==="function"||Boolean(obj&&obj.constructor&&obj.call&&obj.apply);}function mirrorProperties(target,source){for(var prop in source){if(!hasOwnProperty(target,prop)){target[prop]=source[prop];}}}function getAccessor(object,property,method){var accessors=["get","set"];var descriptor=getPropertyDescriptor(object,property);for(var i=0;i1?arguments:spies;return every(_spies,checkAdjacentCalls.bind(null,callMap));}module.exports=calledInOrder;},{"./prototypes/array":49}],42:[function(require,module,exports){var functionName=require("./function-name");/** + * Returns a display name for a value from a constructor + * + * @param {object} value A value to examine + * @returns {(string|null)} A string or null + */function className(value){return value.constructor&&value.constructor.name||// The next branch is for IE11 support only: + // Because the name property is not set on the prototype + // of the Function object, we finally try to grab the + // name from its definition. This will never be reached + // in node, so we are not able to test this properly. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + typeof value.constructor==="function"&&/* istanbul ignore next */functionName(value.constructor)||null;}module.exports=className;},{"./function-name":45}],43:[function(require,module,exports){/** + * Returns a function that will invoke the supplied function and print a + * deprecation warning to the console each time it is called. + * + * @param {Function} func + * @param {string} msg + * @returns {Function} + */exports.wrap=function(func,msg){var wrapped=function wrapped(){exports.printWarning(msg);return func.apply(this,arguments);};if(func.prototype){wrapped.prototype=func.prototype;}return wrapped;};/** + * Returns a string which can be supplied to `wrap()` to notify the user that a + * particular part of the sinon API has been deprecated. + * + * @param {string} packageName + * @param {string} funcName + * @returns {string} + */exports.defaultMsg=function(packageName,funcName){return "".concat(packageName,".").concat(funcName," is deprecated and will be removed from the public API in a future version of ").concat(packageName,".");};/** + * Prints a warning on the console, when it exists + * + * @param {string} msg + * @returns {undefined} + */exports.printWarning=function(msg){/* istanbul ignore next */if((typeof process==="undefined"?"undefined":_typeof$1(process))==="object"&&process.emitWarning){// Emit Warnings in Node + process.emitWarning(msg);}else if(console.info){console.info(msg);}else {console.log(msg);}};},{}],44:[function(require,module,exports){/** + * Returns true when fn returns true for all members of obj. + * This is an every implementation that works for all iterables + * + * @param {object} obj + * @param {Function} fn + * @returns {boolean} + */module.exports=function every(obj,fn){var pass=true;try{// eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + obj.forEach(function(){if(!fn.apply(this,arguments)){// Throwing an error is the only way to break `forEach` + throw new Error();}});}catch(e){pass=false;}return pass;};},{}],45:[function(require,module,exports){/** + * Returns a display name for a function + * + * @param {Function} func + * @returns {string} + */module.exports=function functionName(func){if(!func){return "";}try{return func.displayName||func.name||// Use function decomposition as a last resort to get function + // name. Does not rely on function decomposition to work - if it + // doesn't debugging will be slightly less informative + // (i.e. toString will say 'spy' rather than 'myFunc'). + (String(func).match(/function ([^\s(]+)/)||[])[1];}catch(e){// Stringify may fail and we might get an exception, as a last-last + // resort fall back to empty string. + return "";}};},{}],46:[function(require,module,exports){/** + * A reference to the global object + * + * @type {object} globalObject + */var globalObject;/* istanbul ignore else */if(typeof commonjsGlobal$1!=="undefined"){// Node + globalObject=commonjsGlobal$1;}else if(typeof window!=="undefined"){// Browser + globalObject=window;}else {// WebWorker + globalObject=self;}module.exports=globalObject;},{}],47:[function(require,module,exports){module.exports={global:require("./global"),calledInOrder:require("./called-in-order"),className:require("./class-name"),deprecated:require("./deprecated"),every:require("./every"),functionName:require("./function-name"),orderByFirstCall:require("./order-by-first-call"),prototypes:require("./prototypes"),typeOf:require("./type-of"),valueToString:require("./value-to-string")};},{"./called-in-order":41,"./class-name":42,"./deprecated":43,"./every":44,"./function-name":45,"./global":46,"./order-by-first-call":48,"./prototypes":52,"./type-of":58,"./value-to-string":59}],48:[function(require,module,exports){var sort=require("./prototypes/array").sort;var slice=require("./prototypes/array").slice;/** + * @private + */function comparator(a,b){// uuid, won't ever be equal + var aCall=a.getCall(0);var bCall=b.getCall(0);var aId=aCall&&aCall.callId||-1;var bId=bCall&&bCall.callId||-1;return aId} tickAsync + * @property {function(): number} next + * @property {function(): Promise} nextAsync + * @property {function(): number} runAll + * @property {function(): number} runToFrame + * @property {function(): Promise} runAllAsync + * @property {function(): number} runToLast + * @property {function(): Promise} runToLastAsync + * @property {function(): void} reset + * @property {function(number | Date): void} setSystemTime + * @property {function(number): void} jump + * @property {Performance} performance + * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) + * @property {function(): void} uninstall Uninstall the clock. + * @property {Function[]} methods - the methods that are faked + * @property {boolean} [shouldClearNativeTimers] inherited from config + */ /* eslint-enable jsdoc/require-property-description */ /** + * Configuration object for the `install` method. + * + * @typedef {object} Config + * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) + * @property {string[]} [toFake] names of the methods that should be faked. + * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() + * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) + * @property {number} [advanceTimeDelta] increment mocked time every <> ms (default: 20ms) + * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) + */ /* eslint-disable jsdoc/require-property-description */ /** + * The internal structure to describe a scheduled fake timer + * + * @typedef {object} Timer + * @property {Function} func + * @property {*[]} args + * @property {number} delay + * @property {number} callAt + * @property {number} createdAt + * @property {boolean} immediate + * @property {number} id + * @property {Error} [error] + */ /** + * A Node timer + * + * @typedef {object} NodeImmediate + * @property {function(): boolean} hasRef + * @property {function(): NodeImmediate} ref + * @property {function(): NodeImmediate} unref + */ /* eslint-enable jsdoc/require-property-description */ /* eslint-disable complexity */ /** + * Mocks available features in the specified global namespace. + * + * @param {*} _global Namespace to mock (e.g. `window`) + * @returns {FakeTimers} + */function withGlobal(_global){var userAgent=_global.navigator&&_global.navigator.userAgent;var isRunningInIE=userAgent&&userAgent.indexOf("MSIE ")>-1;var maxTimeout=Math.pow(2,31)-1;//see https://heycam.github.io/webidl/#abstract-opdef-converttoint + var idCounterStart=1e12;// arbitrarily large number to avoid collisions with native timer IDs + var NOOP=function NOOP(){return undefined;};var NOOP_ARRAY=function NOOP_ARRAY(){return [];};var timeoutResult=_global.setTimeout(NOOP,0);var addTimerReturnsObject=_typeof$1(timeoutResult)==="object";var hrtimePresent=_global.process&&typeof _global.process.hrtime==="function";var hrtimeBigintPresent=hrtimePresent&&typeof _global.process.hrtime.bigint==="function";var nextTickPresent=_global.process&&typeof _global.process.nextTick==="function";var utilPromisify=_global.process&&require("util").promisify;var performancePresent=_global.performance&&typeof _global.performance.now==="function";var hasPerformancePrototype=_global.Performance&&_typeof$1(_global.Performance).match(/^(function|object)$/);var hasPerformanceConstructorPrototype=_global.performance&&_global.performance.constructor&&_global.performance.constructor.prototype;var queueMicrotaskPresent=_global.hasOwnProperty("queueMicrotask");var requestAnimationFramePresent=_global.requestAnimationFrame&&typeof _global.requestAnimationFrame==="function";var cancelAnimationFramePresent=_global.cancelAnimationFrame&&typeof _global.cancelAnimationFrame==="function";var requestIdleCallbackPresent=_global.requestIdleCallback&&typeof _global.requestIdleCallback==="function";var cancelIdleCallbackPresent=_global.cancelIdleCallback&&typeof _global.cancelIdleCallback==="function";var setImmediatePresent=_global.setImmediate&&typeof _global.setImmediate==="function";// Make properties writable in IE, as per + // https://www.adequatelygood.com/Replacing-setTimeout-Globally.html + /* eslint-disable no-self-assign */if(isRunningInIE){_global.setTimeout=_global.setTimeout;_global.clearTimeout=_global.clearTimeout;_global.setInterval=_global.setInterval;_global.clearInterval=_global.clearInterval;_global.Date=_global.Date;}// setImmediate is not a standard function + // avoid adding the prop to the window object if not present + if(setImmediatePresent){_global.setImmediate=_global.setImmediate;_global.clearImmediate=_global.clearImmediate;}/* eslint-enable no-self-assign */_global.clearTimeout(timeoutResult);var NativeDate=_global.Date;var uniqueTimerId=idCounterStart;/** + * @param {number} num + * @returns {boolean} + */function isNumberFinite(num){if(Number.isFinite){return Number.isFinite(num);}return isFinite(num);}var isNearInfiniteLimit=false;/** + * @param {Clock} clock + * @param {number} i + */function checkIsNearInfiniteLimit(clock,i){if(clock.loopLimit&&i===clock.loopLimit-1){isNearInfiniteLimit=true;}}/** + * + */function resetIsNearInfiniteLimit(){isNearInfiniteLimit=false;}/** + * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into + * number of milliseconds. This is used to support human-readable strings passed + * to clock.tick() + * + * @param {string} str + * @returns {number} + */function parseTime(str){if(!str){return 0;}var strings=str.split(":");var l=strings.length;var i=l;var ms=0;var parsed;if(l>3||!/^(\d\d:){0,2}\d\d?$/.test(str)){throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");}while(i--){parsed=parseInt(strings[i],10);if(parsed>=60){throw new Error("Invalid time ".concat(str));}ms+=parsed*Math.pow(60,l-i-1);}return ms*1000;}/** + * Get the decimal part of the millisecond value as nanoseconds + * + * @param {number} msFloat the number of milliseconds + * @returns {number} an integer number of nanoseconds in the range [0,1e6) + * + * Example: nanoRemainer(123.456789) -> 456789 + */function nanoRemainder(msFloat){var modulo=1e6;var remainder=msFloat*1e6%modulo;var positiveRemainder=remainder<0?remainder+modulo:remainder;return Math.floor(positiveRemainder);}/** + * Used to grok the `now` parameter to createClock. + * + * @param {Date|number} epoch the system time + * @returns {number} + */function getEpoch(epoch){if(!epoch){return 0;}if(typeof epoch.getTime==="function"){return epoch.getTime();}if(typeof epoch==="number"){return epoch;}throw new TypeError("now should be milliseconds since UNIX epoch");}/** + * @param {number} from + * @param {number} to + * @param {Timer} timer + * @returns {boolean} + */function inRange(from,to,timer){return timer&&timer.callAt>=from&&timer.callAt<=to;}/** + * @param {Clock} clock + * @param {Timer} job + */function getInfiniteLoopError(clock,job){var infiniteLoopError=new Error("Aborting after running ".concat(clock.loopLimit," timers, assuming an infinite loop!"));if(!job.error){return infiniteLoopError;}// pattern never matched in Node + var computedTargetPattern=/target\.*[<|(|[].*?[>|\]|)]\s*/;var clockMethodPattern=new RegExp(String(Object.keys(clock).join("|")));if(addTimerReturnsObject){// node.js environment + clockMethodPattern=new RegExp("\\s+at (Object\\.)?(?:".concat(Object.keys(clock).join("|"),")\\s+"));}var matchedLineIndex=-1;job.error.stack.split("\n").some(function(line,i){// If we've matched a computed target line (e.g. setTimeout) then we + // don't need to look any further. Return true to stop iterating. + var matchedComputedTarget=line.match(computedTargetPattern);/* istanbul ignore if */if(matchedComputedTarget){matchedLineIndex=i;return true;}// If we've matched a clock method line, then there may still be + // others further down the trace. Return false to keep iterating. + var matchedClockMethod=line.match(clockMethodPattern);if(matchedClockMethod){matchedLineIndex=i;return false;}// If we haven't matched anything on this line, but we matched + // previously and set the matched line index, then we can stop. + // If we haven't matched previously, then we should keep iterating. + return matchedLineIndex>=0;});var stack="".concat(infiniteLoopError,"\n").concat(job.type||"Microtask"," - ").concat(job.func.name||"anonymous","\n").concat(job.error.stack.split("\n").slice(matchedLineIndex+1).join("\n"));try{Object.defineProperty(infiniteLoopError,"stack",{value:stack});}catch(e){// noop + }return infiniteLoopError;}/** + * @param {Date} target + * @param {Date} source + * @returns {Date} the target after modifications + */function mirrorDateProperties(target,source){var prop;for(prop in source){if(source.hasOwnProperty(prop)){target[prop]=source[prop];}}// set special now implementation + if(source.now){target.now=function now(){return target.clock.now;};}else {delete target.now;}// set special toSource implementation + if(source.toSource){target.toSource=function toSource(){return source.toSource();};}else {delete target.toSource;}// set special toString implementation + target.toString=function toString(){return source.toString();};target.prototype=source.prototype;target.parse=source.parse;target.UTC=source.UTC;target.prototype.toUTCString=source.prototype.toUTCString;target.isFake=true;return target;}//eslint-disable-next-line jsdoc/require-jsdoc + function createDate(){/** + * @param {number} year + * @param {number} month + * @param {number} date + * @param {number} hour + * @param {number} minute + * @param {number} second + * @param {number} ms + * @returns {Date} + */function ClockDate(year,month,date,hour,minute,second,ms){// the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2. + // This remains so in the 10th edition of 2019 as well. + if(!(this instanceof ClockDate)){return new NativeDate(ClockDate.clock.now).toString();}// if Date is called as a constructor with 'new' keyword + // Defensive and verbose to avoid potential harm in passing + // explicit undefined when user does not pass argument + switch(arguments.length){case 0:return new NativeDate(ClockDate.clock.now);case 1:return new NativeDate(year);case 2:return new NativeDate(year,month);case 3:return new NativeDate(year,month,date);case 4:return new NativeDate(year,month,date,hour);case 5:return new NativeDate(year,month,date,hour,minute);case 6:return new NativeDate(year,month,date,hour,minute,second);default:return new NativeDate(year,month,date,hour,minute,second,ms);}}return mirrorDateProperties(ClockDate,NativeDate);}//eslint-disable-next-line jsdoc/require-jsdoc + function enqueueJob(clock,job){// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob + if(!clock.jobs){clock.jobs=[];}clock.jobs.push(job);}//eslint-disable-next-line jsdoc/require-jsdoc + function runJobs(clock){// runs all microtick-deferred tasks - ecma262/#sec-runjobs + if(!clock.jobs){return;}for(var i=0;iclock.loopLimit){throw getInfiniteLoopError(clock,job);}}resetIsNearInfiniteLimit();clock.jobs=[];}/** + * @param {Clock} clock + * @param {Timer} timer + * @returns {number} id of the created timer + */function addTimer(clock,timer){if(timer.func===undefined){throw new Error("Callback must be provided to timer calls");}if(addTimerReturnsObject){// Node.js environment + if(typeof timer.func!=="function"){throw new TypeError("[ERR_INVALID_CALLBACK]: Callback must be a function. Received ".concat(timer.func," of type ").concat(_typeof$1(timer.func)));}}if(isNearInfiniteLimit){timer.error=new Error();}timer.type=timer.immediate?"Immediate":"Timeout";if(timer.hasOwnProperty("delay")){if(typeof timer.delay!=="number"){timer.delay=parseInt(timer.delay,10);}if(!isNumberFinite(timer.delay)){timer.delay=0;}timer.delay=timer.delay>maxTimeout?1:timer.delay;timer.delay=Math.max(0,timer.delay);}if(timer.hasOwnProperty("interval")){timer.type="Interval";timer.interval=timer.interval>maxTimeout?1:timer.interval;}if(timer.hasOwnProperty("animation")){timer.type="AnimationFrame";timer.animation=true;}if(timer.hasOwnProperty("idleCallback")){timer.type="IdleCallback";timer.idleCallback=true;}if(!clock.timers){clock.timers={};}timer.id=uniqueTimerId++;timer.createdAt=clock.now;timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));clock.timers[timer.id]=timer;if(addTimerReturnsObject){var res=_defineProperty({refed:true,ref:function ref(){this.refed=true;return res;},unref:function unref(){this.refed=false;return res;},hasRef:function hasRef(){return this.refed;},refresh:function refresh(){timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));// it _might_ have been removed, but if not the assignment is perfectly fine + clock.timers[timer.id]=timer;return res;}},Symbol.toPrimitive,function(){return timer.id;});return res;}return timer.id;}/* eslint consistent-return: "off" */ /** + * Timer comparitor + * + * @param {Timer} a + * @param {Timer} b + * @returns {number} + */function compareTimers(a,b){// Sort first by absolute timing + if(a.callAtb.callAt){return 1;}// Sort next by immediate, immediate timers take precedence + if(a.immediate&&!b.immediate){return -1;}if(!a.immediate&&b.immediate){return 1;}// Sort next by creation time, earlier-created timers take precedence + if(a.createdAtb.createdAt){return 1;}// Sort next by id, lower-id timers take precedence + if(a.idb.id){return 1;}// As timer ids are unique, no fallback `0` is necessary + }/** + * @param {Clock} clock + * @param {number} from + * @param {number} to + * @returns {Timer} + */function firstTimerInRange(clock,from,to){var timers=clock.timers;var timer=null;var id,isInRange;for(id in timers){if(timers.hasOwnProperty(id)){isInRange=inRange(from,to,timers[id]);if(isInRange&&(!timer||compareTimers(timer,timers[id])===1)){timer=timers[id];}}}return timer;}/** + * @param {Clock} clock + * @returns {Timer} + */function firstTimer(clock){var timers=clock.timers;var timer=null;var id;for(id in timers){if(timers.hasOwnProperty(id)){if(!timer||compareTimers(timer,timers[id])===1){timer=timers[id];}}}return timer;}/** + * @param {Clock} clock + * @returns {Timer} + */function lastTimer(clock){var timers=clock.timers;var timer=null;var id;for(id in timers){if(timers.hasOwnProperty(id)){if(!timer||compareTimers(timer,timers[id])===-1){timer=timers[id];}}}return timer;}/** + * @param {Clock} clock + * @param {Timer} timer + */function callTimer(clock,timer){if(typeof timer.interval==="number"){clock.timers[timer.id].callAt+=timer.interval;}else {delete clock.timers[timer.id];}if(typeof timer.func==="function"){timer.func.apply(null,timer.args);}else {/* eslint no-eval: "off" */var eval2=eval;(function(){eval2(timer.func);})();}}/** + * Gets clear handler name for a given timer type + * + * @param {string} ttype + */function getClearHandler(ttype){if(ttype==="IdleCallback"||ttype==="AnimationFrame"){return "cancel".concat(ttype);}return "clear".concat(ttype);}/** + * Gets schedule handler name for a given timer type + * + * @param {string} ttype + */function getScheduleHandler(ttype){if(ttype==="IdleCallback"||ttype==="AnimationFrame"){return "request".concat(ttype);}return "set".concat(ttype);}/** + * Creates an anonymous function to warn only once + */function createWarnOnce(){var calls=0;return function(msg){// eslint-disable-next-line + !calls++&&console.warn(msg);};}var warnOnce=createWarnOnce();/** + * @param {Clock} clock + * @param {number} timerId + * @param {string} ttype + */function clearTimer(clock,timerId,ttype){if(!timerId){// null appears to be allowed in most browsers, and appears to be + // relied upon by some libraries, like Bootstrap carousel + return;}if(!clock.timers){clock.timers={};}// in Node, the ID is stored as the primitive value for `Timeout` objects + // for `Immediate` objects, no ID exists, so it gets coerced to NaN + var id=Number(timerId);if(Number.isNaN(id)||id1e9){throw new TypeError("Number of nanoseconds can't exceed a billion");}var oldSecs=prev[0];var nanoDiff=remainderInNanos-prev[1];var secDiff=secsSinceStart-oldSecs;if(nanoDiff<0){nanoDiff+=1e9;secDiff-=1;}return [secDiff,nanoDiff];}return [secsSinceStart,remainderInNanos];}function fakePerformanceNow(){var hrt=hrtime();var millis=hrt[0]*1000+hrt[1]/1e6;return millis;}if(hrtimeBigintPresent){hrtime.bigint=function(){var parts=hrtime();return BigInt(parts[0])*BigInt(1e9)+BigInt(parts[1]);// eslint-disable-line + };}clock.requestIdleCallback=function requestIdleCallback(func,timeout){var timeToNextIdlePeriod=0;if(clock.countTimers()>0){timeToNextIdlePeriod=50;// const for now + }var result=addTimer(clock,{func:func,args:Array.prototype.slice.call(arguments,2),delay:typeof timeout==="undefined"?timeToNextIdlePeriod:Math.min(timeout,timeToNextIdlePeriod),idleCallback:true});return Number(result);};clock.cancelIdleCallback=function cancelIdleCallback(timerId){return clearTimer(clock,timerId,"IdleCallback");};clock.setTimeout=function setTimeout(func,timeout){return addTimer(clock,{func:func,args:Array.prototype.slice.call(arguments,2),delay:timeout});};if(typeof _global.Promise!=="undefined"&&utilPromisify){clock.setTimeout[utilPromisify.custom]=function promisifiedSetTimeout(timeout,arg){return new _global.Promise(function setTimeoutExecutor(resolve){addTimer(clock,{func:resolve,args:[arg],delay:timeout});});};}clock.clearTimeout=function clearTimeout(timerId){return clearTimer(clock,timerId,"Timeout");};clock.nextTick=function nextTick(func){return enqueueJob(clock,{func:func,args:Array.prototype.slice.call(arguments,1),error:isNearInfiniteLimit?new Error():null});};clock.queueMicrotask=function queueMicrotask(func){return clock.nextTick(func);// explicitly drop additional arguments + };clock.setInterval=function setInterval(func,timeout){// eslint-disable-next-line no-param-reassign + timeout=parseInt(timeout,10);return addTimer(clock,{func:func,args:Array.prototype.slice.call(arguments,2),delay:timeout,interval:timeout});};clock.clearInterval=function clearInterval(timerId){return clearTimer(clock,timerId,"Interval");};if(setImmediatePresent){clock.setImmediate=function setImmediate(func){return addTimer(clock,{func:func,args:Array.prototype.slice.call(arguments,1),immediate:true});};if(typeof _global.Promise!=="undefined"&&utilPromisify){clock.setImmediate[utilPromisify.custom]=function promisifiedSetImmediate(arg){return new _global.Promise(function setImmediateExecutor(resolve){addTimer(clock,{func:resolve,args:[arg],immediate:true});});};}clock.clearImmediate=function clearImmediate(timerId){return clearTimer(clock,timerId,"Immediate");};}clock.countTimers=function countTimers(){return Object.keys(clock.timers||{}).length+(clock.jobs||[]).length;};clock.requestAnimationFrame=function requestAnimationFrame(func){var result=addTimer(clock,{func:func,delay:getTimeToNextFrame(),get args(){return [fakePerformanceNow()];},animation:true});return Number(result);};clock.cancelAnimationFrame=function cancelAnimationFrame(timerId){return clearTimer(clock,timerId,"AnimationFrame");};clock.runMicrotasks=function runMicrotasks(){runJobs(clock);};/** + * @param {number|string} tickValue milliseconds or a string parseable by parseTime + * @param {boolean} isAsync + * @param {Function} resolve + * @param {Function} reject + * @returns {number|undefined} will return the new `now` value or nothing for async + */function doTick(tickValue,isAsync,resolve,reject){var msFloat=typeof tickValue==="number"?tickValue:parseTime(tickValue);var ms=Math.floor(msFloat);var remainder=nanoRemainder(msFloat);var nanosTotal=nanos+remainder;var tickTo=clock.now+ms;if(msFloat<0){throw new TypeError("Negative ticks are not supported");}// adjust for positive overflow + if(nanosTotal>=1e6){tickTo+=1;nanosTotal-=1e6;}nanos=nanosTotal;var tickFrom=clock.now;var previous=clock.now;// ESLint fails to detect this correctly + /* eslint-disable prefer-const */var timer,firstException,oldNow,nextPromiseTick,compensationCheck,postTimerCall;/* eslint-enable prefer-const */clock.duringTick=true;// perform microtasks + oldNow=clock.now;runJobs(clock);if(oldNow!==clock.now){// compensate for any setSystemTime() call during microtask callback + tickFrom+=clock.now-oldNow;tickTo+=clock.now-oldNow;}//eslint-disable-next-line jsdoc/require-jsdoc + function doTickInner(){// perform each timer in the requested range + timer=firstTimerInRange(clock,tickFrom,tickTo);// eslint-disable-next-line no-unmodified-loop-condition + while(timer&&tickFrom<=tickTo){if(clock.timers[timer.id]){tickFrom=timer.callAt;clock.now=timer.callAt;oldNow=clock.now;try{runJobs(clock);callTimer(clock,timer);}catch(e){firstException=firstException||e;}if(isAsync){// finish up after native setImmediate callback to allow + // all native es6 promises to process their callbacks after + // each timer fires. + originalSetTimeout(nextPromiseTick);return;}compensationCheck();}postTimerCall();}// perform process.nextTick()s again + oldNow=clock.now;runJobs(clock);if(oldNow!==clock.now){// compensate for any setSystemTime() call during process.nextTick() callback + tickFrom+=clock.now-oldNow;tickTo+=clock.now-oldNow;}clock.duringTick=false;// corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo] + timer=firstTimerInRange(clock,tickFrom,tickTo);if(timer){try{clock.tick(tickTo-clock.now);// do it all again - for the remainder of the requested range + }catch(e){firstException=firstException||e;}}else {// no timers remaining in the requested range: move the clock all the way to the end + clock.now=tickTo;// update nanos + nanos=nanosTotal;}if(firstException){throw firstException;}if(isAsync){resolve(clock.now);}else {return clock.now;}}nextPromiseTick=isAsync&&function(){try{compensationCheck();postTimerCall();doTickInner();}catch(e){reject(e);}};compensationCheck=function compensationCheck(){// compensate for any setSystemTime() call during timer callback + if(oldNow!==clock.now){tickFrom+=clock.now-oldNow;tickTo+=clock.now-oldNow;previous+=clock.now-oldNow;}};postTimerCall=function postTimerCall(){timer=firstTimerInRange(clock,previous,tickTo);previous=tickFrom;};return doTickInner();}/** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {number} will return the new `now` value + */clock.tick=function tick(tickValue){return doTick(tickValue,false);};if(typeof _global.Promise!=="undefined"){/** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {Promise} + */clock.tickAsync=function tickAsync(tickValue){return new _global.Promise(function(resolve,reject){originalSetTimeout(function(){try{doTick(tickValue,true,resolve,reject);}catch(e){reject(e);}});});};}clock.next=function next(){runJobs(clock);var timer=firstTimer(clock);if(!timer){return clock.now;}clock.duringTick=true;try{clock.now=timer.callAt;callTimer(clock,timer);runJobs(clock);return clock.now;}finally{clock.duringTick=false;}};if(typeof _global.Promise!=="undefined"){clock.nextAsync=function nextAsync(){return new _global.Promise(function(resolve,reject){originalSetTimeout(function(){try{var timer=firstTimer(clock);if(!timer){resolve(clock.now);return;}var err;clock.duringTick=true;clock.now=timer.callAt;try{callTimer(clock,timer);}catch(e){err=e;}clock.duringTick=false;originalSetTimeout(function(){if(err){reject(err);}else {resolve(clock.now);}});}catch(e){reject(e);}});});};}clock.runAll=function runAll(){var numTimers,i;runJobs(clock);for(i=0;itimer.callAt){timer.callAt=clock.now+ms;}}clock.tick(ms);};if(performancePresent){clock.performance=Object.create(null);clock.performance.now=fakePerformanceNow;}if(hrtimePresent){clock.hrtime=hrtime;}return clock;}/* eslint-disable complexity */ /** + * @param {Config=} [config] Optional config + * @returns {Clock} + */function install(config){if(arguments.length>1||config instanceof Date||Array.isArray(config)||typeof config==="number"){throw new TypeError("FakeTimers.install called with ".concat(String(config)," install requires an object parameter"));}if(_global.Date.isFake===true){// Timers are already faked; this is a problem. + // Make the user reset timers before continuing. + throw new TypeError("Can't install fake timers twice on the same global object.");}// eslint-disable-next-line no-param-reassign + config=typeof config!=="undefined"?config:{};config.shouldAdvanceTime=config.shouldAdvanceTime||false;config.advanceTimeDelta=config.advanceTimeDelta||20;config.shouldClearNativeTimers=config.shouldClearNativeTimers||false;if(config.target){throw new TypeError("config.target is no longer supported. Use `withGlobal(target)` instead.");}var i,l;var clock=createClock(config.now,config.loopLimit);clock.shouldClearNativeTimers=config.shouldClearNativeTimers;clock.uninstall=function(){return uninstall(clock,config);};clock.methods=config.toFake||[];if(clock.methods.length===0){// do not fake nextTick by default - GitHub#126 + clock.methods=Object.keys(timers).filter(function(key){return key!=="nextTick"&&key!=="queueMicrotask";});}if(config.shouldAdvanceTime===true){var intervalTick=doIntervalTick.bind(null,clock,config.advanceTimeDelta);var intervalId=_global.setInterval(intervalTick,config.advanceTimeDelta);clock.attachedInterval=intervalId;}if(clock.methods.includes("performance")){var proto=function(){if(hasPerformancePrototype){return _global.Performance.prototype;}if(hasPerformanceConstructorPrototype){return _global.performance.constructor.prototype;}}();if(proto){Object.getOwnPropertyNames(proto).forEach(function(name){if(name!=="now"){clock.performance[name]=name.indexOf("getEntries")===0?NOOP_ARRAY:NOOP;}});}else if((config.toFake||[]).includes("performance")){// user explicitly tried to fake performance when not present + throw new ReferenceError("non-existent performance object cannot be faked");}}for(i=0,l=clock.methods.length;i2){throw new TypeError("Expected 1 or 2 arguments, received ".concat(arguments.length));}if(type in TYPE_MAP){TYPE_MAP[type](m,expectation,message);}else {m.test=function(actual){return deepEqual(actual,expectation);};}if(!m.message){m.message="match(".concat(valueToString(expectation),")");}// ensure that nothing mutates the exported message value, ref https://github.com/sinonjs/sinon/issues/2502 + Object.defineProperty(m,"message",{configurable:false,writable:false,value:m.message});return m;}createMatcher.isMatcher=isMatcher;createMatcher.any=createMatcher(function(){return true;},"any");createMatcher.defined=createMatcher(function(actual){return actual!==null&&actual!==undefined;},"defined");createMatcher.truthy=createMatcher(function(actual){return Boolean(actual);},"truthy");createMatcher.falsy=createMatcher(function(actual){return !actual;},"falsy");createMatcher.same=function(expectation){return createMatcher(function(actual){return expectation===actual;},"same(".concat(valueToString(expectation),")"));};createMatcher["in"]=function(arrayOfExpectations){if(typeOf(arrayOfExpectations)!=="array"){throw new TypeError("array expected");}return createMatcher(function(actual){return some(arrayOfExpectations,function(expectation){return expectation===actual;});},"in(".concat(valueToString(arrayOfExpectations),")"));};createMatcher.typeOf=function(type){assertType(type,"string","type");return createMatcher(function(actual){return typeOf(actual)===type;},"typeOf(\"".concat(type,"\")"));};createMatcher.instanceOf=function(type){/* istanbul ignore if */if(typeof Symbol==="undefined"||typeof Symbol.hasInstance==="undefined"){assertType(type,"function","type");}else {assertMethodExists(type,Symbol.hasInstance,"type","[Symbol.hasInstance]");}return createMatcher(function(actual){return actual instanceof type;},"instanceOf(".concat(functionName(type)||objectToString(type),")"));};/** + * Creates a property matcher + * + * @private + * @param {Function} propertyTest A function to test the property against a value + * @param {string} messagePrefix A prefix to use for messages generated by the matcher + * @returns {object} A matcher + */function createPropertyMatcher(propertyTest,messagePrefix){return function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="".concat(messagePrefix,"(\"").concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||!propertyTest(actual,property)){return false;}return onlyProperty||deepEqual(actual[property],value);},message);};}createMatcher.has=createPropertyMatcher(function(actual,property){if(_typeof$1(actual)==="object"){return property in actual;}return actual[property]!==undefined;},"has");createMatcher.hasOwn=createPropertyMatcher(function(actual,property){return hasOwnProperty(actual,property);},"hasOwn");createMatcher.hasNested=function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="hasNested(\"".concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||get(actual,property)===undefined){return false;}return onlyProperty||deepEqual(get(actual,property),value);},message);};var jsonParseResultTypes={"null":true,"boolean":true,number:true,string:true,object:true,array:true};createMatcher.json=function(value){if(!jsonParseResultTypes[typeOf(value)]){throw new TypeError("Value cannot be the result of JSON.parse");}var message="json(".concat(JSON.stringify(value,null," "),")");return createMatcher(function(actual){var parsed;try{parsed=JSON.parse(actual);}catch(e){return false;}return deepEqual(parsed,value);},message);};createMatcher.every=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return every(Object.keys(actual),function(key){return predicate.test(actual[key]);});}return isIterable(actual)&&every(actual,function(element){return predicate.test(element);});},"every(".concat(predicate.message,")"));};createMatcher.some=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return !every(Object.keys(actual),function(key){return !predicate.test(actual[key]);});}return isIterable(actual)&&!every(actual,function(element){return !predicate.test(element);});},"some(".concat(predicate.message,")"));};createMatcher.array=createMatcher.typeOf("array");createMatcher.array.deepEquals=function(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength=actual.length===expectation.length;return typeOf(actual)==="array"&&sameLength&&every(actual,function(element,index){var expected=expectation[index];return typeOf(expected)==="array"&&typeOf(element)==="array"?createMatcher.array.deepEquals(expected).test(element):deepEqual(expected,element);});},"deepEquals([".concat(iterableToString(expectation),"])"));};createMatcher.array.startsWith=function(expectation){return createMatcher(function(actual){return typeOf(actual)==="array"&&every(expectation,function(expectedElement,index){return actual[index]===expectedElement;});},"startsWith([".concat(iterableToString(expectation),"])"));};createMatcher.array.endsWith=function(expectation){return createMatcher(function(actual){// This indicates the index in which we should start matching + var offset=actual.length-expectation.length;return typeOf(actual)==="array"&&every(expectation,function(expectedElement,index){return actual[offset+index]===expectedElement;});},"endsWith([".concat(iterableToString(expectation),"])"));};createMatcher.array.contains=function(expectation){return createMatcher(function(actual){return typeOf(actual)==="array"&&every(expectation,function(expectedElement){return arrayIndexOf(actual,expectedElement)!==-1;});},"contains([".concat(iterableToString(expectation),"])"));};createMatcher.map=createMatcher.typeOf("map");createMatcher.map.deepEquals=function mapDeepEquals(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength=actual.size===expectation.size;return typeOf(actual)==="map"&&sameLength&&every(actual,function(element,key){return expectation.has(key)&&expectation.get(key)===element;});},"deepEquals(Map[".concat(iterableToString(expectation),"])"));};createMatcher.map.contains=function mapContains(expectation){return createMatcher(function(actual){return typeOf(actual)==="map"&&every(expectation,function(element,key){return actual.has(key)&&actual.get(key)===element;});},"contains(Map[".concat(iterableToString(expectation),"])"));};createMatcher.set=createMatcher.typeOf("set");createMatcher.set.deepEquals=function setDeepEquals(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength=actual.size===expectation.size;return typeOf(actual)==="set"&&sameLength&&every(actual,function(element){return expectation.has(element);});},"deepEquals(Set[".concat(iterableToString(expectation),"])"));};createMatcher.set.contains=function setContains(expectation){return createMatcher(function(actual){return typeOf(actual)==="set"&&every(expectation,function(element){return actual.has(element);});},"contains(Set[".concat(iterableToString(expectation),"])"));};createMatcher.bool=createMatcher.typeOf("boolean");createMatcher.number=createMatcher.typeOf("number");createMatcher.string=createMatcher.typeOf("string");createMatcher.object=createMatcher.typeOf("object");createMatcher.func=createMatcher.typeOf("function");createMatcher.regexp=createMatcher.typeOf("regexp");createMatcher.date=createMatcher.typeOf("date");createMatcher.symbol=createMatcher.typeOf("symbol");module.exports=createMatcher;},{"./create-matcher/assert-matcher":63,"./create-matcher/assert-method-exists":64,"./create-matcher/assert-type":65,"./create-matcher/is-iterable":66,"./create-matcher/is-matcher":67,"./create-matcher/matcher-prototype":69,"./create-matcher/type-map":70,"./deep-equal":71,"./iterable-to-string":85,"@sinonjs/commons":94,"lodash.get":115}],63:[function(require,module,exports){var isMatcher=require("./is-matcher");/** + * Throws a TypeError when `value` is not a matcher + * + * @private + * @param {*} value The value to examine + */function assertMatcher(value){if(!isMatcher(value)){throw new TypeError("Matcher expected");}}module.exports=assertMatcher;},{"./is-matcher":67}],64:[function(require,module,exports){/** + * Throws a TypeError when expected method doesn't exist + * + * @private + * @param {*} value A value to examine + * @param {string} method The name of the method to look for + * @param {name} name A name to use for the error message + * @param {string} methodPath The name of the method to use for error messages + * @throws {TypeError} When the method doesn't exist + */function assertMethodExists(value,method,name,methodPath){if(value[method]===null||value[method]===undefined){throw new TypeError("Expected ".concat(name," to have method ").concat(methodPath));}}module.exports=assertMethodExists;},{}],65:[function(require,module,exports){var typeOf=require("@sinonjs/commons").typeOf;/** + * Ensures that value is of type + * + * @private + * @param {*} value A value to examine + * @param {string} type A basic JavaScript type to compare to, e.g. "object", "string" + * @param {string} name A string to use for the error message + * @throws {TypeError} If value is not of the expected type + * @returns {undefined} + */function assertType(value,type,name){var actual=typeOf(value);if(actual!==type){throw new TypeError("Expected type of ".concat(name," to be ").concat(type,", but was ").concat(actual));}}module.exports=assertType;},{"@sinonjs/commons":94}],66:[function(require,module,exports){var typeOf=require("@sinonjs/commons").typeOf;/** + * Returns `true` for iterables + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` looks like an iterable + */function isIterable(value){return Boolean(value)&&typeOf(value.forEach)==="function";}module.exports=isIterable;},{"@sinonjs/commons":94}],67:[function(require,module,exports){var isPrototypeOf=require("@sinonjs/commons").prototypes.object.isPrototypeOf;var matcherPrototype=require("./matcher-prototype");/** + * Returns `true` when `object` is a matcher + * + * @private + * @param {*} object A value to examine + * @returns {boolean} Returns `true` when `object` is a matcher + */function isMatcher(object){return isPrototypeOf(matcherPrototype,object);}module.exports=isMatcher;},{"./matcher-prototype":69,"@sinonjs/commons":94}],68:[function(require,module,exports){var every=require("@sinonjs/commons").prototypes.array.every;var concat=require("@sinonjs/commons").prototypes.array.concat;var typeOf=require("@sinonjs/commons").typeOf;var deepEqualFactory=require("../deep-equal").use;var isMatcher=require("./is-matcher");var keys=Object.keys;var getOwnPropertySymbols=Object.getOwnPropertySymbols;/** + * Matches `actual` with `expectation` + * + * @private + * @param {*} actual A value to examine + * @param {object} expectation An object with properties to match on + * @param {object} matcher A matcher to use for comparison + * @returns {boolean} Returns true when `actual` matches all properties in `expectation` + */function matchObject(actual,expectation,matcher){var deepEqual=deepEqualFactory(matcher);if(actual===null||actual===undefined){return false;}var expectedKeys=keys(expectation);/* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */if(typeOf(getOwnPropertySymbols)==="function"){expectedKeys=concat(expectedKeys,getOwnPropertySymbols(expectation));}return every(expectedKeys,function(key){var exp=expectation[key];var act=actual[key];if(isMatcher(exp)){if(!exp.test(act)){return false;}}else if(typeOf(exp)==="object"){if(!matchObject(act,exp,matcher)){return false;}}else if(!deepEqual(act,exp)){return false;}return true;});}module.exports=matchObject;},{"../deep-equal":71,"./is-matcher":67,"@sinonjs/commons":94}],69:[function(require,module,exports){var matcherPrototype={toString:function toString(){return this.message;}};matcherPrototype.or=function(valueOrMatcher){var createMatcher=require("../create-matcher");var isMatcher=createMatcher.isMatcher;if(!arguments.length){throw new TypeError("Matcher expected");}var m2=isMatcher(valueOrMatcher)?valueOrMatcher:createMatcher(valueOrMatcher);var m1=this;var or=Object.create(matcherPrototype);or.test=function(actual){return m1.test(actual)||m2.test(actual);};or.message="".concat(m1.message,".or(").concat(m2.message,")");return or;};matcherPrototype.and=function(valueOrMatcher){var createMatcher=require("../create-matcher");var isMatcher=createMatcher.isMatcher;if(!arguments.length){throw new TypeError("Matcher expected");}var m2=isMatcher(valueOrMatcher)?valueOrMatcher:createMatcher(valueOrMatcher);var m1=this;var and=Object.create(matcherPrototype);and.test=function(actual){return m1.test(actual)&&m2.test(actual);};and.message="".concat(m1.message,".and(").concat(m2.message,")");return and;};module.exports=matcherPrototype;},{"../create-matcher":62}],70:[function(require,module,exports){var functionName=require("@sinonjs/commons").functionName;var join=require("@sinonjs/commons").prototypes.array.join;var map=require("@sinonjs/commons").prototypes.array.map;var stringIndexOf=require("@sinonjs/commons").prototypes.string.indexOf;var valueToString=require("@sinonjs/commons").valueToString;var matchObject=require("./match-object");var createTypeMap=function createTypeMap(match){return {"function":function _function(m,expectation,message){m.test=expectation;m.message=message||"match(".concat(functionName(expectation),")");},number:function number(m,expectation){m.test=function(actual){// we need type coercion here + return expectation==actual;// eslint-disable-line eqeqeq + };},object:function object(m,expectation){var array=[];if(typeof expectation.test==="function"){m.test=function(actual){return expectation.test(actual)===true;};m.message="match(".concat(functionName(expectation.test),")");return m;}array=map(Object.keys(expectation),function(key){return "".concat(key,": ").concat(valueToString(expectation[key]));});m.test=function(actual){return matchObject(actual,expectation,match);};m.message="match(".concat(join(array,", "),")");return m;},regexp:function regexp(m,expectation){m.test=function(actual){return typeof actual==="string"&&expectation.test(actual);};},string:function string(m,expectation){m.test=function(actual){return typeof actual==="string"&&stringIndexOf(actual,expectation)!==-1;};m.message="match(\"".concat(expectation,"\")");}};};module.exports=createTypeMap;},{"./match-object":68,"@sinonjs/commons":94}],71:[function(require,module,exports){var valueToString=require("@sinonjs/commons").valueToString;var className=require("@sinonjs/commons").className;var typeOf=require("@sinonjs/commons").typeOf;var arrayProto=require("@sinonjs/commons").prototypes.array;var objectProto=require("@sinonjs/commons").prototypes.object;var mapForEach=require("@sinonjs/commons").prototypes.map.forEach;var getClass=require("./get-class");var identical=require("./identical");var isArguments=require("./is-arguments");var isArrayType=require("./is-array-type");var isDate=require("./is-date");var isElement=require("./is-element");var isIterable=require("./is-iterable");var isMap=require("./is-map");var isNaN=require("./is-nan");var isObject=require("./is-object");var isSet=require("./is-set");var isSubset=require("./is-subset");var concat=arrayProto.concat;var every=arrayProto.every;var push=arrayProto.push;var getTime=Date.prototype.getTime;var hasOwnProperty=objectProto.hasOwnProperty;var indexOf=arrayProto.indexOf;var keys=Object.keys;var getOwnPropertySymbols=Object.getOwnPropertySymbols;/** + * Deep equal comparison. Two values are "deep equal" when: + * + * - They are equal, according to samsam.identical + * - They are both date objects representing the same time + * - They are both arrays containing elements that are all deepEqual + * - They are objects with the same set of properties, and each property + * in ``actual`` is deepEqual to the corresponding property in ``expectation`` + * + * Supports cyclic objects. + * + * @alias module:samsam.deepEqual + * @param {*} actual The object to examine + * @param {*} expectation The object actual is expected to be equal to + * @param {object} match A value to match on + * @returns {boolean} Returns true when actual and expectation are considered equal + */function deepEqualCyclic(actual,expectation,match){// used for cyclic comparison + // contain already visited objects + var actualObjects=[];var expectationObjects=[];// contain pathes (position in the object structure) + // of the already visited objects + // indexes same as in objects arrays + var actualPaths=[];var expectationPaths=[];// contains combinations of already compared objects + // in the manner: { "$1['ref']$2['ref']": true } + var compared={};// does the recursion for the deep equal check + // eslint-disable-next-line complexity + return function deepEqual(actualObj,expectationObj,actualPath,expectationPath){// If both are matchers they must be the same instance in order to be + // considered equal If we didn't do that we would end up running one + // matcher against the other + if(match&&match.isMatcher(expectationObj)){if(match.isMatcher(actualObj)){return actualObj===expectationObj;}return expectationObj.test(actualObj);}var actualType=_typeof$1(actualObj);var expectationType=_typeof$1(expectationObj);if(actualObj===expectationObj||isNaN(actualObj)||isNaN(expectationObj)||actualObj===null||expectationObj===null||actualObj===undefined||expectationObj===undefined||actualType!=="object"||expectationType!=="object"){return identical(actualObj,expectationObj);}// Elements are only equal if identical(expected, actual) + if(isElement(actualObj)||isElement(expectationObj)){return false;}var isActualDate=isDate(actualObj);var isExpectationDate=isDate(expectationObj);if(isActualDate||isExpectationDate){if(!isActualDate||!isExpectationDate||getTime.call(actualObj)!==getTime.call(expectationObj)){return false;}}if(actualObj instanceof RegExp&&expectationObj instanceof RegExp){if(valueToString(actualObj)!==valueToString(expectationObj)){return false;}}if(actualObj instanceof Promise&&expectationObj instanceof Promise){return actualObj===expectationObj;}if(actualObj instanceof Error&&expectationObj instanceof Error){return actualObj===expectationObj;}var actualClass=getClass(actualObj);var expectationClass=getClass(expectationObj);var actualKeys=keys(actualObj);var expectationKeys=keys(expectationObj);var actualName=className(actualObj);var expectationName=className(expectationObj);var expectationSymbols=typeOf(getOwnPropertySymbols)==="function"?getOwnPropertySymbols(expectationObj):/* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */[];var expectationKeysAndSymbols=concat(expectationKeys,expectationSymbols);if(isArguments(actualObj)||isArguments(expectationObj)){if(actualObj.length!==expectationObj.length){return false;}}else {if(actualType!==expectationType||actualClass!==expectationClass||actualKeys.length!==expectationKeys.length||actualName&&expectationName&&actualName!==expectationName){return false;}}if(isSet(actualObj)||isSet(expectationObj)){if(!isSet(actualObj)||!isSet(expectationObj)||actualObj.size!==expectationObj.size){return false;}return isSubset(actualObj,expectationObj,deepEqual);}if(isMap(actualObj)||isMap(expectationObj)){if(!isMap(actualObj)||!isMap(expectationObj)||actualObj.size!==expectationObj.size){return false;}var mapsDeeplyEqual=true;mapForEach(actualObj,function(value,key){mapsDeeplyEqual=mapsDeeplyEqual&&deepEqualCyclic(value,expectationObj.get(key));});return mapsDeeplyEqual;}// jQuery objects have iteration protocols + // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols + // But, they don't work well with the implementation concerning iterables below, + // so we will detect them and use jQuery's own equality function + /* istanbul ignore next -- this can only be tested in the `test-headless` script */if(actualObj.constructor&&actualObj.constructor.name==="jQuery"&&typeof actualObj.is==="function"){return actualObj.is(expectationObj);}var isActualNonArrayIterable=isIterable(actualObj)&&!isArrayType(actualObj)&&!isArguments(actualObj);var isExpectationNonArrayIterable=isIterable(expectationObj)&&!isArrayType(expectationObj)&&!isArguments(expectationObj);if(isActualNonArrayIterable||isExpectationNonArrayIterable){var actualArray=Array.from(actualObj);var expectationArray=Array.from(expectationObj);if(actualArray.length!==expectationArray.length){return false;}var arrayDeeplyEquals=true;every(actualArray,function(key){arrayDeeplyEquals=arrayDeeplyEquals&&deepEqualCyclic(actualArray[key],expectationArray[key]);});return arrayDeeplyEquals;}return every(expectationKeysAndSymbols,function(key){if(!hasOwnProperty(actualObj,key)){return false;}var actualValue=actualObj[key];var expectationValue=expectationObj[key];var actualObject=isObject(actualValue);var expectationObject=isObject(expectationValue);// determines, if the objects were already visited + // (it's faster to check for isObject first, than to + // get -1 from getIndex for non objects) + var actualIndex=actualObject?indexOf(actualObjects,actualValue):-1;var expectationIndex=expectationObject?indexOf(expectationObjects,expectationValue):-1;// determines the new paths of the objects + // - for non cyclic objects the current path will be extended + // by current property name + // - for cyclic objects the stored path is taken + var newActualPath=actualIndex!==-1?actualPaths[actualIndex]:"".concat(actualPath,"[").concat(JSON.stringify(key),"]");var newExpectationPath=expectationIndex!==-1?expectationPaths[expectationIndex]:"".concat(expectationPath,"[").concat(JSON.stringify(key),"]");var combinedPath=newActualPath+newExpectationPath;// stop recursion if current objects are already compared + if(compared[combinedPath]){return true;}// remember the current objects and their paths + if(actualIndex===-1&&actualObject){push(actualObjects,actualValue);push(actualPaths,newActualPath);}if(expectationIndex===-1&&expectationObject){push(expectationObjects,expectationValue);push(expectationPaths,newExpectationPath);}// remember that the current objects are already compared + if(actualObject&&expectationObject){compared[combinedPath]=true;}// End of cyclic logic + // neither actualValue nor expectationValue is a cycle + // continue with next level + return deepEqual(actualValue,expectationValue,newActualPath,newExpectationPath);});}(actual,expectation,"$1","$2");}deepEqualCyclic.use=function(match){return function deepEqual(a,b){return deepEqualCyclic(a,b,match);};};module.exports=deepEqualCyclic;},{"./get-class":72,"./identical":73,"./is-arguments":74,"./is-array-type":75,"./is-date":76,"./is-element":77,"./is-iterable":78,"./is-map":79,"./is-nan":80,"./is-object":82,"./is-set":83,"./is-subset":84,"@sinonjs/commons":94}],72:[function(require,module,exports){var toString=require("@sinonjs/commons").prototypes.object.toString;/** + * Returns the internal `Class` by calling `Object.prototype.toString` + * with the provided value as `this`. Return value is a `String`, naming the + * internal class, e.g. "Array" + * + * @private + * @param {*} value - Any value + * @returns {string} - A string representation of the `Class` of `value` + */function getClass(value){return toString(value).split(/[ \]]/)[1];}module.exports=getClass;},{"@sinonjs/commons":94}],73:[function(require,module,exports){var isNaN=require("./is-nan");var isNegZero=require("./is-neg-zero");/** + * Strict equality check according to EcmaScript Harmony's `egal`. + * + * **From the Harmony wiki:** + * > An `egal` function simply makes available the internal `SameValue` function + * > from section 9.12 of the ES5 spec. If two values are egal, then they are not + * > observably distinguishable. + * + * `identical` returns `true` when `===` is `true`, except for `-0` and + * `+0`, where it returns `false`. Additionally, it returns `true` when + * `NaN` is compared to itself. + * + * @alias module:samsam.identical + * @param {*} obj1 The first value to compare + * @param {*} obj2 The second value to compare + * @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise + */function identical(obj1,obj2){if(obj1===obj2||isNaN(obj1)&&isNaN(obj2)){return obj1!==0||isNegZero(obj1)===isNegZero(obj2);}return false;}module.exports=identical;},{"./is-nan":80,"./is-neg-zero":81}],74:[function(require,module,exports){var getClass=require("./get-class");/** + * Returns `true` when `object` is an `arguments` object, `false` otherwise + * + * @alias module:samsam.isArguments + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an `arguments` object + */function isArguments(object){return getClass(object)==="Arguments";}module.exports=isArguments;},{"./get-class":72}],75:[function(require,module,exports){var functionName=require("@sinonjs/commons").functionName;var indexOf=require("@sinonjs/commons").prototypes.array.indexOf;var map=require("@sinonjs/commons").prototypes.array.map;var ARRAY_TYPES=require("./array-types");var type=require("type-detect");/** + * Returns `true` when `object` is an array type, `false` otherwise + * + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an array type + * @private + */function isArrayType(object){return indexOf(map(ARRAY_TYPES,functionName),type(object))!==-1;}module.exports=isArrayType;},{"./array-types":61,"@sinonjs/commons":94,"type-detect":150}],76:[function(require,module,exports){/** + * Returns `true` when `value` is an instance of Date + * + * @private + * @param {Date} value The value to examine + * @returns {boolean} `true` when `value` is an instance of Date + */function isDate(value){return value instanceof Date;}module.exports=isDate;},{}],77:[function(require,module,exports){var div=typeof document!=="undefined"&&document.createElement("div");/** + * Returns `true` when `object` is a DOM element node. + * + * Unlike Underscore.js/lodash, this function will return `false` if `object` + * is an *element-like* object, i.e. a regular object with a `nodeType` + * property that holds the value `1`. + * + * @alias module:samsam.isElement + * @param {object} object The object to examine + * @returns {boolean} Returns `true` for DOM element nodes + */function isElement(object){if(!object||object.nodeType!==1||!div){return false;}try{object.appendChild(div);object.removeChild(div);}catch(e){return false;}return true;}module.exports=isElement;},{}],78:[function(require,module,exports){/** + * Returns `true` when the argument is an iterable, `false` otherwise + * + * @alias module:samsam.isIterable + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise + */function isIterable(val){// checks for null and undefined + if(_typeof$1(val)!=="object"){return false;}return typeof val[Symbol.iterator]==="function";}module.exports=isIterable;},{}],79:[function(require,module,exports){/** + * Returns `true` when `value` is a Map + * + * @param {*} value A value to examine + * @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise + * @private + */function isMap(value){return typeof Map!=="undefined"&&value instanceof Map;}module.exports=isMap;},{}],80:[function(require,module,exports){/** + * Compares a `value` to `NaN` + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `NaN` + */function isNaN(value){// Unlike global `isNaN`, this function avoids type coercion + // `typeof` check avoids IE host object issues, hat tip to + // lodash + // eslint-disable-next-line no-self-compare + return typeof value==="number"&&value!==value;}module.exports=isNaN;},{}],81:[function(require,module,exports){/** + * Returns `true` when `value` is `-0` + * + * @alias module:samsam.isNegZero + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `-0` + */function isNegZero(value){return value===0&&1/value===-Infinity;}module.exports=isNegZero;},{}],82:[function(require,module,exports){/** + * Returns `true` when the value is a regular Object and not a specialized Object + * + * This helps speed up deepEqual cyclic checks + * + * The premise is that only Objects are stored in the visited array. + * So if this function returns false, we don't have to do the + * expensive operation of searching for the value in the the array of already + * visited objects + * + * @private + * @param {object} value The object to examine + * @returns {boolean} `true` when the object is a non-specialised object + */function isObject(value){return _typeof$1(value)==="object"&&value!==null&&// none of these are collection objects, so we can return false + !(value instanceof Boolean)&&!(value instanceof Date)&&!(value instanceof Error)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String);}module.exports=isObject;},{}],83:[function(require,module,exports){/** + * Returns `true` when the argument is an instance of Set, `false` otherwise + * + * @alias module:samsam.isSet + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise + */function isSet(val){return typeof Set!=="undefined"&&val instanceof Set||false;}module.exports=isSet;},{}],84:[function(require,module,exports){var forEach=require("@sinonjs/commons").prototypes.set.forEach;/** + * Returns `true` when `s1` is a subset of `s2`, `false` otherwise + * + * @private + * @param {Array|Set} s1 The target value + * @param {Array|Set} s2 The containing value + * @param {Function} compare A comparison function, should return `true` when + * values are considered equal + * @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise + */function isSubset(s1,s2,compare){var allContained=true;forEach(s1,function(v1){var includes=false;forEach(s2,function(v2){if(compare(v2,v1)){includes=true;}});allContained=allContained&&includes;});return allContained;}module.exports=isSubset;},{"@sinonjs/commons":94}],85:[function(require,module,exports){var slice=require("@sinonjs/commons").prototypes.string.slice;var typeOf=require("@sinonjs/commons").typeOf;var valueToString=require("@sinonjs/commons").valueToString;/** + * Creates a string represenation of an iterable object + * + * @private + * @param {object} obj The iterable object to stringify + * @returns {string} A string representation + */function iterableToString(obj){if(typeOf(obj)==="map"){return mapToString(obj);}return genericIterableToString(obj);}/** + * Creates a string representation of a Map + * + * @private + * @param {Map} map The map to stringify + * @returns {string} A string representation + */function mapToString(map){var representation="";// eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + map.forEach(function(value,key){representation+="[".concat(stringify(key),",").concat(stringify(value),"],");});representation=slice(representation,0,-1);return representation;}/** + * Create a string represenation for an iterable + * + * @private + * @param {object} iterable The iterable to stringify + * @returns {string} A string representation + */function genericIterableToString(iterable){var representation="";// eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + iterable.forEach(function(value){representation+="".concat(stringify(value),",");});representation=slice(representation,0,-1);return representation;}/** + * Creates a string representation of the passed `item` + * + * @private + * @param {object} item The item to stringify + * @returns {string} A string representation of `item` + */function stringify(item){return typeof item==="string"?"'".concat(item,"'"):valueToString(item);}module.exports=iterableToString;},{"@sinonjs/commons":94}],86:[function(require,module,exports){var valueToString=require("@sinonjs/commons").valueToString;var indexOf=require("@sinonjs/commons").prototypes.string.indexOf;var forEach=require("@sinonjs/commons").prototypes.array.forEach;var type=require("type-detect");var engineCanCompareMaps=typeof Array.from==="function";var deepEqual=require("./deep-equal").use(match);// eslint-disable-line no-use-before-define + var isArrayType=require("./is-array-type");var isSubset=require("./is-subset");var createMatcher=require("./create-matcher");/** + * Returns true when `array` contains all of `subset` as defined by the `compare` + * argument + * + * @param {Array} array An array to search for a subset + * @param {Array} subset The subset to find in the array + * @param {Function} compare A comparison function + * @returns {boolean} [description] + * @private + */function arrayContains(array,subset,compare){if(subset.length===0){return true;}var i,l,j,k;for(i=0,l=array.length;i=l){return false;}if(!compare(array[i+j],subset[j])){return false;}}return true;}}return false;}/* eslint-disable complexity */ /** + * Matches an object with a matcher (or value) + * + * @alias module:samsam.match + * @param {object} object The object candidate to match + * @param {object} matcherOrValue A matcher or value to match against + * @returns {boolean} true when `object` matches `matcherOrValue` + */function match(object,matcherOrValue){if(matcherOrValue&&typeof matcherOrValue.test==="function"){return matcherOrValue.test(object);}switch(type(matcherOrValue)){case"bigint":case"boolean":case"number":case"symbol":return matcherOrValue===object;case"function":return matcherOrValue(object)===true;case"string":var notNull=typeof object==="string"||Boolean(object);return notNull&&indexOf(valueToString(object).toLowerCase(),matcherOrValue.toLowerCase())>=0;case"null":return object===null;case"undefined":return typeof object==="undefined";case"Date":/* istanbul ignore else */if(type(object)==="Date"){return object.getTime()===matcherOrValue.getTime();}/* istanbul ignore next: this is basically the rest of the function, which is covered */break;case"Array":case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":return isArrayType(matcherOrValue)&&arrayContains(object,matcherOrValue,match);case"Map":/* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/if(!engineCanCompareMaps){throw new Error("The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances");}return type(object)==="Map"&&arrayContains(Array.from(object),Array.from(matcherOrValue),match);}switch(type(object)){case"null":return false;case"Set":return isSubset(matcherOrValue,object,match);}/* istanbul ignore else */if(matcherOrValue&&_typeof$1(matcherOrValue)==="object"){if(matcherOrValue===object){return true;}if(_typeof$1(object)!=="object"){return false;}var prop;// eslint-disable-next-line guard-for-in + for(prop in matcherOrValue){var value=object[prop];if(typeof value==="undefined"&&typeof object.getAttribute==="function"){value=object.getAttribute(prop);}if(matcherOrValue[prop]===null||typeof matcherOrValue[prop]==="undefined"){if(value!==matcherOrValue[prop]){return false;}}else if(typeof value==="undefined"||!deepEqual(value,matcherOrValue[prop])){return false;}}return true;}/* istanbul ignore next */throw new Error("Matcher was an unknown or unsupported type");}/* eslint-enable complexity */forEach(Object.keys(createMatcher),function(key){match[key]=createMatcher[key];});module.exports=match;},{"./create-matcher":62,"./deep-equal":71,"./is-array-type":75,"./is-subset":84,"@sinonjs/commons":94,"type-detect":150}],87:[function(require,module,exports){/** + * @module samsam + */var identical=require("./identical");var isArguments=require("./is-arguments");var isElement=require("./is-element");var isNegZero=require("./is-neg-zero");var isSet=require("./is-set");var isMap=require("./is-map");var match=require("./match");var deepEqualCyclic=require("./deep-equal").use(match);var createMatcher=require("./create-matcher");module.exports={createMatcher:createMatcher,deepEqual:deepEqualCyclic,identical:identical,isArguments:isArguments,isElement:isElement,isMap:isMap,isNegZero:isNegZero,isSet:isSet,match:match};},{"./create-matcher":62,"./deep-equal":71,"./identical":73,"./is-arguments":74,"./is-element":77,"./is-map":79,"./is-neg-zero":81,"./is-set":83,"./match":86}],88:[function(require,module,exports){arguments[4][41][0].apply(exports,arguments);},{"./prototypes/array":96,"dup":41}],89:[function(require,module,exports){arguments[4][42][0].apply(exports,arguments);},{"./function-name":92,"dup":42}],90:[function(require,module,exports){arguments[4][43][0].apply(exports,arguments);},{"dup":43}],91:[function(require,module,exports){arguments[4][44][0].apply(exports,arguments);},{"dup":44}],92:[function(require,module,exports){arguments[4][45][0].apply(exports,arguments);},{"dup":45}],93:[function(require,module,exports){arguments[4][46][0].apply(exports,arguments);},{"dup":46}],94:[function(require,module,exports){arguments[4][47][0].apply(exports,arguments);},{"./called-in-order":88,"./class-name":89,"./deprecated":90,"./every":91,"./function-name":92,"./global":93,"./order-by-first-call":95,"./prototypes":99,"./type-of":105,"./value-to-string":106,"dup":47}],95:[function(require,module,exports){arguments[4][48][0].apply(exports,arguments);},{"./prototypes/array":96,"dup":48}],96:[function(require,module,exports){arguments[4][49][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":49}],97:[function(require,module,exports){arguments[4][50][0].apply(exports,arguments);},{"./throws-on-proto":104,"dup":50}],98:[function(require,module,exports){arguments[4][51][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":51}],99:[function(require,module,exports){arguments[4][52][0].apply(exports,arguments);},{"./array":96,"./function":98,"./map":100,"./object":101,"./set":102,"./string":103,"dup":52}],100:[function(require,module,exports){arguments[4][53][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":53}],101:[function(require,module,exports){arguments[4][54][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":54}],102:[function(require,module,exports){arguments[4][55][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":55}],103:[function(require,module,exports){arguments[4][56][0].apply(exports,arguments);},{"./copy-prototype-methods":97,"dup":56}],104:[function(require,module,exports){arguments[4][57][0].apply(exports,arguments);},{"dup":57}],105:[function(require,module,exports){arguments[4][58][0].apply(exports,arguments);},{"dup":58,"type-detect":150}],106:[function(require,module,exports){arguments[4][59][0].apply(exports,arguments);},{"dup":59}],107:[function(require,module,exports){// This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + var encoding=require("./lib/encoding.js");module.exports={TextEncoder:encoding.TextEncoder,TextDecoder:encoding.TextDecoder};},{"./lib/encoding.js":109}],108:[function(require,module,exports){(function(global){if(typeof module!=="undefined"&&module.exports){module.exports=global;}global["encoding-indexes"]={"big5":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,17392,19506,17923,17830,17784,160359,19831,17843,162993,19682,163013,15253,18230,18244,19527,19520,148159,144919,160594,159371,159954,19543,172881,18255,17882,19589,162924,19719,19108,18081,158499,29221,154196,137827,146950,147297,26189,22267,null,32149,22813,166841,15860,38708,162799,23515,138590,23204,13861,171696,23249,23479,23804,26478,34195,170309,29793,29853,14453,138579,145054,155681,16108,153822,15093,31484,40855,147809,166157,143850,133770,143966,17162,33924,40854,37935,18736,34323,22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,36934,13542,29636,155065,29894,40903,22451,18735,21580,16689,145038,22552,31346,162661,35727,18094,159368,16769,155033,31662,140476,40904,140481,140489,140492,40905,34052,144827,16564,40906,17633,175615,25281,28782,40907,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,12736,12737,12738,12739,12740,131340,12741,131281,131277,12742,12743,131275,139240,12744,131274,12745,12746,12747,12748,131342,12749,12750,256,193,461,192,274,201,282,200,332,211,465,210,null,7870,null,7872,202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,null,7871,null,7873,234,609,9178,9179,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,172969,135493,null,25866,null,null,20029,28381,40270,37343,null,null,161589,25745,20250,20264,20392,20822,20852,20892,20964,21153,21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,36711,36718,29713,31996,32205,26950,31433,21031,null,null,null,null,37260,30904,37214,32956,null,36107,33014,133607,null,null,32927,40647,19661,40393,40460,19518,171510,159758,40458,172339,13761,null,28314,33342,29977,null,18705,39532,39567,40857,31111,164972,138698,132560,142054,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,163204,21797,null,134210,134421,151851,21904,142534,14828,131905,36422,150968,169189,16467,164030,30586,142392,14900,18389,164189,158194,151018,25821,134524,135092,134357,135412,25741,36478,134806,134155,135012,142505,164438,148691,null,134470,170573,164073,18420,151207,142530,39602,14951,169460,16365,13574,152263,169940,161992,142660,40302,38933,null,17369,155813,25780,21731,142668,142282,135287,14843,135279,157402,157462,162208,25834,151634,134211,36456,139681,166732,132913,null,18443,131497,16378,22643,142733,null,148936,132348,155799,134988,134550,21881,16571,17338,null,19124,141926,135325,33194,39157,134556,25465,14846,141173,36288,22177,25724,15939,null,173569,134665,142031,142537,null,135368,145858,14738,14854,164507,13688,155209,139463,22098,134961,142514,169760,13500,27709,151099,null,null,161140,142987,139784,173659,167117,134778,134196,157724,32659,135375,141315,141625,13819,152035,134796,135053,134826,16275,134960,134471,135503,134732,null,134827,134057,134472,135360,135485,16377,140950,25650,135085,144372,161337,142286,134526,134527,142417,142421,14872,134808,135367,134958,173618,158544,167122,167321,167114,38314,21708,33476,21945,null,171715,39974,39606,161630,142830,28992,33133,33004,23580,157042,33076,14231,21343,164029,37302,134906,134671,134775,134907,13789,151019,13833,134358,22191,141237,135369,134672,134776,135288,135496,164359,136277,134777,151120,142756,23124,135197,135198,135413,135414,22428,134673,161428,164557,135093,134779,151934,14083,135094,135552,152280,172733,149978,137274,147831,164476,22681,21096,13850,153405,31666,23400,18432,19244,40743,18919,39967,39821,154484,143677,22011,13810,22153,20008,22786,138177,194680,38737,131206,20059,20155,13630,23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,149737,32594,31035,31993,32595,156266,13505,null,156491,32770,32896,157202,158033,21341,34916,35265,161970,35744,36125,38021,38264,38271,38376,167439,38886,39029,39118,39134,39267,170000,40060,40479,40644,27503,63751,20023,131207,38429,25143,38050,null,20539,28158,171123,40870,15817,34959,147790,28791,23797,19232,152013,13657,154928,24866,166450,36775,37366,29073,26393,29626,144001,172295,15499,137600,19216,30948,29698,20910,165647,16393,27235,172730,16931,34319,133743,31274,170311,166634,38741,28749,21284,139390,37876,30425,166371,40871,30685,20131,20464,20668,20015,20247,40872,21556,32139,22674,22736,138678,24210,24217,24514,141074,25995,144377,26905,27203,146531,27903,null,29184,148741,29580,16091,150035,23317,29881,35715,154788,153237,31379,31724,31939,32364,33528,34199,40873,34960,40874,36537,40875,36815,34143,39392,37409,40876,167353,136255,16497,17058,23066,null,null,null,39016,26475,17014,22333,null,34262,149883,33471,160013,19585,159092,23931,158485,159678,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,143958,141206,17306,17718,null,23765,146202,35577,23672,15634,144721,23928,40882,29015,17752,147692,138787,19575,14712,13386,131492,158785,35532,20404,131641,22975,33132,38998,170234,24379,134047,null,139713,166253,16642,18107,168057,16135,40883,172469,16632,14294,18167,158790,16764,165554,160767,17773,14548,152730,17761,17691,19849,19579,19830,17898,16328,150287,13921,17630,17597,16877,23870,23880,23894,15868,14351,23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,26111,26195,15090,26258,15138,26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,28033,15599,28068,28081,28181,28184,28201,28294,166336,28347,28386,28378,40831,28392,28393,28452,28468,15686,147265,28545,28606,15722,15733,29111,23705,15754,28716,15761,28752,28756,28783,28799,28809,131877,17345,13809,134872,147159,22462,159443,28990,153568,13902,27042,166889,23412,31305,153825,169177,31333,31357,154028,31419,31408,31426,31427,29137,156813,16842,31450,31453,31466,16879,21682,154625,31499,31573,31529,152334,154878,31650,31599,33692,154548,158847,31696,33825,31634,31672,154912,15789,154725,33938,31738,31750,31797,154817,31812,31875,149634,31910,26237,148856,31945,31943,31974,31860,31987,31989,31950,32359,17693,159300,32093,159446,29837,32137,32171,28981,32179,32210,147543,155689,32228,15635,32245,137209,32229,164717,32285,155937,155994,32366,32402,17195,37996,32295,32576,32577,32583,31030,156368,39393,32663,156497,32675,136801,131176,17756,145254,17667,164666,32762,156809,32773,32776,32797,32808,32815,172167,158915,32827,32828,32865,141076,18825,157222,146915,157416,26405,32935,166472,33031,33050,22704,141046,27775,156824,151480,25831,136330,33304,137310,27219,150117,150165,17530,33321,133901,158290,146814,20473,136445,34018,33634,158474,149927,144688,137075,146936,33450,26907,194964,16859,34123,33488,33562,134678,137140,14017,143741,144730,33403,33506,33560,147083,159139,158469,158615,144846,15807,33565,21996,33669,17675,159141,33708,33729,33747,13438,159444,27223,34138,13462,159298,143087,33880,154596,33905,15827,17636,27303,33866,146613,31064,33960,158614,159351,159299,34014,33807,33681,17568,33939,34020,154769,16960,154816,17731,34100,23282,159385,17703,34163,17686,26559,34326,165413,165435,34241,159880,34306,136578,159949,194994,17770,34344,13896,137378,21495,160666,34430,34673,172280,34798,142375,34737,34778,34831,22113,34412,26710,17935,34885,34886,161248,146873,161252,34910,34972,18011,34996,34997,25537,35013,30583,161551,35207,35210,35238,35241,35239,35260,166437,35303,162084,162493,35484,30611,37374,35472,162393,31465,162618,147343,18195,162616,29052,35596,35615,152624,152933,35647,35660,35661,35497,150138,35728,35739,35503,136927,17941,34895,35995,163156,163215,195028,14117,163155,36054,163224,163261,36114,36099,137488,36059,28764,36113,150729,16080,36215,36265,163842,135188,149898,15228,164284,160012,31463,36525,36534,36547,37588,36633,36653,164709,164882,36773,37635,172703,133712,36787,18730,166366,165181,146875,24312,143970,36857,172052,165564,165121,140069,14720,159447,36919,165180,162494,36961,165228,165387,37032,165651,37060,165606,37038,37117,37223,15088,37289,37316,31916,166195,138889,37390,27807,37441,37474,153017,37561,166598,146587,166668,153051,134449,37676,37739,166625,166891,28815,23235,166626,166629,18789,37444,166892,166969,166911,37747,37979,36540,38277,38310,37926,38304,28662,17081,140922,165592,135804,146990,18911,27676,38523,38550,16748,38563,159445,25050,38582,30965,166624,38589,21452,18849,158904,131700,156688,168111,168165,150225,137493,144138,38705,34370,38710,18959,17725,17797,150249,28789,23361,38683,38748,168405,38743,23370,168427,38751,37925,20688,143543,143548,38793,38815,38833,38846,38848,38866,38880,152684,38894,29724,169011,38911,38901,168989,162170,19153,38964,38963,38987,39014,15118,160117,15697,132656,147804,153350,39114,39095,39112,39111,19199,159015,136915,21936,39137,39142,39148,37752,39225,150057,19314,170071,170245,39413,39436,39483,39440,39512,153381,14020,168113,170965,39648,39650,170757,39668,19470,39700,39725,165376,20532,39732,158120,14531,143485,39760,39744,171326,23109,137315,39822,148043,39938,39935,39948,171624,40404,171959,172434,172459,172257,172323,172511,40318,40323,172340,40462,26760,40388,139611,172435,172576,137531,172595,40249,172217,172724,40592,40597,40606,40610,19764,40618,40623,148324,40641,15200,14821,15645,20274,14270,166955,40706,40712,19350,37924,159138,40727,40726,40761,22175,22154,40773,39352,168075,38898,33919,40802,40809,31452,40846,29206,19390,149877,149947,29047,150008,148296,150097,29598,166874,137466,31135,166270,167478,37737,37875,166468,37612,37761,37835,166252,148665,29207,16107,30578,31299,28880,148595,148472,29054,137199,28835,137406,144793,16071,137349,152623,137208,14114,136955,137273,14049,137076,137425,155467,14115,136896,22363,150053,136190,135848,136134,136374,34051,145062,34051,33877,149908,160101,146993,152924,147195,159826,17652,145134,170397,159526,26617,14131,15381,15847,22636,137506,26640,16471,145215,147681,147595,147727,158753,21707,22174,157361,22162,135135,134056,134669,37830,166675,37788,20216,20779,14361,148534,20156,132197,131967,20299,20362,153169,23144,131499,132043,14745,131850,132116,13365,20265,131776,167603,131701,35546,131596,20120,20685,20749,20386,20227,150030,147082,20290,20526,20588,20609,20428,20453,20568,20732,20825,20827,20829,20830,28278,144789,147001,147135,28018,137348,147081,20904,20931,132576,17629,132259,132242,132241,36218,166556,132878,21081,21156,133235,21217,37742,18042,29068,148364,134176,149932,135396,27089,134685,29817,16094,29849,29716,29782,29592,19342,150204,147597,21456,13700,29199,147657,21940,131909,21709,134086,22301,37469,38644,37734,22493,22413,22399,13886,22731,23193,166470,136954,137071,136976,23084,22968,37519,23166,23247,23058,153926,137715,137313,148117,14069,27909,29763,23073,155267,23169,166871,132115,37856,29836,135939,28933,18802,37896,166395,37821,14240,23582,23710,24158,24136,137622,137596,146158,24269,23375,137475,137476,14081,137376,14045,136958,14035,33066,166471,138682,144498,166312,24332,24334,137511,137131,23147,137019,23364,34324,161277,34912,24702,141408,140843,24539,16056,140719,140734,168072,159603,25024,131134,131142,140827,24985,24984,24693,142491,142599,149204,168269,25713,149093,142186,14889,142114,144464,170218,142968,25399,173147,25782,25393,25553,149987,142695,25252,142497,25659,25963,26994,15348,143502,144045,149897,144043,21773,144096,137433,169023,26318,144009,143795,15072,16784,152964,166690,152975,136956,152923,152613,30958,143619,137258,143924,13412,143887,143746,148169,26254,159012,26219,19347,26160,161904,138731,26211,144082,144097,26142,153714,14545,145466,145340,15257,145314,144382,29904,15254,26511,149034,26806,26654,15300,27326,14435,145365,148615,27187,27218,27337,27397,137490,25873,26776,27212,15319,27258,27479,147392,146586,37792,37618,166890,166603,37513,163870,166364,37991,28069,28427,149996,28007,147327,15759,28164,147516,23101,28170,22599,27940,30786,28987,148250,148086,28913,29264,29319,29332,149391,149285,20857,150180,132587,29818,147192,144991,150090,149783,155617,16134,16049,150239,166947,147253,24743,16115,29900,29756,37767,29751,17567,159210,17745,30083,16227,150745,150790,16216,30037,30323,173510,15129,29800,166604,149931,149902,15099,15821,150094,16127,149957,149747,37370,22322,37698,166627,137316,20703,152097,152039,30584,143922,30478,30479,30587,149143,145281,14942,149744,29752,29851,16063,150202,150215,16584,150166,156078,37639,152961,30750,30861,30856,30930,29648,31065,161601,153315,16654,31131,33942,31141,27181,147194,31290,31220,16750,136934,16690,37429,31217,134476,149900,131737,146874,137070,13719,21867,13680,13994,131540,134157,31458,23129,141045,154287,154268,23053,131675,30960,23082,154566,31486,16889,31837,31853,16913,154547,155324,155302,31949,150009,137136,31886,31868,31918,27314,32220,32263,32211,32590,156257,155996,162632,32151,155266,17002,158581,133398,26582,131150,144847,22468,156690,156664,149858,32733,31527,133164,154345,154947,31500,155150,39398,34373,39523,27164,144447,14818,150007,157101,39455,157088,33920,160039,158929,17642,33079,17410,32966,33033,33090,157620,39107,158274,33378,33381,158289,33875,159143,34320,160283,23174,16767,137280,23339,137377,23268,137432,34464,195004,146831,34861,160802,23042,34926,20293,34951,35007,35046,35173,35149,153219,35156,161669,161668,166901,166873,166812,166393,16045,33955,18165,18127,14322,35389,35356,169032,24397,37419,148100,26068,28969,28868,137285,40301,35999,36073,163292,22938,30659,23024,17262,14036,36394,36519,150537,36656,36682,17140,27736,28603,140065,18587,28537,28299,137178,39913,14005,149807,37051,37015,21873,18694,37307,37892,166475,16482,166652,37927,166941,166971,34021,35371,38297,38311,38295,38294,167220,29765,16066,149759,150082,148458,16103,143909,38543,167655,167526,167525,16076,149997,150136,147438,29714,29803,16124,38721,168112,26695,18973,168083,153567,38749,37736,166281,166950,166703,156606,37562,23313,35689,18748,29689,147995,38811,38769,39224,134950,24001,166853,150194,38943,169178,37622,169431,37349,17600,166736,150119,166756,39132,166469,16128,37418,18725,33812,39227,39245,162566,15869,39323,19311,39338,39516,166757,153800,27279,39457,23294,39471,170225,19344,170312,39356,19389,19351,37757,22642,135938,22562,149944,136424,30788,141087,146872,26821,15741,37976,14631,24912,141185,141675,24839,40015,40019,40059,39989,39952,39807,39887,171565,39839,172533,172286,40225,19630,147716,40472,19632,40204,172468,172269,172275,170287,40357,33981,159250,159711,158594,34300,17715,159140,159364,159216,33824,34286,159232,145367,155748,31202,144796,144960,18733,149982,15714,37851,37566,37704,131775,30905,37495,37965,20452,13376,36964,152925,30781,30804,30902,30795,137047,143817,149825,13978,20338,28634,28633,28702,28702,21524,147893,22459,22771,22410,40214,22487,28980,13487,147884,29163,158784,151447,23336,137141,166473,24844,23246,23051,17084,148616,14124,19323,166396,37819,37816,137430,134941,33906,158912,136211,148218,142374,148417,22932,146871,157505,32168,155995,155812,149945,149899,166394,37605,29666,16105,29876,166755,137375,16097,150195,27352,29683,29691,16086,150078,150164,137177,150118,132007,136228,149989,29768,149782,28837,149878,37508,29670,37727,132350,37681,166606,166422,37766,166887,153045,18741,166530,29035,149827,134399,22180,132634,134123,134328,21762,31172,137210,32254,136898,150096,137298,17710,37889,14090,166592,149933,22960,137407,137347,160900,23201,14050,146779,14000,37471,23161,166529,137314,37748,15565,133812,19094,14730,20724,15721,15692,136092,29045,17147,164376,28175,168164,17643,27991,163407,28775,27823,15574,147437,146989,28162,28428,15727,132085,30033,14012,13512,18048,16090,18545,22980,37486,18750,36673,166940,158656,22546,22472,14038,136274,28926,148322,150129,143331,135856,140221,26809,26983,136088,144613,162804,145119,166531,145366,144378,150687,27162,145069,158903,33854,17631,17614,159014,159057,158850,159710,28439,160009,33597,137018,33773,158848,159827,137179,22921,23170,137139,23137,23153,137477,147964,14125,23023,137020,14023,29070,37776,26266,148133,23150,23083,148115,27179,147193,161590,148571,148170,28957,148057,166369,20400,159016,23746,148686,163405,148413,27148,148054,135940,28838,28979,148457,15781,27871,194597,150095,32357,23019,23855,15859,24412,150109,137183,32164,33830,21637,146170,144128,131604,22398,133333,132633,16357,139166,172726,28675,168283,23920,29583,31955,166489,168992,20424,32743,29389,29456,162548,29496,29497,153334,29505,29512,16041,162584,36972,29173,149746,29665,33270,16074,30476,16081,27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,151388,29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,23646,30654,30667,22770,30744,28857,30748,16552,30777,30791,30801,30822,33864,152885,31027,26627,31026,16643,16649,31121,31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,31981,36755,28864,134351,32207,32212,32208,32253,32686,32692,29343,17303,32800,32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,38469,34699,17926,17943,34990,35071,35108,35143,35217,162151,35369,35384,35476,35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,39809,39901,39921,39924,19565,39968,14191,138178,40265,39994,40702,22096,40339,40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,40696,31432,40772,131220,131767,132000,26906,38083,22956,132311,22592,38081,14265,132565,132629,132726,136890,22359,29043,133826,133837,134079,21610,194619,134091,21662,134139,134203,134227,134245,134268,24807,134285,22138,134325,134365,134381,134511,134578,134600,26965,39983,34725,134660,134670,134871,135056,134957,134771,23584,135100,24075,135260,135247,135286,26398,135291,135304,135318,13895,135359,135379,135471,135483,21348,33965,135907,136053,135990,35713,136567,136729,137155,137159,20088,28859,137261,137578,137773,137797,138282,138352,138412,138952,25283,138965,139029,29080,26709,139333,27113,14024,139900,140247,140282,141098,141425,141647,33533,141671,141715,142037,35237,142056,36768,142094,38840,142143,38983,39613,142412,null,142472,142519,154600,142600,142610,142775,142741,142914,143220,143308,143411,143462,144159,144350,24497,26184,26303,162425,144743,144883,29185,149946,30679,144922,145174,32391,131910,22709,26382,26904,146087,161367,155618,146961,147129,161278,139418,18640,19128,147737,166554,148206,148237,147515,148276,148374,150085,132554,20946,132625,22943,138920,15294,146687,148484,148694,22408,149108,14747,149295,165352,170441,14178,139715,35678,166734,39382,149522,149755,150037,29193,150208,134264,22885,151205,151430,132985,36570,151596,21135,22335,29041,152217,152601,147274,150183,21948,152646,152686,158546,37332,13427,152895,161330,152926,18200,152930,152934,153543,149823,153693,20582,13563,144332,24798,153859,18300,166216,154286,154505,154630,138640,22433,29009,28598,155906,162834,36950,156082,151450,35682,156674,156746,23899,158711,36662,156804,137500,35562,150006,156808,147439,156946,19392,157119,157365,141083,37989,153569,24981,23079,194765,20411,22201,148769,157436,20074,149812,38486,28047,158909,13848,35191,157593,157806,156689,157790,29151,157895,31554,168128,133649,157990,37124,158009,31301,40432,158202,39462,158253,13919,156777,131105,31107,158260,158555,23852,144665,33743,158621,18128,158884,30011,34917,159150,22710,14108,140685,159819,160205,15444,160384,160389,37505,139642,160395,37680,160486,149968,27705,38047,160848,134904,34855,35061,141606,164979,137137,28344,150058,137248,14756,14009,23568,31203,17727,26294,171181,170148,35139,161740,161880,22230,16607,136714,14753,145199,164072,136133,29101,33638,162269,168360,23143,19639,159919,166315,162301,162314,162571,163174,147834,31555,31102,163849,28597,172767,27139,164632,21410,159239,37823,26678,38749,164207,163875,158133,136173,143919,163912,23941,166960,163971,22293,38947,166217,23979,149896,26046,27093,21458,150181,147329,15377,26422,163984,164084,164142,139169,164175,164233,164271,164378,164614,164655,164746,13770,164968,165546,18682,25574,166230,30728,37461,166328,17394,166375,17375,166376,166726,166868,23032,166921,36619,167877,168172,31569,168208,168252,15863,168286,150218,36816,29327,22155,169191,169449,169392,169400,169778,170193,170313,170346,170435,170536,170766,171354,171419,32415,171768,171811,19620,38215,172691,29090,172799,19857,36882,173515,19868,134300,36798,21953,36794,140464,36793,150163,17673,32383,28502,27313,20202,13540,166700,161949,14138,36480,137205,163876,166764,166809,162366,157359,15851,161365,146615,153141,153942,20122,155265,156248,22207,134765,36366,23405,147080,150686,25566,25296,137206,137339,25904,22061,154698,21530,152337,15814,171416,19581,22050,22046,32585,155352,22901,146752,34672,19996,135146,134473,145082,33047,40286,36120,30267,40005,30286,30649,37701,21554,33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,134813,13774,22021,22001,26353,164578,13869,30004,22000,21946,21655,21874,134209,134294,24272,151880,134774,142434,134818,40619,32090,21982,135285,25245,38765,21652,36045,29174,37238,25596,25529,25598,21865,142147,40050,143027,20890,13535,134567,20903,21581,21790,21779,30310,36397,157834,30129,32950,34820,34694,35015,33206,33820,135361,17644,29444,149254,23440,33547,157843,22139,141044,163119,147875,163187,159440,160438,37232,135641,37384,146684,173737,134828,134905,29286,138402,18254,151490,163833,135147,16634,40029,25887,142752,18675,149472,171388,135148,134666,24674,161187,135149,null,155720,135559,29091,32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,149016,22682,150382,33325,21579,22442,154261,133497,null,14930,140389,29556,171692,19721,39917,146686,171824,19547,151465,169374,171998,33884,146870,160434,157619,145184,25390,32037,147191,146988,14890,36872,21196,15988,13946,17897,132238,30272,23280,134838,30842,163630,22695,16575,22140,39819,23924,30292,173108,40581,19681,30201,14331,24857,143578,148466,null,22109,135849,22439,149859,171526,21044,159918,13741,27722,40316,31830,39737,22494,137068,23635,25811,169168,156469,160100,34477,134440,159010,150242,134513,null,20990,139023,23950,38659,138705,40577,36940,31519,39682,23761,31651,25192,25397,39679,31695,39722,31870,39726,31810,31878,39957,31740,39689,40727,39963,149822,40794,21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,38465,27008,20646,30022,137069,39386,21107,null,37209,38529,37212,null,37201,167575,25471,159011,27338,22033,37262,30074,25221,132092,29519,31856,154657,146685,null,149785,30422,39837,20010,134356,33726,34882,null,23626,27072,20717,22394,21023,24053,20174,27697,131570,20281,21660,21722,21146,36226,13822,24332,13811,null,27474,37244,40869,39831,38958,39092,39610,40616,40580,29050,31508,null,27642,34840,32632,null,22048,173642,36471,40787,null,36308,36431,40476,36353,25218,164733,36392,36469,31443,150135,31294,30936,27882,35431,30215,166490,40742,27854,34774,30147,172722,30803,194624,36108,29410,29553,35629,29442,29937,36075,150203,34351,24506,34976,17591,null,137275,159237,null,35454,140571,null,24829,30311,39639,40260,37742,39823,34805,null,34831,36087,29484,38689,39856,13782,29362,19463,31825,39242,155993,24921,19460,40598,24957,null,22367,24943,25254,25145,25294,14940,25058,21418,144373,25444,26626,13778,23895,166850,36826,167481,null,20697,138566,30982,21298,38456,134971,16485,null,30718,null,31938,155418,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,160902,32859,29936,33027,30500,35209,157644,30035,159441,34729,34766,33224,34700,35401,36013,35651,30507,29944,34010,13877,27058,36262,null,35241,29800,28089,34753,147473,29927,15835,29046,24740,24988,15569,29026,24695,null,32625,166701,29264,24809,19326,21024,15384,146631,155351,161366,152881,137540,135934,170243,159196,159917,23745,156077,166415,145015,131310,157766,151310,17762,23327,156492,40784,40614,156267,12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,12321,12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19968,20057,19969,19971,20035,20061,20102,20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,20800,20995,21242,21315,21449,21475,22303,22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,20887,20982,20998,20999,21000,21243,21246,21247,21270,21305,21320,21319,21317,21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,29916,29926,29976,29983,29992,29993,30000,30001,30002,30003,30091,30333,30382,30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,20073,20121,20132,20134,20133,20223,20233,20249,20234,20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,22930,22952,22942,22947,22937,22934,22925,22948,22931,22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,21658,21602,21608,21643,21629,21646,22266,22403,22391,22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,32937,32948,32938,32943,33253,33278,33293,33459,33437,33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,22865,22863,22862,22864,23004,23000,23039,23011,23016,23043,23013,23018,23002,23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,27954,27946,27969,27941,27916,27953,27934,27927,27963,27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,31361,31487,31485,31869,32002,32005,32000,32009,32007,32004,32006,32568,32654,32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,35331,35998,36000,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,21769,21742,21738,21734,21799,21767,21757,21775,22275,22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,32020,32016,32021,32026,32028,32013,32025,32027,32570,32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,24246,24245,24254,24373,24375,24407,24428,24425,24427,24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,33333,33335,33334,33337,33678,33694,33688,33656,33698,33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,25954,25955,26001,26000,26031,26222,26224,26228,26230,26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,36024,36234,36229,36225,36302,36317,36299,36314,36305,36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,28998,29032,29014,29242,29266,29495,29509,29503,29502,29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,39156,39165,39166,39347,39345,39348,39649,40169,40578,40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,32862,32858,32903,33104,33152,33167,33160,33162,33151,33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,26292,26289,27171,27167,27112,27137,27166,27161,27133,27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,39389,39376,39391,39387,39377,39381,39378,39385,39607,39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,36986,37172,37266,37664,37686,37624,37683,37679,37666,37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,35140,35128,35133,35244,35598,35607,35609,35611,35594,35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37000,37291,37292,37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,40672,40725,40748,20787,22181,22750,22751,22754,23541,40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,38876,38907,39006,39000,39003,39100,39237,39241,39446,39449,39693,39912,39911,39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,25885,25884,26005,26345,27387,27396,27386,27570,28748,29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,38002,38000,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,24027,12083,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,710,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,65339,65341,10045,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8679,8632,8633,12751,131276,20058,131210,20994,17553,40880,20872,40881,161287,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,12003,null,null,null,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,32917,32921,32912,32914,32924,33424,33423,33413,33422,33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,27842,27834,27843,27846,27885,27890,27858,27869,27828,27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,24631,24633,24660,24690,24670,24645,24659,24647,24649,24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,32969,32975,32983,32998,32973,33279,33313,33428,33497,33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,26702,26692,26676,26653,26642,26644,26662,26664,26670,26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28000,28055,28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,33607,33605,33612,33619,33566,33580,33611,33575,33608,34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,24720,24710,24766,24752,24762,24787,24788,24783,24804,24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,31531,31533,31535,31538,31544,31514,31523,31892,31896,31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,21902,22284,22569,22583,22553,22558,22567,22563,22568,22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,28252,28257,28209,28200,28256,28273,28267,28217,28194,28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,35000,35008,35006,34998,35004,34999,35005,34994,35073,35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,24886,24882,24878,24902,24879,24911,24873,24896,25120,37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,27002,26952,26953,26933,26988,26931,26941,26981,26864,27000,26932,26985,26944,26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,30873,30848,30870,30843,31100,31106,31101,31097,31249,31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,37470,37507,37422,37450,37446,37485,37484,37455,37472,37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,27050,27041,27038,27097,27031,27024,27074,27061,27045,27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,33972,33985,33997,33962,33946,33969,34000,33949,33959,33979,33954,33940,33991,33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,34587,34627,34604,34625,34622,34630,34592,34610,34602,34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,25005,24991,24978,25002,24993,24973,24934,25011,25133,25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,33362,33360,33358,33361,34084,34107,34063,34048,34089,34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,39382,39384,39371,39383,39372,39603,39660,39659,39667,39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,24296,24293,24395,24508,24989,25000,24982,25029,25012,25030,25025,25036,25018,25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,30261,30258,30256,30395,30438,30618,30621,30625,30620,30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,37634,37668,37631,37673,37689,37685,37674,37652,37644,37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,31730,31744,31743,31739,31758,31732,31755,31731,31746,31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,39421,39422,39420,39427,39614,39678,39677,39681,39676,39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,22169,22896,23356,23657,23658,24000,24173,24174,25048,25055,25069,25070,25073,25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,35621,35639,35622,35638,35630,35620,35643,35645,35642,35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,31788,31803,31980,31978,32374,32373,32376,32368,32375,32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,26079,26344,26339,26340,27379,27376,27370,27368,27385,27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,40000,39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,28740,28746,28744,28745,28741,28742,29213,29210,29209,29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,39502,39507,39508,39500,39503,39496,39498,39497,39506,39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,31990,32410,32408,32411,32409,33248,33249,34374,34375,34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,9584,9583,65517,132423,37595,132575,147397,34124,17077,29679,20917,13897,149826,166372,37700,137691,33518,146632,30780,26436,25311,149811,166314,131744,158643,135941,20395,140525,20488,159017,162436,144896,150193,140563,20521,131966,24484,131968,131911,28379,132127,20605,20737,13434,20750,39020,14147,33814,149924,132231,20832,144308,20842,134143,139516,131813,140592,132494,143923,137603,23426,34685,132531,146585,20914,20920,40244,20937,20943,20945,15580,20947,150182,20915,20962,21314,20973,33741,26942,145197,24443,21003,21030,21052,21173,21079,21140,21177,21189,31765,34114,21216,34317,158483,21253,166622,21833,28377,147328,133460,147436,21299,21316,134114,27851,136998,26651,29653,24650,16042,14540,136936,29149,17570,21357,21364,165547,21374,21375,136598,136723,30694,21395,166555,21408,21419,21422,29607,153458,16217,29596,21441,21445,27721,20041,22526,21465,15019,134031,21472,147435,142755,21494,134263,21523,28793,21803,26199,27995,21613,158547,134516,21853,21647,21668,18342,136973,134877,15796,134477,166332,140952,21831,19693,21551,29719,21894,21929,22021,137431,147514,17746,148533,26291,135348,22071,26317,144010,26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,166758,13859,135759,22342,147877,27758,28811,22338,14001,158846,22502,136214,22531,136276,148323,22566,150517,22620,22698,13665,22752,22748,135740,22779,23551,22339,172368,148088,37843,13729,22815,26790,14019,28249,136766,23076,21843,136850,34053,22985,134478,158849,159018,137180,23001,137211,137138,159142,28017,137256,136917,23033,159301,23211,23139,14054,149929,23159,14088,23190,29797,23251,159649,140628,15749,137489,14130,136888,24195,21200,23414,25992,23420,162318,16388,18525,131588,23509,24928,137780,154060,132517,23539,23453,19728,23557,138052,23571,29646,23572,138405,158504,23625,18653,23685,23785,23791,23947,138745,138807,23824,23832,23878,138916,23738,24023,33532,14381,149761,139337,139635,33415,14390,15298,24110,27274,24181,24186,148668,134355,21414,20151,24272,21416,137073,24073,24308,164994,24313,24315,14496,24316,26686,37915,24333,131521,194708,15070,18606,135994,24378,157832,140240,24408,140401,24419,38845,159342,24434,37696,166454,24487,23990,15711,152144,139114,159992,140904,37334,131742,166441,24625,26245,137335,14691,15815,13881,22416,141236,31089,15936,24734,24740,24755,149890,149903,162387,29860,20705,23200,24932,33828,24898,194726,159442,24961,20980,132694,24967,23466,147383,141407,25043,166813,170333,25040,14642,141696,141505,24611,24924,25886,25483,131352,25285,137072,25301,142861,25452,149983,14871,25656,25592,136078,137212,25744,28554,142902,38932,147596,153373,25825,25829,38011,14950,25658,14935,25933,28438,150056,150051,25989,25965,25951,143486,26037,149824,19255,26065,16600,137257,26080,26083,24543,144384,26136,143863,143864,26180,143780,143781,26187,134773,26215,152038,26227,26228,138813,143921,165364,143816,152339,30661,141559,39332,26370,148380,150049,15147,27130,145346,26462,26471,26466,147917,168173,26583,17641,26658,28240,37436,26625,144358,159136,26717,144495,27105,27147,166623,26995,26819,144845,26881,26880,15666,14849,144956,15232,26540,26977,166474,17148,26934,27032,15265,132041,33635,20624,27129,144985,139562,27205,145155,27293,15347,26545,27336,168348,15373,27421,133411,24798,27445,27508,141261,28341,146139,132021,137560,14144,21537,146266,27617,147196,27612,27703,140427,149745,158545,27738,33318,27769,146876,17605,146877,147876,149772,149760,146633,14053,15595,134450,39811,143865,140433,32655,26679,159013,159137,159211,28054,27996,28284,28420,149887,147589,159346,34099,159604,20935,27804,28189,33838,166689,28207,146991,29779,147330,31180,28239,23185,143435,28664,14093,28573,146992,28410,136343,147517,17749,37872,28484,28508,15694,28532,168304,15675,28575,147780,28627,147601,147797,147513,147440,147380,147775,20959,147798,147799,147776,156125,28747,28798,28839,28801,28876,28885,28886,28895,16644,15848,29108,29078,148087,28971,28997,23176,29002,29038,23708,148325,29007,37730,148161,28972,148570,150055,150050,29114,166888,28861,29198,37954,29205,22801,37955,29220,37697,153093,29230,29248,149876,26813,29269,29271,15957,143428,26637,28477,29314,29482,29483,149539,165931,18669,165892,29480,29486,29647,29610,134202,158254,29641,29769,147938,136935,150052,26147,14021,149943,149901,150011,29687,29717,26883,150054,29753,132547,16087,29788,141485,29792,167602,29767,29668,29814,33721,29804,14128,29812,37873,27180,29826,18771,150156,147807,150137,166799,23366,166915,137374,29896,137608,29966,29929,29982,167641,137803,23511,167596,37765,30029,30026,30055,30062,151426,16132,150803,30094,29789,30110,30132,30210,30252,30289,30287,30319,30326,156661,30352,33263,14328,157969,157966,30369,30373,30391,30412,159647,33890,151709,151933,138780,30494,30502,30528,25775,152096,30552,144044,30639,166244,166248,136897,30708,30729,136054,150034,26826,30895,30919,30931,38565,31022,153056,30935,31028,30897,161292,36792,34948,166699,155779,140828,31110,35072,26882,31104,153687,31133,162617,31036,31145,28202,160038,16040,31174,168205,31188],"euc-kr":[44034,44035,44037,44038,44043,44044,44045,44046,44047,44056,44062,44063,44065,44066,44067,44069,44070,44071,44072,44073,44074,44075,44078,44082,44083,44084,null,null,null,null,null,null,44085,44086,44087,44090,44091,44093,44094,44095,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44108,44110,44111,44112,44113,44114,44115,44117,null,null,null,null,null,null,44118,44119,44121,44122,44123,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44146,44147,44149,44150,44153,44155,44156,44157,44158,44159,44162,44167,44168,44173,44174,44175,44177,44178,44179,44181,44182,44183,44184,44185,44186,44187,44190,44194,44195,44196,44197,44198,44199,44203,44205,44206,44209,44210,44211,44212,44213,44214,44215,44218,44222,44223,44224,44226,44227,44229,44230,44231,44233,44234,44235,44237,44238,44239,44240,44241,44242,44243,44244,44246,44248,44249,44250,44251,44252,44253,44254,44255,44258,44259,44261,44262,44265,44267,44269,44270,44274,44276,44279,44280,44281,44282,44283,44286,44287,44289,44290,44291,44293,44295,44296,44297,44298,44299,44302,44304,44306,44307,44308,44309,44310,44311,44313,44314,44315,44317,44318,44319,44321,44322,44323,44324,44325,44326,44327,44328,44330,44331,44334,44335,44336,44337,44338,44339,null,null,null,null,null,null,44342,44343,44345,44346,44347,44349,44350,44351,44352,44353,44354,44355,44358,44360,44362,44363,44364,44365,44366,44367,44369,44370,44371,44373,44374,44375,null,null,null,null,null,null,44377,44378,44379,44380,44381,44382,44383,44384,44386,44388,44389,44390,44391,44392,44393,44394,44395,44398,44399,44401,44402,44407,44408,44409,44410,44414,44416,44419,44420,44421,44422,44423,44426,44427,44429,44430,44431,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44446,44447,44448,44449,44450,44451,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44472,44473,44474,44475,44476,44477,44478,44479,44482,44483,44485,44486,44487,44489,44490,44491,44492,44493,44494,44495,44498,44500,44501,44502,44503,44504,44505,44506,44507,44509,44510,44511,44513,44514,44515,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44538,44539,44541,44542,44546,44547,44548,44549,44550,44551,44554,44556,44558,44559,44560,44561,44562,44563,44565,44566,44567,44568,44569,44570,44571,44572,null,null,null,null,null,null,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44594,44595,44597,44598,44601,44603,44604,null,null,null,null,null,null,44605,44606,44607,44610,44612,44615,44616,44617,44619,44623,44625,44626,44627,44629,44631,44632,44633,44634,44635,44638,44642,44643,44644,44646,44647,44650,44651,44653,44654,44655,44657,44658,44659,44660,44661,44662,44663,44666,44670,44671,44672,44673,44674,44675,44678,44679,44680,44681,44682,44683,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44735,44737,44738,44739,44741,44742,44743,44744,44745,44746,44747,44750,44754,44755,44756,44757,44758,44759,44762,44763,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44777,44778,44780,44782,44783,44784,44785,44786,44787,44789,44790,44791,44793,44794,44795,44797,44798,44799,44800,44801,44802,44803,44804,44805,null,null,null,null,null,null,44806,44809,44810,44811,44812,44814,44815,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,null,null,null,null,null,null,44836,44837,44838,44839,44840,44841,44842,44843,44846,44847,44849,44851,44853,44854,44855,44856,44857,44858,44859,44862,44864,44868,44869,44870,44871,44874,44875,44876,44877,44878,44879,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44894,44895,44896,44897,44898,44899,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44922,44923,44924,44925,44926,44927,44929,44930,44931,44933,44934,44935,44937,44938,44939,44940,44941,44942,44943,44946,44947,44948,44950,44951,44952,44953,44954,44955,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44986,44987,44989,44990,44991,44993,44994,44995,44996,44997,44998,45002,45004,45007,45008,45009,45010,45011,45013,45014,45015,45016,45017,45018,45019,45021,45022,45023,45024,45025,null,null,null,null,null,null,45026,45027,45028,45029,45030,45031,45034,45035,45036,45037,45038,45039,45042,45043,45045,45046,45047,45049,45050,45051,45052,45053,45054,45055,45058,45059,null,null,null,null,null,null,45061,45062,45063,45064,45065,45066,45067,45069,45070,45071,45073,45074,45075,45077,45078,45079,45080,45081,45082,45083,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45126,45127,45129,45131,45133,45135,45136,45137,45138,45142,45144,45146,45147,45148,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45182,45183,45185,45186,45187,45189,45190,45191,45192,45193,45194,45195,45198,45200,45202,45203,45204,45205,45206,45207,45211,45213,45214,45219,45220,45221,45222,45223,45226,45232,45234,45238,45239,45241,45242,45243,45245,45246,45247,45248,45249,45250,45251,45254,45258,45259,45260,45261,45262,45263,45266,null,null,null,null,null,null,45267,45269,45270,45271,45273,45274,45275,45276,45277,45278,45279,45281,45282,45283,45284,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,null,null,null,null,null,null,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45322,45325,45326,45327,45329,45332,45333,45334,45335,45338,45342,45343,45344,45345,45346,45350,45351,45353,45354,45355,45357,45358,45359,45360,45361,45362,45363,45366,45370,45371,45372,45373,45374,45375,45378,45379,45381,45382,45383,45385,45386,45387,45388,45389,45390,45391,45394,45395,45398,45399,45401,45402,45403,45405,45406,45407,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45434,45435,45437,45438,45439,45441,45443,45444,45445,45446,45447,45450,45452,45454,45455,45456,45457,45461,45462,45463,45465,45466,45467,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,null,null,null,null,null,null,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45517,45518,45519,45521,45522,45523,45525,null,null,null,null,null,null,45526,45527,45528,45529,45530,45531,45534,45536,45537,45538,45539,45540,45541,45542,45543,45546,45547,45549,45550,45551,45553,45554,45555,45556,45557,45558,45559,45560,45562,45564,45566,45567,45568,45569,45570,45571,45574,45575,45577,45578,45581,45582,45583,45584,45585,45586,45587,45590,45592,45594,45595,45596,45597,45598,45599,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45621,45622,45623,45624,45625,45626,45627,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45657,45658,45659,45661,45662,45663,45665,45666,45667,45668,45669,45670,45671,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45686,45687,45688,45689,45690,45691,45693,45694,45695,45696,45697,45698,45699,45702,45703,45704,45706,45707,45708,45709,45710,null,null,null,null,null,null,45711,45714,45715,45717,45718,45719,45723,45724,45725,45726,45727,45730,45732,45735,45736,45737,45739,45741,45742,45743,45745,45746,45747,45749,45750,45751,null,null,null,null,null,null,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45770,45771,45773,45774,45775,45777,45779,45780,45781,45782,45783,45786,45788,45790,45791,45792,45793,45795,45799,45801,45802,45808,45809,45810,45814,45820,45821,45822,45826,45827,45829,45830,45831,45833,45834,45835,45836,45837,45838,45839,45842,45846,45847,45848,45849,45850,45851,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45911,45913,45914,45917,45920,45921,45922,45923,45926,45928,45930,45932,45933,45935,45938,45939,45941,45942,45943,45945,45946,45947,45948,45949,45950,45951,45954,45958,45959,45960,45961,45962,45963,45965,null,null,null,null,null,null,45966,45967,45969,45970,45971,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45986,45987,45988,45989,45990,45991,45993,45994,45995,45997,null,null,null,null,null,null,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46022,46023,46025,46026,46029,46031,46033,46034,46035,46038,46040,46042,46044,46046,46047,46049,46050,46051,46053,46054,46055,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46097,46098,46099,46100,46101,46102,46103,46105,46106,46107,46109,46110,46111,46113,46114,46115,46116,46117,46118,46119,46122,46124,46125,46126,46127,46128,46129,46130,46131,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46162,46163,46165,46166,46167,46169,46170,46171,46172,46173,46174,46175,46178,46180,46182,null,null,null,null,null,null,46183,46184,46185,46186,46187,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46209,46210,null,null,null,null,null,null,46211,46212,46213,46214,46215,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46238,46239,46240,46241,46242,46243,46245,46246,46247,46249,46250,46251,46253,46254,46255,46256,46257,46258,46259,46260,46262,46264,46266,46267,46268,46269,46270,46271,46273,46274,46275,46277,46278,46279,46281,46282,46283,46284,46285,46286,46287,46289,46290,46291,46292,46294,46295,46296,46297,46298,46299,46302,46303,46305,46306,46309,46311,46312,46313,46314,46315,46318,46320,46322,46323,46324,46325,46326,46327,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46358,46359,46361,46362,46365,46366,46367,46368,46369,46370,46371,46374,46379,46380,46381,46382,46383,46386,46387,46389,46390,46391,46393,46394,46395,46396,46397,46398,46399,46402,46406,null,null,null,null,null,null,46407,46408,46409,46410,46414,46415,46417,46418,46419,46421,46422,46423,46424,46425,46426,46427,46430,46434,46435,46436,46437,46438,46439,46440,46441,46442,null,null,null,null,null,null,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46498,46499,46501,46502,46503,46505,46508,46509,46510,46511,46514,46518,46519,46520,46521,46522,46526,46527,46529,46530,46531,46533,46534,46535,46536,46537,46538,46539,46542,46546,46547,46548,46549,46550,46551,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46610,46611,46613,46614,46615,46617,46618,46619,46620,46621,null,null,null,null,null,null,46622,46623,46624,46625,46626,46627,46628,46630,46631,46632,46633,46634,46635,46637,46638,46639,46640,46641,46642,46643,46645,46646,46647,46648,46649,46650,null,null,null,null,null,null,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46693,46694,46695,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46750,46751,46753,46754,46755,46757,46758,46759,46760,46761,46762,46765,46766,46767,46768,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46805,46806,46807,46808,46809,46810,46811,46812,46813,null,null,null,null,null,null,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46833,46834,46835,46837,46838,46839,46841,46842,null,null,null,null,null,null,46843,46844,46845,46846,46847,46850,46851,46852,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46890,46891,46893,46894,46897,46898,46899,46900,46901,46902,46903,46906,46908,46909,46910,46911,46912,46913,46914,46915,46917,46918,46919,46921,46922,46923,46925,46926,46927,46928,46929,46930,46931,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46945,46946,46947,46949,46950,46951,46953,46954,46955,46956,46957,46958,46959,46962,46964,46966,46967,46968,46969,46970,46971,46974,46975,46977,46978,46979,46981,46982,46983,46984,46985,46986,46987,46990,46995,46996,46997,47002,47003,47005,47006,47007,47009,47010,47011,47012,47013,47014,47015,47018,47022,47023,47024,47025,47026,47027,47030,47031,47033,47034,47035,47036,47037,47038,47039,47040,47041,null,null,null,null,null,null,47042,47043,47044,47045,47046,47048,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,null,null,null,null,null,null,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47086,47087,47089,47090,47091,47093,47094,47095,47096,47097,47098,47099,47102,47106,47107,47108,47109,47110,47114,47115,47117,47118,47119,47121,47122,47123,47124,47125,47126,47127,47130,47132,47134,47135,47136,47137,47138,47139,47142,47143,47145,47146,47147,47149,47150,47151,47152,47153,47154,47155,47158,47162,47163,47164,47165,47166,47167,47169,47170,47171,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47186,47188,47189,47190,47191,47192,47193,47194,47195,47198,47199,47201,47202,47203,47205,47206,47207,47208,47209,47210,47211,47214,47216,47218,47219,47220,47221,47222,47223,47225,47226,47227,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,null,null,null,null,null,null,47264,47265,47266,47267,47268,47269,47270,47271,47273,47274,47275,47276,47277,47278,47279,47281,47282,47283,47285,47286,47287,47289,47290,47291,47292,47293,null,null,null,null,null,null,47294,47295,47298,47300,47302,47303,47304,47305,47306,47307,47309,47310,47311,47313,47314,47315,47317,47318,47319,47320,47321,47322,47323,47324,47326,47328,47330,47331,47332,47333,47334,47335,47338,47339,47341,47342,47343,47345,47346,47347,47348,47349,47350,47351,47354,47356,47358,47359,47360,47361,47362,47363,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47385,47386,47387,47388,47389,47390,47391,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47422,47423,47425,47426,47427,47429,47430,47431,47432,47433,47434,47435,47437,47438,47440,47442,47443,47444,47445,47446,47447,47450,47451,47453,47454,47455,47457,47458,47459,47460,47461,47462,47463,47466,47468,47470,47471,47472,47473,47474,47475,47478,47479,47481,47482,47483,47485,null,null,null,null,null,null,47486,47487,47488,47489,47490,47491,47494,47496,47499,47500,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,null,null,null,null,null,null,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47534,47535,47537,47538,47539,47541,47542,47543,47544,47545,47546,47547,47550,47552,47554,47555,47556,47557,47558,47559,47562,47563,47565,47571,47572,47573,47574,47575,47578,47580,47583,47584,47586,47590,47591,47593,47594,47595,47597,47598,47599,47600,47601,47602,47603,47606,47611,47612,47613,47614,47615,47618,47619,47620,47621,47622,47623,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47674,47675,47677,47678,47679,47681,47683,47684,47685,47686,47687,47690,47692,47695,47696,47697,47698,47702,47703,47705,47706,47707,47709,47710,47711,47712,47713,47714,47715,47718,47722,47723,47724,47725,47726,47727,null,null,null,null,null,null,47730,47731,47733,47734,47735,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47750,47752,47753,47754,47755,47757,47758,47759,47760,47761,47762,null,null,null,null,null,null,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47786,47789,47790,47791,47793,47795,47796,47797,47798,47799,47802,47804,47806,47807,47808,47809,47810,47811,47813,47814,47815,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47869,47870,47871,47873,47874,47875,47877,47878,47879,47880,47881,47882,47883,47884,47886,47888,47890,47891,47892,47893,47894,47895,47897,47898,47899,47901,47902,47903,47905,47906,47907,47908,47909,47910,47911,47912,47914,47916,47917,47918,47919,47920,47921,47922,47923,47927,47929,47930,47935,47936,47937,47938,47939,47942,47944,47946,47947,47948,47950,47953,47954,null,null,null,null,null,null,47955,47957,47958,47959,47961,47962,47963,47964,47965,47966,47967,47968,47970,47972,47973,47974,47975,47976,47977,47978,47979,47981,47982,47983,47984,47985,null,null,null,null,null,null,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48009,48010,48011,48013,48014,48015,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48037,48038,48039,48041,48042,48043,48045,48046,48047,48048,48049,48050,48051,48053,48054,48056,48057,48058,48059,48060,48061,48062,48063,48065,48066,48067,48069,48070,48071,48073,48074,48075,48076,48077,48078,48079,48081,48082,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48122,48123,48125,48126,48129,48131,48132,48133,48134,48135,48138,48142,48144,48146,48147,48153,48154,48160,48161,48162,48163,48166,48168,48170,48171,48172,48174,48175,48178,48179,48181,null,null,null,null,null,null,48182,48183,48185,48186,48187,48188,48189,48190,48191,48194,48198,48199,48200,48202,48203,48206,48207,48209,48210,48211,48212,48213,48214,48215,48216,48217,null,null,null,null,null,null,48218,48219,48220,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48262,48263,48265,48266,48269,48271,48272,48273,48274,48275,48278,48280,48283,48284,48285,48286,48287,48290,48291,48293,48294,48297,48298,48299,48300,48301,48302,48303,48306,48310,48311,48312,48313,48314,48315,48318,48319,48321,48322,48323,48325,48326,48327,48328,48329,48330,48331,48332,48334,48338,48339,48340,48342,48343,48345,48346,48347,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48375,48377,48378,48379,48381,48382,48383,48384,48385,48386,48387,48390,48392,48394,48395,48396,48397,48398,48399,48401,48402,48403,48405,48406,48407,48408,48409,48410,48411,48412,48413,null,null,null,null,null,null,48414,48415,48416,48417,48418,48419,48421,48422,48423,48424,48425,48426,48427,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,null,null,null,null,null,null,48442,48443,48444,48445,48446,48447,48449,48450,48451,48452,48453,48454,48455,48458,48459,48461,48462,48463,48465,48466,48467,48468,48469,48470,48471,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48485,48486,48487,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48514,48515,48517,48518,48523,48524,48525,48526,48527,48530,48532,48534,48535,48536,48539,48541,48542,48543,48544,48545,48546,48547,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48561,48562,48563,48564,48565,48566,48567,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48598,48599,48601,48602,48603,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48618,48619,48620,48621,48622,48623,48625,null,null,null,null,null,null,48626,48627,48629,48630,48631,48633,48634,48635,48636,48637,48638,48639,48641,48642,48644,48646,48647,48648,48649,48650,48651,48654,48655,48657,48658,48659,null,null,null,null,null,null,48661,48662,48663,48664,48665,48666,48667,48670,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48710,48711,48713,48714,48715,48717,48719,48720,48721,48722,48723,48726,48728,48732,48733,48734,48735,48738,48739,48741,48742,48743,48745,48747,48748,48749,48750,48751,48754,48758,48759,48760,48761,48762,48766,48767,48769,48770,48771,48773,48774,48775,48776,48777,48778,48779,48782,48786,48787,48788,48789,48790,48791,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48850,48851,null,null,null,null,null,null,48853,48854,48857,48858,48859,48860,48861,48862,48863,48865,48866,48870,48871,48872,48873,48874,48875,48877,48878,48879,48880,48881,48882,48883,48884,48885,null,null,null,null,null,null,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48898,48899,48900,48901,48902,48903,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48922,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48962,48963,48965,48966,48967,48969,48970,48971,48972,48973,48974,48975,48978,48979,48980,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49045,49046,49047,49048,49049,49050,49051,49052,49053,null,null,null,null,null,null,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49073,49074,49075,49076,49077,49078,49079,49080,null,null,null,null,null,null,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49094,49095,49096,49097,49098,49099,49102,49103,49105,49106,49107,49109,49110,49111,49112,49113,49114,49115,49117,49118,49120,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49234,49235,49236,49237,49238,49239,49241,49242,49243,null,null,null,null,null,null,49245,49246,49247,49249,49250,49251,49252,49253,49254,49255,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,null,null,null,null,null,null,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49298,49299,49301,49302,49303,49305,49306,49307,49308,49309,49310,49311,49314,49316,49318,49319,49320,49321,49322,49323,49326,49329,49330,49335,49336,49337,49338,49339,49342,49346,49347,49348,49350,49351,49354,49355,49357,49358,49359,49361,49362,49363,49364,49365,49366,49367,49370,49374,49375,49376,49377,49378,49379,49382,49383,49385,49386,49387,49389,49390,49391,49392,49393,49394,49395,49398,49400,49402,49403,49404,49405,49406,49407,49409,49410,49411,49413,49414,49415,49417,49418,49419,49420,49421,49422,49423,49425,49426,49427,49428,49430,49431,49432,49433,49434,49435,49441,49442,49445,49448,49449,49450,49451,49454,49458,49459,49460,49461,49463,49466,49467,49469,49470,49471,49473,49474,49475,49476,49477,49478,49479,49482,49486,49487,49488,49489,49490,49491,49494,49495,null,null,null,null,null,null,49497,49498,49499,49501,49502,49503,49504,49505,49506,49507,49510,49514,49515,49516,49517,49518,49519,49521,49522,49523,49525,49526,49527,49529,49530,49531,null,null,null,null,null,null,49532,49533,49534,49535,49536,49537,49538,49539,49540,49542,49543,49544,49545,49546,49547,49551,49553,49554,49555,49557,49559,49560,49561,49562,49563,49566,49568,49570,49571,49572,49574,49575,49578,49579,49581,49582,49583,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49598,49599,49600,49601,49602,49603,49605,49606,49607,49609,49610,49611,49613,49614,49615,49616,49617,49618,49619,49621,49622,49625,49626,49627,49628,49629,49630,49631,49633,49634,49635,49637,49638,49639,49641,49642,49643,49644,49645,49646,49647,49650,49652,49653,49654,49655,49656,49657,49658,49659,49662,49663,49665,49666,49667,49669,49670,49671,49672,49673,49674,49675,49678,49680,49682,49683,49684,49685,49686,49687,49690,49691,49693,49694,49697,49698,49699,49700,49701,49702,49703,49706,49708,49710,49712,49715,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,null,null,null,null,null,null,49734,49735,49737,49738,49739,49740,49741,49742,49743,49746,49747,49749,49750,49751,49753,49754,49755,49756,49757,49758,49759,49761,49762,49763,49764,49766,null,null,null,null,null,null,49767,49768,49769,49770,49771,49774,49775,49777,49778,49779,49781,49782,49783,49784,49785,49786,49787,49790,49792,49794,49795,49796,49797,49798,49799,49802,49803,49804,49805,49806,49807,49809,49810,49811,49812,49813,49814,49815,49817,49818,49820,49822,49823,49824,49825,49826,49827,49830,49831,49833,49834,49835,49838,49839,49840,49841,49842,49843,49846,49848,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49886,49887,49889,49890,49893,49894,49895,49896,49897,49898,49902,49904,49906,49907,49908,49909,49911,49914,49917,49918,49919,49921,49922,49923,49924,49925,49926,49927,49930,49931,49934,49935,49936,49937,49938,49942,49943,49945,49946,49947,49949,49950,49951,49952,49953,49954,49955,49958,49959,49962,49963,49964,49965,49966,49967,49968,49969,49970,null,null,null,null,null,null,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49990,49991,49992,49993,49994,49995,49996,49997,null,null,null,null,null,null,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50026,50027,50029,50030,50031,50033,50035,50036,50037,50038,50039,50042,50043,50046,50047,50048,50049,50050,50051,50053,50054,50055,50057,50058,50059,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50138,50139,50141,50142,50145,50147,50148,50149,50150,50151,50154,50155,50156,50158,50159,50160,50161,50162,50163,50166,50167,50169,50170,50171,50172,50173,50174,null,null,null,null,null,null,50175,50176,50177,50178,50179,50180,50181,50182,50183,50185,50186,50187,50188,50189,50190,50191,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,null,null,null,null,null,null,50203,50204,50205,50206,50207,50208,50209,50210,50211,50213,50214,50215,50216,50217,50218,50219,50221,50222,50223,50225,50226,50227,50229,50230,50231,50232,50233,50234,50235,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50278,50279,50281,50282,50283,50285,50286,50287,50288,50289,50290,50291,50294,50295,50296,50298,50299,50300,50301,50302,50303,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50325,50326,50327,50328,50329,50330,50331,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50361,50362,50363,50365,50366,50367,50368,50369,50370,50371,50372,50373,null,null,null,null,null,null,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,null,null,null,null,null,null,50400,50401,50402,50403,50404,50405,50406,50407,50408,50410,50411,50412,50413,50414,50415,50418,50419,50421,50422,50423,50425,50427,50428,50429,50430,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50445,50446,50447,50449,50450,50451,50453,50454,50455,50456,50457,50458,50459,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50474,50475,50477,50478,50479,50481,50482,50483,50484,50485,50486,50487,50490,50492,50494,50495,50496,50497,50498,50499,50502,50503,50507,50511,50512,50513,50514,50518,50522,50523,50524,50527,50530,50531,50533,50534,50535,50537,50538,50539,50540,50541,50542,50543,50546,50550,50551,50552,50553,50554,50555,50558,50559,50561,50562,50563,50565,50566,50568,50569,50570,50571,50574,50576,50578,50579,50580,50582,50585,50586,50587,50589,50590,50591,50593,50594,50595,50596,50597,50598,50599,50600,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50614,null,null,null,null,null,null,50615,50618,50623,50624,50625,50626,50627,50635,50637,50639,50642,50643,50645,50646,50647,50649,50650,50651,50652,50653,50654,50655,50658,50660,50662,50663,null,null,null,null,null,null,50664,50665,50666,50667,50671,50673,50674,50675,50677,50680,50681,50682,50683,50690,50691,50692,50697,50698,50699,50701,50702,50703,50705,50706,50707,50708,50709,50710,50711,50714,50717,50718,50719,50720,50721,50722,50723,50726,50727,50729,50730,50731,50735,50737,50738,50742,50744,50746,50748,50749,50750,50751,50754,50755,50757,50758,50759,50761,50762,50763,50764,50765,50766,50767,50770,50774,50775,50776,50777,50778,50779,50782,50783,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50797,50798,50800,50802,50803,50804,50805,50806,50807,50810,50811,50813,50814,50815,50817,50818,50819,50820,50821,50822,50823,50826,50828,50830,50831,50832,50833,50834,50835,50838,50839,50841,50842,50843,50845,50846,50847,50848,50849,50850,50851,50854,50856,50858,50859,50860,50861,50862,50863,50866,50867,50869,50870,50871,50875,50876,50877,50878,50879,50882,50884,50886,50887,50888,50889,50890,50891,50894,null,null,null,null,null,null,50895,50897,50898,50899,50901,50902,50903,50904,50905,50906,50907,50910,50911,50914,50915,50916,50917,50918,50919,50922,50923,50925,50926,50927,50929,50930,null,null,null,null,null,null,50931,50932,50933,50934,50935,50938,50939,50940,50942,50943,50944,50945,50946,50947,50950,50951,50953,50954,50955,50957,50958,50959,50960,50961,50962,50963,50966,50968,50970,50971,50972,50973,50974,50975,50978,50979,50981,50982,50983,50985,50986,50987,50988,50989,50990,50991,50994,50996,50998,51000,51001,51002,51003,51006,51007,51009,51010,51011,51013,51014,51015,51016,51017,51019,51022,51024,51033,51034,51035,51037,51038,51039,51041,51042,51043,51044,51045,51046,51047,51049,51050,51052,51053,51054,51055,51056,51057,51058,51059,51062,51063,51065,51066,51067,51071,51072,51073,51074,51078,51083,51084,51085,51087,51090,51091,51093,51097,51099,51100,51101,51102,51103,51106,51111,51112,51113,51114,51115,51118,51119,51121,51122,51123,51125,51126,51127,51128,51129,51130,51131,51134,51138,51139,51140,51141,51142,51143,51146,51147,51149,51151,51153,51154,51155,51156,51157,51158,51159,51161,51162,51163,51164,null,null,null,null,null,null,51166,51167,51168,51169,51170,51171,51173,51174,51175,51177,51178,51179,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,null,null,null,null,null,null,51195,51196,51197,51198,51199,51202,51203,51205,51206,51207,51209,51211,51212,51213,51214,51215,51218,51220,51223,51224,51225,51226,51227,51230,51231,51233,51234,51235,51237,51238,51239,51240,51241,51242,51243,51246,51248,51250,51251,51252,51253,51254,51255,51257,51258,51259,51261,51262,51263,51265,51266,51267,51268,51269,51270,51271,51274,51275,51278,51279,51280,51281,51282,51283,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51314,51315,51317,51318,51319,51321,51323,51324,51325,51326,51327,51330,51332,51336,51337,51338,51342,51343,51344,51345,51346,51347,51349,51350,51351,51352,51353,51354,51355,51356,51358,51360,51362,51363,51364,51365,51366,51367,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51390,51391,51392,51393,null,null,null,null,null,null,51394,51395,51397,51398,51399,51401,51402,51403,51405,51406,51407,51408,51409,51410,51411,51414,51416,51418,51419,51420,51421,51422,51423,51426,51427,51429,null,null,null,null,null,null,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51446,51447,51448,51449,51450,51451,51454,51455,51457,51458,51459,51463,51464,51465,51466,51467,51470,12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,8835,8746,8745,8743,8744,65506,51472,51474,51475,51476,51477,51478,51479,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,null,null,null,null,null,null,51501,51502,51503,51504,51505,51506,51507,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,null,null,null,null,null,null,51528,51529,51530,51531,51532,51533,51534,51535,51538,51539,51541,51542,51543,51545,51546,51547,51548,51549,51550,51551,51554,51556,51557,51558,51559,51560,51561,51562,51563,51565,51566,51567,8658,8660,8704,8707,180,65374,711,728,733,730,729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51569,51570,51571,51573,51574,51575,51576,51577,51578,51579,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51594,51595,51597,51598,51599,null,null,null,null,null,null,51601,51602,51603,51604,51605,51606,51607,51610,51612,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,null,null,null,null,null,null,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51650,51651,51653,51654,51657,51659,51660,51661,51662,51663,51666,51668,51671,51672,51675,65281,65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,51678,51679,51681,51683,51685,51686,51688,51689,51690,51691,51694,51698,51699,51700,51701,51702,51703,51706,51707,51709,51710,51711,51713,51714,51715,51716,null,null,null,null,null,null,51717,51718,51719,51722,51726,51727,51728,51729,51730,51731,51733,51734,51735,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,null,null,null,null,null,null,51750,51751,51752,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,51783,51784,51785,51786,51787,51790,51791,51793,51794,51795,51797,51798,51799,51800,51801,51802,51803,51806,51810,51811,51812,51813,51814,51815,51817,51818,null,null,null,null,null,null,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51838,51839,51840,51841,51842,51843,51845,51846,null,null,null,null,null,null,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,null,null,null,null,null,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51902,51903,51905,51906,51907,51909,null,null,null,null,null,null,51910,51911,51912,51913,51914,51915,51918,51920,51922,51924,51925,51926,51927,51930,51931,51932,51933,51934,51935,51937,51938,51939,51940,51941,51942,51943,null,null,null,null,null,null,51944,51945,51946,51947,51949,51950,51951,51952,51953,51954,51955,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51977,51978,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51979,51980,51981,51982,51983,51985,51986,51987,51989,51990,51991,51993,51994,51995,51996,51997,51998,51999,52002,52003,52004,52005,52006,52007,52008,52009,null,null,null,null,null,null,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52034,52035,52036,null,null,null,null,null,null,52037,52038,52039,52042,52043,52045,52046,52047,52049,52050,52051,52052,52053,52054,52055,52058,52059,52060,52062,52063,52064,52065,52066,52067,52069,52070,52071,52072,52073,52074,52075,52076,13205,13206,13207,8467,13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,null,null,null,null,null,null,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52125,52126,52127,52128,52129,52130,52131,null,null,null,null,null,null,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,198,208,170,294,null,306,null,319,321,216,338,186,222,358,330,null,12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,190,8539,8540,8541,8542,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,null,null,null,null,null,null,52192,52193,52194,52195,52197,52198,52200,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,null,null,null,null,null,null,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52238,52239,52241,52242,52243,52245,52246,52247,52248,52249,52250,52251,52254,52255,52256,52259,52260,230,273,240,295,305,307,312,320,322,248,339,223,254,359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,185,178,179,8308,8319,8321,8322,8323,8324,52261,52262,52266,52267,52269,52271,52273,52274,52275,52276,52277,52278,52279,52282,52287,52288,52289,52290,52291,52294,52295,52297,52298,52299,52301,52302,null,null,null,null,null,null,52303,52304,52305,52306,52307,52310,52314,52315,52316,52317,52318,52319,52321,52322,52323,52325,52327,52329,52330,52331,52332,52333,52334,52335,52337,52338,null,null,null,null,null,null,52339,52340,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,52372,52373,52374,52375,52378,52379,52381,52382,52383,52385,52386,52387,52388,52389,52390,52391,52394,52398,52399,52400,52401,52402,52403,52406,52407,52409,null,null,null,null,null,null,52410,52411,52413,52414,52415,52416,52417,52418,52419,52422,52424,52426,52427,52428,52429,52430,52431,52433,52434,52435,52437,52438,52439,52440,52441,52442,null,null,null,null,null,null,52443,52444,52445,52446,52447,52448,52449,52450,52451,52453,52454,52455,52456,52457,52458,52459,52461,52462,52463,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,52478,52479,52480,52482,52483,52484,52485,52486,52487,52490,52491,52493,52494,52495,52497,52498,52499,52500,52501,52502,52503,52506,52508,52510,52511,52512,null,null,null,null,null,null,52513,52514,52515,52517,52518,52519,52521,52522,52523,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52538,52539,52540,52541,52542,null,null,null,null,null,null,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52573,52574,52575,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,52577,52578,52579,52581,52582,52583,52584,52585,52586,52587,52590,52592,52594,52595,52596,52597,52598,52599,52601,52602,52603,52604,52605,52606,52607,52608,null,null,null,null,null,null,52609,52610,52611,52612,52613,52614,52615,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52630,52631,52633,52634,52635,52637,52638,52639,null,null,null,null,null,null,52640,52641,52642,52643,52646,52648,52650,52651,52652,52653,52654,52655,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52677,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52678,52679,52680,52681,52682,52683,52685,52686,52687,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,null,null,null,null,null,null,52706,52707,52708,52709,52710,52711,52713,52714,52715,52717,52718,52719,52721,52722,52723,52724,52725,52726,52727,52730,52732,52734,52735,52736,52737,52738,null,null,null,null,null,null,52739,52741,52742,52743,52745,52746,52747,52749,52750,52751,52752,52753,52754,52755,52757,52758,52759,52760,52762,52763,52764,52765,52766,52767,52770,52771,52773,52774,52775,52777,52778,52779,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52780,52781,52782,52783,52786,52788,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,null,null,null,null,null,null,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52826,52827,52829,52830,52834,52835,52836,52837,52838,52839,52842,52844,null,null,null,null,null,null,52846,52847,52848,52849,52850,52851,52854,52855,52857,52858,52859,52861,52862,52863,52864,52865,52866,52867,52870,52872,52874,52875,52876,52877,52878,52879,52882,52883,52885,52886,52887,52889,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52890,52891,52892,52893,52894,52895,52898,52902,52903,52904,52905,52906,52907,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,null,null,null,null,null,null,52923,52924,52925,52926,52927,52928,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,null,null,null,null,null,null,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52966,52967,52969,52970,52973,52974,52975,52976,52977,52978,52979,52982,52986,52987,52988,52989,52990,52991,44032,44033,44036,44039,44040,44041,44042,44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,44273,44275,44277,44278,44284,44285,44288,44292,44294,52994,52995,52997,52998,52999,53001,53002,53003,53004,53005,53006,53007,53010,53012,53014,53015,53016,53017,53018,53019,53021,53022,53023,53025,53026,53027,null,null,null,null,null,null,53029,53030,53031,53032,53033,53034,53035,53038,53042,53043,53044,53045,53046,53047,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,null,null,null,null,null,null,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53078,53079,53081,53082,53083,53085,53086,53087,53088,53089,53090,53091,53094,53096,53098,53099,53100,44300,44301,44303,44305,44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,53101,53102,53103,53106,53107,53109,53110,53111,53113,53114,53115,53116,53117,53118,53119,53121,53122,53123,53124,53126,53127,53128,53129,53130,53131,53133,null,null,null,null,null,null,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53154,53155,53156,53157,53158,53159,53161,null,null,null,null,null,null,53162,53163,53164,53165,53166,53167,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53189,53190,53191,53192,53193,53194,53195,44665,44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,44945,44949,44956,44984,44985,44988,44992,44999,45000,45001,45003,45005,45006,45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,45143,45145,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53218,53219,53221,53222,53223,53225,null,null,null,null,null,null,53226,53227,53228,53229,53230,53231,53234,53236,53238,53239,53240,53241,53242,53243,53245,53246,53247,53249,53250,53251,53253,53254,53255,53256,53257,53258,null,null,null,null,null,null,53259,53260,53261,53262,53263,53264,53266,53267,53268,53269,53270,53271,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,45516,45520,45524,45532,45533,53294,53295,53296,53297,53298,53299,53302,53303,53305,53306,53307,53309,53310,53311,53312,53313,53314,53315,53318,53320,53322,53323,53324,53325,53326,53327,null,null,null,null,null,null,53329,53330,53331,53333,53334,53335,53337,53338,53339,53340,53341,53342,53343,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53358,53359,null,null,null,null,null,null,53361,53362,53363,53365,53366,53367,53368,53369,53370,53371,53374,53375,53376,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,45535,45544,45545,45548,45552,45561,45563,45565,45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,45910,45912,45915,45916,45918,45919,45924,45925,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53414,53415,53417,53418,53419,53421,53422,53423,53424,53425,53426,null,null,null,null,null,null,53427,53430,53432,53434,53435,53436,53437,53438,53439,53442,53443,53445,53446,53447,53450,53451,53452,53453,53454,53455,53458,53462,53463,53464,53465,53466,null,null,null,null,null,null,53467,53470,53471,53473,53474,53475,53477,53478,53479,53480,53481,53482,53483,53486,53490,53491,53492,53493,53494,53495,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,45927,45929,45931,45934,45936,45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,53509,53510,53511,53512,53513,53514,53515,53516,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,null,null,null,null,null,null,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53554,53555,53557,53558,53559,53561,53563,53564,53565,53566,null,null,null,null,null,null,53567,53570,53574,53575,53576,53577,53578,53579,53582,53583,53585,53586,53587,53589,53590,53591,53592,53593,53594,53595,53598,53600,53602,53603,53604,53605,53606,53607,53609,53610,53611,53613,46400,46401,46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,46999,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53629,53630,53631,53632,53633,53634,53635,53637,53638,53639,53641,53642,null,null,null,null,null,null,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53666,53667,53669,53670,53671,null,null,null,null,null,null,53673,53674,53675,53676,53677,53678,53679,53682,53684,53686,53687,53688,53689,53691,53693,53694,53695,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,47000,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,47452,47456,47464,47465,53712,53713,53714,53715,53716,53717,53718,53719,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,null,null,null,null,null,null,53739,53740,53741,53742,53743,53744,53745,53746,53747,53749,53750,53751,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,null,null,null,null,null,null,53768,53770,53771,53772,53773,53774,53775,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,47467,47469,47476,47477,47480,47484,47492,47493,47495,47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,47803,47805,47812,47816,47832,47833,47868,53802,53803,53806,53807,53809,53810,53811,53813,53814,53815,53816,53817,53818,53819,53822,53824,53826,53827,53828,53829,53830,53831,53833,53834,53835,53836,null,null,null,null,null,null,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53853,53854,53855,53856,53857,53858,53859,53861,53862,53863,53864,null,null,null,null,null,null,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53890,53891,53893,53894,53895,53897,53898,53899,53900,47872,47876,47885,47887,47889,47896,47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,53901,53902,53903,53906,53907,53908,53910,53911,53912,53913,53914,53915,53917,53918,53919,53921,53922,53923,53925,53926,53927,53928,53929,53930,53931,53933,null,null,null,null,null,null,53934,53935,53936,53938,53939,53940,53941,53942,53943,53946,53947,53949,53950,53953,53955,53956,53957,53958,53959,53962,53964,53965,53966,53967,53968,53969,null,null,null,null,null,null,53970,53971,53973,53974,53975,53977,53978,53979,53981,53982,53983,53984,53985,53986,53987,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54002,54003,54005,54006,54007,54009,54010,48281,48282,48288,48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,54011,54012,54013,54014,54015,54018,54020,54022,54023,54024,54025,54026,54027,54031,54033,54034,54035,54037,54039,54040,54041,54042,54043,54046,54050,54051,null,null,null,null,null,null,54052,54054,54055,54058,54059,54061,54062,54063,54065,54066,54067,54068,54069,54070,54071,54074,54078,54079,54080,54081,54082,54083,54086,54087,54088,54089,null,null,null,null,null,null,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,49372,49373,49380,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54142,54143,54145,54146,54147,54149,54150,54151,null,null,null,null,null,null,54152,54153,54154,54155,54158,54162,54163,54164,54165,54166,54167,54170,54171,54173,54174,54175,54177,54178,54179,54180,54181,54182,54183,54186,54188,54190,null,null,null,null,null,null,54191,54192,54193,54194,54195,54197,54198,54199,54201,54202,54203,54205,54206,54207,54208,54209,54210,54211,54214,54215,54218,54219,54220,54221,54222,54223,54225,54226,54227,54228,54229,54230,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,49695,49696,49704,49705,49707,49709,54231,54233,54234,54235,54236,54237,54238,54239,54240,54242,54244,54245,54246,54247,54248,54249,54250,54251,54254,54255,54257,54258,54259,54261,54262,54263,null,null,null,null,null,null,54264,54265,54266,54267,54270,54272,54274,54275,54276,54277,54278,54279,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,null,null,null,null,null,null,54295,54296,54297,54298,54299,54300,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,49711,49713,49714,49716,49736,49744,49745,49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,50157,50164,50165,50168,50184,50192,50212,50220,50224,54328,54329,54330,54331,54332,54333,54334,54335,54337,54338,54339,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,null,null,null,null,null,null,54356,54357,54358,54359,54360,54361,54362,54363,54365,54366,54367,54369,54370,54371,54373,54374,54375,54376,54377,54378,54379,54380,54382,54384,54385,54386,null,null,null,null,null,null,54387,54388,54389,54390,54391,54394,54395,54397,54398,54401,54403,54404,54405,54406,54407,54410,54412,54414,54415,54416,54417,54418,54419,54421,54422,54423,54424,54425,54426,54427,54428,54429,50228,50236,50237,50248,50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,null,null,null,null,null,null,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54477,54478,54479,54481,54482,54483,54485,null,null,null,null,null,null,54486,54487,54488,54489,54490,54491,54493,54494,54496,54497,54498,54499,54500,54501,54502,54503,54505,54506,54507,54509,54510,54511,54513,54514,54515,54516,54517,54518,54519,54521,54522,54524,50640,50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,50913,50920,54526,54527,54528,54529,54530,54531,54533,54534,54535,54537,54538,54539,54541,54542,54543,54544,54545,54546,54547,54550,54552,54553,54554,54555,54556,54557,null,null,null,null,null,null,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,null,null,null,null,null,null,54584,54585,54586,54587,54590,54591,54593,54594,54595,54597,54598,54599,54600,54601,54602,54603,54606,54608,54610,54611,54612,54613,54614,54615,54618,54619,54621,54622,54623,54625,54626,54627,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,51200,51201,51204,51208,51210,54628,54630,54631,54634,54636,54638,54639,54640,54641,54642,54643,54646,54647,54649,54650,54651,54653,54654,54655,54656,54657,54658,54659,54662,54666,54667,null,null,null,null,null,null,54668,54669,54670,54671,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54694,54695,null,null,null,null,null,null,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,51216,51217,51219,51221,51222,51228,51229,51232,51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,51649,51652,51655,51656,51658,51664,51665,51667,54730,54731,54733,54734,54735,54737,54739,54740,54741,54742,54743,54746,54748,54750,54751,54752,54753,54754,54755,54758,54759,54761,54762,54763,54765,54766,null,null,null,null,null,null,54767,54768,54769,54770,54771,54774,54776,54778,54779,54780,54781,54782,54783,54786,54787,54789,54790,54791,54793,54794,54795,54796,54797,54798,54799,54802,null,null,null,null,null,null,54806,54807,54808,54809,54810,54811,54813,54814,54815,54817,54818,54819,54821,54822,54823,54824,54825,54826,54827,54828,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54842,54843,51669,51670,51673,51674,51676,51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,51992,52000,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,54845,54846,54847,54849,54850,54851,54852,54854,54855,54858,54860,54862,54863,54864,54866,54867,54870,54871,54873,54874,54875,54877,54878,54879,54880,54881,null,null,null,null,null,null,54882,54883,54884,54885,54886,54888,54890,54891,54892,54893,54894,54895,54898,54899,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,null,null,null,null,null,null,54913,54914,54916,54918,54919,54920,54921,54922,54923,54926,54927,54929,54930,54931,54933,54934,54935,54936,54937,54938,54939,54940,54942,54944,54946,54947,54948,54949,54950,54951,54953,54954,52284,52285,52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,52789,54955,54957,54958,54959,54961,54962,54963,54964,54965,54966,54967,54968,54970,54972,54973,54974,54975,54976,54977,54978,54979,54982,54983,54985,54986,54987,null,null,null,null,null,null,54989,54990,54991,54992,54994,54995,54997,54998,55000,55002,55003,55004,55005,55006,55007,55009,55010,55011,55013,55014,55015,55017,55018,55019,55020,55021,null,null,null,null,null,null,55022,55023,55025,55026,55027,55028,55030,55031,55032,55033,55034,55035,55038,55039,55041,55042,55043,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55058,55059,55060,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,52984,52985,52992,52993,52996,53000,53008,53009,53011,53013,53020,53024,53028,53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,53300,53301,53304,53308,55061,55062,55063,55066,55067,55069,55070,55071,55073,55074,55075,55076,55077,55078,55079,55082,55084,55086,55087,55088,55089,55090,55091,55094,55095,55097,null,null,null,null,null,null,55098,55099,55101,55102,55103,55104,55105,55106,55107,55109,55110,55112,55114,55115,55116,55117,55118,55119,55122,55123,55125,55130,55131,55132,55133,55134,null,null,null,null,null,null,55135,55138,55140,55142,55143,55144,55146,55147,55149,55150,55151,55153,55154,55155,55157,55158,55159,55160,55161,55162,55163,55166,55167,55168,55170,55171,55172,55173,55174,55175,55178,55179,53316,53317,53319,53321,53328,53332,53336,53344,53356,53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,53812,53820,53821,53823,53825,53832,53852,55181,55182,55183,55185,55186,55187,55188,55189,55190,55191,55194,55196,55198,55199,55200,55201,55202,55203,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,53860,53888,53889,53892,53896,53904,53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,53960,53961,53963,53972,53976,53980,53988,53989,54000,54001,54004,54008,54016,54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54280,54301,54336,54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,55193,55195,55197,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20285,20339,20551,20729,21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21283,23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,21138,27298,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,23622,24760,25106,26690,26800,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26856,28330,30028,30328,30926,31293,31995,32363,32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,34467,36002,38799,20018,23521,25096,26524,29916,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31185,33747,35463,35506,36328,36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21312,21475,21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,36020,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,24524,25216,26071,26083,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26398,26399,26462,26827,26820,27231,27450,27683,27773,27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,31048,31098,31637,32000,32186,32648,32774,32813,32908,35352,35663,35912,36215,37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,26976,28275,63778,30007,63779,63780,63781,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32013,63782,63783,34930,22218,23064,63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20025,20150,20294,21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,63835,30313,32645,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,36706,38722,24976,25088,25891,28451,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29001,29833,32244,32879,34030,36646,36899,37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,20698,23534,24278,26009,29134,30274,30637,32842,34044,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36988,39719,40845,22744,23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31435,31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,33180,33707,37000,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,40629,28357,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,20497,21006,21563,21839,25991,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27766,32010,32011,32862,34442,38272,38639,21247,27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,36820,38930,39151,21187,25300,25765,28196,28497,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30332,36299,37297,37474,39662,39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30887,34327,38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,23142,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,31807,32566,33104,33105,33178,33344,33433,33705,35331,36000,36070,36091,36212,36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26000,26503,27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,31875,32203,32737,32933,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,33086,33218,33778,34586,35048,35513,35692,36027,37145,38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,39164,39391,40605,21066,63849,26388,63850,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20632,21034,23665,25955,27733,29642,29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32997,33298,34223,35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,23744,24101,24833,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,25100,34899,36848,37477,23815,23847,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23913,29791,33181,34664,28629,25342,32722,35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,36805,22833,23460,23526,24713,23529,23563,24515,27777,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63858,28145,28683,29978,33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27387,32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,22914,63874,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,28814,28976,29744,33398,33490,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63910,38331,39653,40573,26308,63911,29121,33865,63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,63924,20034,20522,63925,21000,21473,26355,27757,28618,29450,30591,31330,33454,34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,63929,25034,25942,26111,26212,26791,27738,28595,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28879,29100,29522,31613,34568,35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31368,31407,32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,34131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,29232,29503,29783,33489,34945,36677,36960,63942,38498,39000,40219,26376,36234,37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,27943,63946,28216,63947,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28641,29494,29495,63948,29788,30001,63949,30290,63950,63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,30691,32681,33380,34191,34811,34915,35516,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,35696,37291,20108,20197,20234,63965,63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63991,63992,63993,20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,27583,27656,28593,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29006,29728,30000,30008,30033,30322,31564,31627,31661,31686,32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,37336,37478,37580,37664,38662,38742,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38748,38914,40718,21046,21137,21884,22564,24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,24939,26837,28121,29742,31278,32066,32156,32305,33131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36394,36405,37758,37912,20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21675,22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,32221,36655,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,37319,37365,20874,26613,31574,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36012,20932,22971,24765,34389,20508,63999,21076,23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,33729,35531,38737,39894,64000,21059,26367,28053,28399,32224,35558,36910,36958,39636,21021,21119,21736,24980,25220,25307,26786,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26898,26970,27189,28818,28966,30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,22684,25277,25512,26894,27000,27166,28267,30394,31179,33467,33833,35535,36264,36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36101,21462,21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,35351,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,29923,36009,36774,37393,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38442,20843,21485,25420,20329,21764,24726,25943,27803,28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,29922,31080,34920,35961,39111,39108,39491,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21697,31263,26963,35575,35914,39080,39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,64008,64009,38917,20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,27194,28779,30069,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,25928,25989,26313,26783,28045,28102,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29243,32948,37237,39501,20399,20505,21402,21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,26342,29081,29113,29114,29351,31143,31232,32690,35440,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"gb18030":[19970,19972,19973,19974,19983,19986,19991,19999,20000,20001,20003,20006,20009,20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,21979,21982,21984,21986,21991,21993,21997,21998,22000,22001,22004,22006,22008,22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24006,24007,24008,24009,24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28998,28999,29000,29001,29003,29005,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,58850,58851,58852,12288,65281,65282,65283,65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,234,593,7743,324,328,505,609,59337,59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,27686,20133,23475,39559,37219,25000,37039,38889,21547,28085,23506,20989,21898,32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,30000,29980,24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,34996,34997,34998,35000,35001,35002,35003,35005,35006,35007,35008,35011,35012,35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,21310,36188,21350,21347,20994,21000,21006,21037,21043,21055,21056,21068,21086,21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34000,34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,28049,28015,28062,28064,27998,28051,28052,27996,28000,28028,28003,28186,28103,28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,26297,36980,36989,36994,37000,36995,37003,24400,24407,24406,24408,23611,21675,23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,23000,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27000,26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,32951,32999,33000,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26000,40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,58000,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565],"gb18030-ranges":[[0,128],[36,165],[38,169],[45,178],[50,184],[81,216],[89,226],[95,235],[96,238],[100,244],[103,248],[104,251],[105,253],[109,258],[126,276],[133,284],[148,300],[172,325],[175,329],[179,334],[208,364],[306,463],[307,465],[308,467],[309,469],[310,471],[311,473],[312,475],[313,477],[341,506],[428,594],[443,610],[544,712],[545,716],[558,730],[741,930],[742,938],[749,962],[750,970],[805,1026],[819,1104],[820,1106],[7922,8209],[7924,8215],[7925,8218],[7927,8222],[7934,8231],[7943,8241],[7944,8244],[7945,8246],[7950,8252],[8062,8365],[8148,8452],[8149,8454],[8152,8458],[8164,8471],[8174,8482],[8236,8556],[8240,8570],[8262,8596],[8264,8602],[8374,8713],[8380,8720],[8381,8722],[8384,8726],[8388,8731],[8390,8737],[8392,8740],[8393,8742],[8394,8748],[8396,8751],[8401,8760],[8406,8766],[8416,8777],[8419,8781],[8424,8787],[8437,8802],[8439,8808],[8445,8816],[8482,8854],[8485,8858],[8496,8870],[8521,8896],[8603,8979],[8936,9322],[8946,9372],[9046,9548],[9050,9588],[9063,9616],[9066,9622],[9076,9634],[9092,9652],[9100,9662],[9108,9672],[9111,9676],[9113,9680],[9131,9702],[9162,9735],[9164,9738],[9218,9793],[9219,9795],[11329,11906],[11331,11909],[11334,11913],[11336,11917],[11346,11928],[11361,11944],[11363,11947],[11366,11951],[11370,11956],[11372,11960],[11375,11964],[11389,11979],[11682,12284],[11686,12292],[11687,12312],[11692,12319],[11694,12330],[11714,12351],[11716,12436],[11723,12447],[11725,12535],[11730,12543],[11736,12586],[11982,12842],[11989,12850],[12102,12964],[12336,13200],[12348,13215],[12350,13218],[12384,13253],[12393,13263],[12395,13267],[12397,13270],[12510,13384],[12553,13428],[12851,13727],[12962,13839],[12973,13851],[13738,14617],[13823,14703],[13919,14801],[13933,14816],[14080,14964],[14298,15183],[14585,15471],[14698,15585],[15583,16471],[15847,16736],[16318,17208],[16434,17325],[16438,17330],[16481,17374],[16729,17623],[17102,17997],[17122,18018],[17315,18212],[17320,18218],[17402,18301],[17418,18318],[17859,18760],[17909,18811],[17911,18814],[17915,18820],[17916,18823],[17936,18844],[17939,18848],[17961,18872],[18664,19576],[18703,19620],[18814,19738],[18962,19887],[19043,40870],[33469,59244],[33470,59336],[33471,59367],[33484,59413],[33485,59417],[33490,59423],[33497,59431],[33501,59437],[33505,59443],[33513,59452],[33520,59460],[33536,59478],[33550,59493],[37845,63789],[37921,63866],[37948,63894],[38029,63976],[38038,63986],[38064,64016],[38065,64018],[38066,64021],[38069,64025],[38075,64034],[38076,64037],[38078,64042],[39108,65074],[39109,65093],[39113,65107],[39114,65112],[39115,65127],[39116,65132],[39265,65375],[39394,65510],[189000,65536]],"jis0208":[12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,8213,8208,65295,65340,65374,8741,65372,8230,8229,8216,8217,8220,8221,65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,65291,65293,177,215,247,65309,8800,65308,65310,8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,65504,65505,65285,65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,null,null,null,null,null,null,null,null,null,null,null,8712,8715,8838,8839,8834,8835,8746,8745,null,null,null,null,null,null,null,null,8743,8744,65506,8658,8660,8704,8707,null,null,null,null,null,null,null,null,null,null,null,8736,8869,8978,8706,8711,8801,8786,8810,8811,8730,8765,8733,8757,8747,8748,null,null,null,null,null,null,null,8491,8240,9839,9837,9834,8224,8225,182,null,null,null,null,9711,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,null,null,null,null,null,null,null,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,null,null,null,null,null,null,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,null,null,null,null,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,13129,13076,13090,13133,13080,13095,13059,13110,13137,13143,13069,13094,13091,13099,13130,13115,13212,13213,13214,13198,13199,13252,13217,null,null,null,null,null,null,null,null,13179,12317,12319,8470,13261,8481,12964,12965,12966,12967,12968,12849,12850,12857,13182,13181,13180,8786,8801,8747,8750,8721,8730,8869,8736,8735,8895,8757,8745,8746,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20124,21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21000,33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,23721,32747,36107,38593,38929,38996,39000,20225,20238,21361,21916,22120,22522,22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32000,24509,35215,35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,36578,39003,28857,20253,27583,28593,30000,38651,20814,21520,22581,22615,22956,23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,21329,21542,22915,24199,24444,24754,25161,25209,25259,26000,27604,27852,30130,30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,33178,33433,35676,36000,36070,36212,38428,38468,20398,25771,27494,33310,33889,34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,26906,26915,26913,26822,27001,26999,26972,27000,26987,26964,27006,26990,26937,26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,33983,33951,34009,33997,33979,34010,34000,33985,33990,34006,33953,34081,34047,34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38000,38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,65506,65508,65287,65282,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,65506,65508,65287,65282,12849,8470,8481,8757,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"jis0212":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,728,711,184,729,733,175,731,730,65374,900,901,null,null,null,null,null,null,null,null,161,166,191,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,186,170,169,174,8482,164,8470,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,902,904,905,906,938,null,908,null,910,939,null,911,null,null,null,null,940,941,942,943,970,912,972,962,973,971,944,974,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,198,272,null,294,null,306,null,321,319,null,330,216,338,null,358,222,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,230,273,240,295,305,307,312,322,320,329,331,248,339,223,359,254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,193,192,196,194,258,461,256,260,197,195,262,264,268,199,266,270,201,200,203,202,282,278,274,280,null,284,286,290,288,292,205,204,207,206,463,304,298,302,296,308,310,313,317,315,323,327,325,209,211,210,214,212,465,336,332,213,340,344,342,346,348,352,350,356,354,218,217,220,219,364,467,368,362,370,366,360,471,475,473,469,372,221,376,374,377,381,379,null,null,null,null,null,null,null,225,224,228,226,259,462,257,261,229,227,263,265,269,231,267,271,233,232,235,234,283,279,275,281,501,285,287,null,289,293,237,236,239,238,464,null,299,303,297,309,311,314,318,316,324,328,326,241,243,242,246,244,466,337,333,245,341,345,343,347,349,353,351,357,355,250,249,252,251,365,468,369,363,371,367,361,472,476,474,470,373,253,255,375,378,382,380,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19970,19972,19973,19980,19986,19999,20003,20004,20008,20011,20014,20015,20016,20021,20032,20033,20036,20039,20049,20058,20060,20067,20072,20073,20084,20085,20089,20095,20109,20118,20119,20125,20143,20153,20163,20176,20186,20187,20192,20193,20194,20200,20207,20209,20211,20213,20221,20222,20223,20224,20226,20227,20232,20235,20236,20242,20245,20246,20247,20249,20270,20273,20320,20275,20277,20279,20281,20283,20286,20288,20290,20296,20297,20299,20300,20306,20308,20310,20312,20319,20323,20330,20332,20334,20337,20343,20344,20345,20346,20349,20350,20353,20354,20356,20357,20361,20362,20364,20366,20368,20370,20371,20372,20375,20377,20378,20382,20383,20402,20407,20409,20411,20412,20413,20414,20416,20417,20421,20422,20424,20425,20427,20428,20429,20431,20434,20444,20448,20450,20464,20466,20476,20477,20479,20480,20481,20484,20487,20490,20492,20494,20496,20499,20503,20504,20507,20508,20509,20510,20514,20519,20526,20528,20530,20531,20533,20544,20545,20546,20549,20550,20554,20556,20558,20561,20562,20563,20567,20569,20575,20576,20578,20579,20582,20583,20586,20589,20592,20593,20539,20609,20611,20612,20614,20618,20622,20623,20624,20626,20627,20628,20630,20635,20636,20638,20639,20640,20641,20642,20650,20655,20656,20665,20666,20669,20672,20675,20676,20679,20684,20686,20688,20691,20692,20696,20700,20701,20703,20706,20708,20710,20712,20713,20719,20721,20726,20730,20734,20739,20742,20743,20744,20747,20748,20749,20750,20722,20752,20759,20761,20763,20764,20765,20766,20771,20775,20776,20780,20781,20783,20785,20787,20788,20789,20792,20793,20802,20810,20815,20819,20821,20823,20824,20831,20836,20838,20862,20867,20868,20875,20878,20888,20893,20897,20899,20909,20920,20922,20924,20926,20927,20930,20936,20943,20945,20946,20947,20949,20952,20958,20962,20965,20974,20978,20979,20980,20983,20993,20994,20997,21010,21011,21013,21014,21016,21026,21032,21041,21042,21045,21052,21061,21065,21077,21079,21080,21082,21084,21087,21088,21089,21094,21102,21111,21112,21113,21120,21122,21125,21130,21132,21139,21141,21142,21143,21144,21146,21148,21156,21157,21158,21159,21167,21168,21174,21175,21176,21178,21179,21181,21184,21188,21190,21192,21196,21199,21201,21204,21206,21211,21212,21217,21221,21224,21225,21226,21228,21232,21233,21236,21238,21239,21248,21251,21258,21259,21260,21265,21267,21272,21275,21276,21278,21279,21285,21287,21288,21289,21291,21292,21293,21296,21298,21301,21308,21309,21310,21314,21324,21323,21337,21339,21345,21347,21349,21356,21357,21362,21369,21374,21379,21383,21384,21390,21395,21396,21401,21405,21409,21412,21418,21419,21423,21426,21428,21429,21431,21432,21434,21437,21440,21445,21455,21458,21459,21461,21466,21469,21470,21472,21478,21479,21493,21506,21523,21530,21537,21543,21544,21546,21551,21553,21556,21557,21571,21572,21575,21581,21583,21598,21602,21604,21606,21607,21609,21611,21613,21614,21620,21631,21633,21635,21637,21640,21641,21645,21649,21653,21654,21660,21663,21665,21670,21671,21673,21674,21677,21678,21681,21687,21689,21690,21691,21695,21702,21706,21709,21710,21728,21738,21740,21743,21750,21756,21758,21759,21760,21761,21765,21768,21769,21772,21773,21774,21781,21802,21803,21810,21813,21814,21819,21820,21821,21825,21831,21833,21834,21837,21840,21841,21848,21850,21851,21854,21856,21857,21860,21862,21887,21889,21890,21894,21896,21902,21903,21905,21906,21907,21908,21911,21923,21924,21933,21938,21951,21953,21955,21958,21961,21963,21964,21966,21969,21970,21971,21975,21976,21979,21982,21986,21993,22006,22015,22021,22024,22026,22029,22030,22031,22032,22033,22034,22041,22060,22064,22067,22069,22071,22073,22075,22076,22077,22079,22080,22081,22083,22084,22086,22089,22091,22093,22095,22100,22110,22112,22113,22114,22115,22118,22121,22125,22127,22129,22130,22133,22148,22149,22152,22155,22156,22165,22169,22170,22173,22174,22175,22182,22183,22184,22185,22187,22188,22189,22193,22195,22199,22206,22213,22217,22218,22219,22223,22224,22220,22221,22233,22236,22237,22239,22241,22244,22245,22246,22247,22248,22257,22251,22253,22262,22263,22273,22274,22279,22282,22284,22289,22293,22298,22299,22301,22304,22306,22307,22308,22309,22313,22314,22316,22318,22319,22323,22324,22333,22334,22335,22341,22342,22348,22349,22354,22370,22373,22375,22376,22379,22381,22382,22383,22384,22385,22387,22388,22389,22391,22393,22394,22395,22396,22398,22401,22403,22412,22420,22423,22425,22426,22428,22429,22430,22431,22433,22421,22439,22440,22441,22444,22456,22461,22471,22472,22476,22479,22485,22493,22494,22500,22502,22503,22505,22509,22512,22517,22518,22520,22525,22526,22527,22531,22532,22536,22537,22497,22540,22541,22555,22558,22559,22560,22566,22567,22573,22578,22585,22591,22601,22604,22605,22607,22608,22613,22623,22625,22628,22631,22632,22648,22652,22655,22656,22657,22663,22664,22665,22666,22668,22669,22671,22672,22676,22678,22685,22688,22689,22690,22694,22697,22705,22706,22724,22716,22722,22728,22733,22734,22736,22738,22740,22742,22746,22749,22753,22754,22761,22771,22789,22790,22795,22796,22802,22803,22804,34369,22813,22817,22819,22820,22824,22831,22832,22835,22837,22838,22847,22851,22854,22866,22867,22873,22875,22877,22878,22879,22881,22883,22891,22893,22895,22898,22901,22902,22905,22907,22908,22923,22924,22926,22930,22933,22935,22943,22948,22951,22957,22958,22959,22960,22963,22967,22970,22972,22977,22979,22980,22984,22986,22989,22994,23005,23006,23007,23011,23012,23015,23022,23023,23025,23026,23028,23031,23040,23044,23052,23053,23054,23058,23059,23070,23075,23076,23079,23080,23082,23085,23088,23108,23109,23111,23112,23116,23120,23125,23134,23139,23141,23143,23149,23159,23162,23163,23166,23179,23184,23187,23190,23193,23196,23198,23199,23200,23202,23207,23212,23217,23218,23219,23221,23224,23226,23227,23231,23236,23238,23240,23247,23258,23260,23264,23269,23274,23278,23285,23286,23293,23296,23297,23304,23319,23348,23321,23323,23325,23329,23333,23341,23352,23361,23371,23372,23378,23382,23390,23400,23406,23407,23420,23421,23422,23423,23425,23428,23430,23434,23438,23440,23441,23443,23444,23446,23464,23465,23468,23469,23471,23473,23474,23479,23482,23484,23488,23489,23501,23503,23510,23511,23512,23513,23514,23520,23535,23537,23540,23549,23564,23575,23582,23583,23587,23590,23593,23595,23596,23598,23600,23602,23605,23606,23641,23642,23644,23650,23651,23655,23656,23657,23661,23664,23668,23669,23674,23675,23676,23677,23687,23688,23690,23695,23698,23709,23711,23712,23714,23715,23718,23722,23730,23732,23733,23738,23753,23755,23762,23773,23767,23790,23793,23794,23796,23809,23814,23821,23826,23851,23843,23844,23846,23847,23857,23860,23865,23869,23871,23874,23875,23878,23880,23893,23889,23897,23882,23903,23904,23905,23906,23908,23914,23917,23920,23929,23930,23934,23935,23937,23939,23944,23946,23954,23955,23956,23957,23961,23963,23967,23968,23975,23979,23984,23988,23992,23993,24003,24007,24011,24016,24014,24024,24025,24032,24036,24041,24056,24057,24064,24071,24077,24082,24084,24085,24088,24095,24096,24110,24104,24114,24117,24126,24139,24144,24137,24145,24150,24152,24155,24156,24158,24168,24170,24171,24172,24173,24174,24176,24192,24203,24206,24226,24228,24229,24232,24234,24236,24241,24243,24253,24254,24255,24262,24268,24267,24270,24273,24274,24276,24277,24284,24286,24293,24299,24322,24326,24327,24328,24334,24345,24348,24349,24353,24354,24355,24356,24360,24363,24364,24366,24368,24372,24374,24379,24381,24383,24384,24388,24389,24391,24397,24400,24404,24408,24411,24416,24419,24420,24423,24431,24434,24436,24437,24440,24442,24445,24446,24457,24461,24463,24470,24476,24477,24482,24487,24491,24484,24492,24495,24496,24497,24504,24516,24519,24520,24521,24523,24528,24529,24530,24531,24532,24542,24545,24546,24552,24553,24554,24556,24557,24558,24559,24562,24563,24566,24570,24572,24583,24586,24589,24595,24596,24599,24600,24602,24607,24612,24621,24627,24629,24640,24647,24648,24649,24652,24657,24660,24662,24663,24669,24673,24679,24689,24702,24703,24706,24710,24712,24714,24718,24721,24723,24725,24728,24733,24734,24738,24740,24741,24744,24752,24753,24759,24763,24766,24770,24772,24776,24777,24778,24779,24782,24783,24788,24789,24793,24795,24797,24798,24802,24805,24818,24821,24824,24828,24829,24834,24839,24842,24844,24848,24849,24850,24851,24852,24854,24855,24857,24860,24862,24866,24874,24875,24880,24881,24885,24886,24887,24889,24897,24901,24902,24905,24926,24928,24940,24946,24952,24955,24956,24959,24960,24961,24963,24964,24971,24973,24978,24979,24983,24984,24988,24989,24991,24992,24997,25000,25002,25005,25016,25017,25020,25024,25025,25026,25038,25039,25045,25052,25053,25054,25055,25057,25058,25063,25065,25061,25068,25069,25071,25089,25091,25092,25095,25107,25109,25116,25120,25122,25123,25127,25129,25131,25145,25149,25154,25155,25156,25158,25164,25168,25169,25170,25172,25174,25178,25180,25188,25197,25199,25203,25210,25213,25229,25230,25231,25232,25254,25256,25267,25270,25271,25274,25278,25279,25284,25294,25301,25302,25306,25322,25330,25332,25340,25341,25347,25348,25354,25355,25357,25360,25363,25366,25368,25385,25386,25389,25397,25398,25401,25404,25409,25410,25411,25412,25414,25418,25419,25422,25426,25427,25428,25432,25435,25445,25446,25452,25453,25457,25460,25461,25464,25468,25469,25471,25474,25476,25479,25482,25488,25492,25493,25497,25498,25502,25508,25510,25517,25518,25519,25533,25537,25541,25544,25550,25553,25555,25556,25557,25564,25568,25573,25578,25580,25586,25587,25589,25592,25593,25609,25610,25616,25618,25620,25624,25630,25632,25634,25636,25637,25641,25642,25647,25648,25653,25661,25663,25675,25679,25681,25682,25683,25684,25690,25691,25692,25693,25695,25696,25697,25699,25709,25715,25716,25723,25725,25733,25735,25743,25744,25745,25752,25753,25755,25757,25759,25761,25763,25766,25768,25772,25779,25789,25790,25791,25796,25801,25802,25803,25804,25806,25808,25809,25813,25815,25828,25829,25833,25834,25837,25840,25845,25847,25851,25855,25857,25860,25864,25865,25866,25871,25875,25876,25878,25881,25883,25886,25887,25890,25894,25897,25902,25905,25914,25916,25917,25923,25927,25929,25936,25938,25940,25951,25952,25959,25963,25978,25981,25985,25989,25994,26002,26005,26008,26013,26016,26019,26022,26030,26034,26035,26036,26047,26050,26056,26057,26062,26064,26068,26070,26072,26079,26096,26098,26100,26101,26105,26110,26111,26112,26116,26120,26121,26125,26129,26130,26133,26134,26141,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26161,26163,26169,26167,26176,26181,26182,26186,26188,26193,26190,26199,26200,26201,26203,26204,26208,26209,26363,26218,26219,26220,26238,26227,26229,26239,26231,26232,26233,26235,26240,26236,26251,26252,26253,26256,26258,26265,26266,26267,26268,26271,26272,26276,26285,26289,26290,26293,26299,26303,26304,26306,26307,26312,26316,26318,26319,26324,26331,26335,26344,26347,26348,26350,26362,26373,26375,26382,26387,26393,26396,26400,26402,26419,26430,26437,26439,26440,26444,26452,26453,26461,26470,26476,26478,26484,26486,26491,26497,26500,26510,26511,26513,26515,26518,26520,26521,26523,26544,26545,26546,26549,26555,26556,26557,26617,26560,26562,26563,26565,26568,26569,26578,26583,26585,26588,26593,26598,26608,26610,26614,26615,26706,26644,26649,26653,26655,26664,26663,26668,26669,26671,26672,26673,26675,26683,26687,26692,26693,26698,26700,26709,26711,26712,26715,26731,26734,26735,26736,26737,26738,26741,26745,26746,26747,26748,26754,26756,26758,26760,26774,26776,26778,26780,26785,26787,26789,26793,26794,26798,26802,26811,26821,26824,26828,26831,26832,26833,26835,26838,26841,26844,26845,26853,26856,26858,26859,26860,26861,26864,26865,26869,26870,26875,26876,26877,26886,26889,26890,26896,26897,26899,26902,26903,26929,26931,26933,26936,26939,26946,26949,26953,26958,26967,26971,26979,26980,26981,26982,26984,26985,26988,26992,26993,26994,27002,27003,27007,27008,27021,27026,27030,27032,27041,27045,27046,27048,27051,27053,27055,27063,27064,27066,27068,27077,27080,27089,27094,27095,27106,27109,27118,27119,27121,27123,27125,27134,27136,27137,27139,27151,27153,27157,27162,27165,27168,27172,27176,27184,27186,27188,27191,27195,27198,27199,27205,27206,27209,27210,27214,27216,27217,27218,27221,27222,27227,27236,27239,27242,27249,27251,27262,27265,27267,27270,27271,27273,27275,27281,27291,27293,27294,27295,27301,27307,27311,27312,27313,27316,27325,27326,27327,27334,27337,27336,27340,27344,27348,27349,27350,27356,27357,27364,27367,27372,27376,27377,27378,27388,27389,27394,27395,27398,27399,27401,27407,27408,27409,27415,27419,27422,27428,27432,27435,27436,27439,27445,27446,27451,27455,27462,27466,27469,27474,27478,27480,27485,27488,27495,27499,27502,27504,27509,27517,27518,27522,27525,27543,27547,27551,27552,27554,27555,27560,27561,27564,27565,27566,27568,27576,27577,27581,27582,27587,27588,27593,27596,27606,27610,27617,27619,27622,27623,27630,27633,27639,27641,27647,27650,27652,27653,27657,27661,27662,27664,27666,27673,27679,27686,27687,27688,27692,27694,27699,27701,27702,27706,27707,27711,27722,27723,27725,27727,27730,27732,27737,27739,27740,27755,27757,27759,27764,27766,27768,27769,27771,27781,27782,27783,27785,27796,27797,27799,27800,27804,27807,27824,27826,27828,27842,27846,27853,27855,27856,27857,27858,27860,27862,27866,27868,27872,27879,27881,27883,27884,27886,27890,27892,27908,27911,27914,27918,27919,27921,27923,27930,27942,27943,27944,27751,27950,27951,27953,27961,27964,27967,27991,27998,27999,28001,28005,28007,28015,28016,28028,28034,28039,28049,28050,28052,28054,28055,28056,28074,28076,28084,28087,28089,28093,28095,28100,28104,28106,28110,28111,28118,28123,28125,28127,28128,28130,28133,28137,28143,28144,28148,28150,28156,28160,28164,28190,28194,28199,28210,28214,28217,28219,28220,28228,28229,28232,28233,28235,28239,28241,28242,28243,28244,28247,28252,28253,28254,28258,28259,28264,28275,28283,28285,28301,28307,28313,28320,28327,28333,28334,28337,28339,28347,28351,28352,28353,28355,28359,28360,28362,28365,28366,28367,28395,28397,28398,28409,28411,28413,28420,28424,28426,28428,28429,28438,28440,28442,28443,28454,28457,28458,28463,28464,28467,28470,28475,28476,28461,28495,28497,28498,28499,28503,28505,28506,28509,28510,28513,28514,28520,28524,28541,28542,28547,28551,28552,28555,28556,28557,28560,28562,28563,28564,28566,28570,28575,28576,28581,28582,28583,28584,28590,28591,28592,28597,28598,28604,28613,28615,28616,28618,28634,28638,28648,28649,28656,28661,28665,28668,28669,28672,28677,28678,28679,28685,28695,28704,28707,28719,28724,28727,28729,28732,28739,28740,28744,28745,28746,28747,28756,28757,28765,28766,28750,28772,28773,28780,28782,28789,28790,28798,28801,28805,28806,28820,28821,28822,28823,28824,28827,28836,28843,28848,28849,28852,28855,28874,28881,28883,28884,28885,28886,28888,28892,28900,28922,28931,28932,28933,28934,28935,28939,28940,28943,28958,28960,28971,28973,28975,28976,28977,28984,28993,28997,28998,28999,29002,29003,29008,29010,29015,29018,29020,29022,29024,29032,29049,29056,29061,29063,29068,29074,29082,29083,29088,29090,29103,29104,29106,29107,29114,29119,29120,29121,29124,29131,29132,29139,29142,29145,29146,29148,29176,29182,29184,29191,29192,29193,29203,29207,29210,29213,29215,29220,29227,29231,29236,29240,29241,29249,29250,29251,29253,29262,29263,29264,29267,29269,29270,29274,29276,29278,29280,29283,29288,29291,29294,29295,29297,29303,29304,29307,29308,29311,29316,29321,29325,29326,29331,29339,29352,29357,29358,29361,29364,29374,29377,29383,29385,29388,29397,29398,29400,29407,29413,29427,29428,29434,29435,29438,29442,29444,29445,29447,29451,29453,29458,29459,29464,29465,29470,29474,29476,29479,29480,29484,29489,29490,29493,29498,29499,29501,29507,29517,29520,29522,29526,29528,29533,29534,29535,29536,29542,29543,29545,29547,29548,29550,29551,29553,29559,29561,29564,29568,29569,29571,29573,29574,29582,29584,29587,29589,29591,29592,29596,29598,29599,29600,29602,29605,29606,29610,29611,29613,29621,29623,29625,29628,29629,29631,29637,29638,29641,29643,29644,29647,29650,29651,29654,29657,29661,29665,29667,29670,29671,29673,29684,29685,29687,29689,29690,29691,29693,29695,29696,29697,29700,29703,29706,29713,29722,29723,29732,29734,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29753,29760,29763,29764,29766,29767,29771,29773,29777,29778,29783,29789,29794,29798,29799,29800,29803,29805,29806,29809,29810,29824,29825,29829,29830,29831,29833,29839,29840,29841,29842,29848,29849,29850,29852,29855,29856,29857,29859,29862,29864,29865,29866,29867,29870,29871,29873,29874,29877,29881,29883,29887,29896,29897,29900,29904,29907,29912,29914,29915,29918,29919,29924,29928,29930,29931,29935,29940,29946,29947,29948,29951,29958,29970,29974,29975,29984,29985,29988,29991,29993,29994,29999,30006,30009,30013,30014,30015,30016,30019,30023,30024,30030,30032,30034,30039,30046,30047,30049,30063,30065,30073,30074,30075,30076,30077,30078,30081,30085,30096,30098,30099,30101,30105,30108,30114,30116,30132,30138,30143,30144,30145,30148,30150,30156,30158,30159,30167,30172,30175,30176,30177,30180,30183,30188,30190,30191,30193,30201,30208,30210,30211,30212,30215,30216,30218,30220,30223,30226,30227,30229,30230,30233,30235,30236,30237,30238,30243,30245,30246,30249,30253,30258,30259,30261,30264,30265,30266,30268,30282,30272,30273,30275,30276,30277,30281,30283,30293,30297,30303,30308,30309,30317,30318,30319,30321,30324,30337,30341,30348,30349,30357,30363,30364,30365,30367,30368,30370,30371,30372,30373,30374,30375,30376,30378,30381,30397,30401,30405,30409,30411,30412,30414,30420,30425,30432,30438,30440,30444,30448,30449,30454,30457,30460,30464,30470,30474,30478,30482,30484,30485,30487,30489,30490,30492,30498,30504,30509,30510,30511,30516,30517,30518,30521,30525,30526,30530,30533,30534,30538,30541,30542,30543,30546,30550,30551,30556,30558,30559,30560,30562,30564,30567,30570,30572,30576,30578,30579,30580,30586,30589,30592,30596,30604,30605,30612,30613,30614,30618,30623,30626,30631,30634,30638,30639,30641,30645,30654,30659,30665,30673,30674,30677,30681,30686,30687,30688,30692,30694,30698,30700,30704,30705,30708,30712,30715,30725,30726,30729,30733,30734,30737,30749,30753,30754,30755,30765,30766,30768,30773,30775,30787,30788,30791,30792,30796,30798,30802,30812,30814,30816,30817,30819,30820,30824,30826,30830,30842,30846,30858,30863,30868,30872,30881,30877,30878,30879,30884,30888,30892,30893,30896,30897,30898,30899,30907,30909,30911,30919,30920,30921,30924,30926,30930,30931,30933,30934,30948,30939,30943,30944,30945,30950,30954,30962,30963,30976,30966,30967,30970,30971,30975,30982,30988,30992,31002,31004,31006,31007,31008,31013,31015,31017,31021,31025,31028,31029,31035,31037,31039,31044,31045,31046,31050,31051,31055,31057,31060,31064,31067,31068,31079,31081,31083,31090,31097,31099,31100,31102,31115,31116,31121,31123,31124,31125,31126,31128,31131,31132,31137,31144,31145,31147,31151,31153,31156,31160,31163,31170,31172,31175,31176,31178,31183,31188,31190,31194,31197,31198,31200,31202,31205,31210,31211,31213,31217,31224,31228,31234,31235,31239,31241,31242,31244,31249,31253,31259,31262,31265,31271,31275,31277,31279,31280,31284,31285,31288,31289,31290,31300,31301,31303,31304,31308,31317,31318,31321,31324,31325,31327,31328,31333,31335,31338,31341,31349,31352,31358,31360,31362,31365,31366,31370,31371,31376,31377,31380,31390,31392,31395,31404,31411,31413,31417,31419,31420,31430,31433,31436,31438,31441,31451,31464,31465,31467,31468,31473,31476,31483,31485,31486,31495,31508,31519,31523,31527,31529,31530,31531,31533,31534,31535,31536,31537,31540,31549,31551,31552,31553,31559,31566,31573,31584,31588,31590,31593,31594,31597,31599,31602,31603,31607,31620,31625,31630,31632,31633,31638,31643,31646,31648,31653,31660,31663,31664,31666,31669,31670,31674,31675,31676,31677,31682,31685,31688,31690,31700,31702,31703,31705,31706,31707,31720,31722,31730,31732,31733,31736,31737,31738,31740,31742,31745,31746,31747,31748,31750,31753,31755,31756,31758,31759,31769,31771,31776,31781,31782,31784,31788,31793,31795,31796,31798,31801,31802,31814,31818,31829,31825,31826,31827,31833,31834,31835,31836,31837,31838,31841,31843,31847,31849,31853,31854,31856,31858,31865,31868,31869,31878,31879,31887,31892,31902,31904,31910,31920,31926,31927,31930,31931,31932,31935,31940,31943,31944,31945,31949,31951,31955,31956,31957,31959,31961,31962,31965,31974,31977,31979,31989,32003,32007,32008,32009,32015,32017,32018,32019,32022,32029,32030,32035,32038,32042,32045,32049,32060,32061,32062,32064,32065,32071,32072,32077,32081,32083,32087,32089,32090,32092,32093,32101,32103,32106,32112,32120,32122,32123,32127,32129,32130,32131,32133,32134,32136,32139,32140,32141,32145,32150,32151,32157,32158,32166,32167,32170,32179,32182,32183,32185,32194,32195,32196,32197,32198,32204,32205,32206,32215,32217,32256,32226,32229,32230,32234,32235,32237,32241,32245,32246,32249,32250,32264,32272,32273,32277,32279,32284,32285,32288,32295,32296,32300,32301,32303,32307,32310,32319,32324,32325,32327,32334,32336,32338,32344,32351,32353,32354,32357,32363,32366,32367,32371,32376,32382,32385,32390,32391,32394,32397,32401,32405,32408,32410,32413,32414,32572,32571,32573,32574,32575,32579,32580,32583,32591,32594,32595,32603,32604,32605,32609,32611,32612,32613,32614,32621,32625,32637,32638,32639,32640,32651,32653,32655,32656,32657,32662,32663,32668,32673,32674,32678,32682,32685,32692,32700,32703,32704,32707,32712,32718,32719,32731,32735,32739,32741,32744,32748,32750,32751,32754,32762,32765,32766,32767,32775,32776,32778,32781,32782,32783,32785,32787,32788,32790,32797,32798,32799,32800,32804,32806,32812,32814,32816,32820,32821,32823,32825,32826,32828,32830,32832,32836,32864,32868,32870,32877,32881,32885,32897,32904,32910,32924,32926,32934,32935,32939,32952,32953,32968,32973,32975,32978,32980,32981,32983,32984,32992,33005,33006,33008,33010,33011,33014,33017,33018,33022,33027,33035,33046,33047,33048,33052,33054,33056,33060,33063,33068,33072,33077,33082,33084,33093,33095,33098,33100,33106,33111,33120,33121,33127,33128,33129,33133,33135,33143,33153,33168,33156,33157,33158,33163,33166,33174,33176,33179,33182,33186,33198,33202,33204,33211,33227,33219,33221,33226,33230,33231,33237,33239,33243,33245,33246,33249,33252,33259,33260,33264,33265,33266,33269,33270,33272,33273,33277,33279,33280,33283,33295,33299,33300,33305,33306,33309,33313,33314,33320,33330,33332,33338,33347,33348,33349,33350,33355,33358,33359,33361,33366,33372,33376,33379,33383,33389,33396,33403,33405,33407,33408,33409,33411,33412,33415,33417,33418,33422,33425,33428,33430,33432,33434,33435,33440,33441,33443,33444,33447,33448,33449,33450,33454,33456,33458,33460,33463,33466,33468,33470,33471,33478,33488,33493,33498,33504,33506,33508,33512,33514,33517,33519,33526,33527,33533,33534,33536,33537,33543,33544,33546,33547,33620,33563,33565,33566,33567,33569,33570,33580,33581,33582,33584,33587,33591,33594,33596,33597,33602,33603,33604,33607,33613,33614,33617,33621,33622,33623,33648,33656,33661,33663,33664,33666,33668,33670,33677,33682,33684,33685,33688,33689,33691,33692,33693,33702,33703,33705,33708,33726,33727,33728,33735,33737,33743,33744,33745,33748,33757,33619,33768,33770,33782,33784,33785,33788,33793,33798,33802,33807,33809,33813,33817,33709,33839,33849,33861,33863,33864,33866,33869,33871,33873,33874,33878,33880,33881,33882,33884,33888,33892,33893,33895,33898,33904,33907,33908,33910,33912,33916,33917,33921,33925,33938,33939,33941,33950,33958,33960,33961,33962,33967,33969,33972,33978,33981,33982,33984,33986,33991,33992,33996,33999,34003,34012,34023,34026,34031,34032,34033,34034,34039,34098,34042,34043,34045,34050,34051,34055,34060,34062,34064,34076,34078,34082,34083,34084,34085,34087,34090,34091,34095,34099,34100,34102,34111,34118,34127,34128,34129,34130,34131,34134,34137,34140,34141,34142,34143,34144,34145,34146,34148,34155,34159,34169,34170,34171,34173,34175,34177,34181,34182,34185,34187,34188,34191,34195,34200,34205,34207,34208,34210,34213,34215,34228,34230,34231,34232,34236,34237,34238,34239,34242,34247,34250,34251,34254,34221,34264,34266,34271,34272,34278,34280,34285,34291,34294,34300,34303,34304,34308,34309,34317,34318,34320,34321,34322,34328,34329,34331,34334,34337,34343,34345,34358,34360,34362,34364,34365,34368,34370,34374,34386,34387,34390,34391,34392,34393,34397,34400,34401,34402,34403,34404,34409,34412,34415,34421,34422,34423,34426,34445,34449,34454,34456,34458,34460,34465,34470,34471,34472,34477,34481,34483,34484,34485,34487,34488,34489,34495,34496,34497,34499,34501,34513,34514,34517,34519,34522,34524,34528,34531,34533,34535,34440,34554,34556,34557,34564,34565,34567,34571,34574,34575,34576,34579,34580,34585,34590,34591,34593,34595,34600,34606,34607,34609,34610,34617,34618,34620,34621,34622,34624,34627,34629,34637,34648,34653,34657,34660,34661,34671,34673,34674,34683,34691,34692,34693,34694,34695,34696,34697,34699,34700,34704,34707,34709,34711,34712,34713,34718,34720,34723,34727,34732,34733,34734,34737,34741,34750,34751,34753,34760,34761,34762,34766,34773,34774,34777,34778,34780,34783,34786,34787,34788,34794,34795,34797,34801,34803,34808,34810,34815,34817,34819,34822,34825,34826,34827,34832,34841,34834,34835,34836,34840,34842,34843,34844,34846,34847,34856,34861,34862,34864,34866,34869,34874,34876,34881,34883,34885,34888,34889,34890,34891,34894,34897,34901,34902,34904,34906,34908,34911,34912,34916,34921,34929,34937,34939,34944,34968,34970,34971,34972,34975,34976,34984,34986,35002,35005,35006,35008,35018,35019,35020,35021,35022,35025,35026,35027,35035,35038,35047,35055,35056,35057,35061,35063,35073,35078,35085,35086,35087,35093,35094,35096,35097,35098,35100,35104,35110,35111,35112,35120,35121,35122,35125,35129,35130,35134,35136,35138,35141,35142,35145,35151,35154,35159,35162,35163,35164,35169,35170,35171,35179,35182,35184,35187,35189,35194,35195,35196,35197,35209,35213,35216,35220,35221,35227,35228,35231,35232,35237,35248,35252,35253,35254,35255,35260,35284,35285,35286,35287,35288,35301,35305,35307,35309,35313,35315,35318,35321,35325,35327,35332,35333,35335,35343,35345,35346,35348,35349,35358,35360,35362,35364,35366,35371,35372,35375,35381,35383,35389,35390,35392,35395,35397,35399,35401,35405,35406,35411,35414,35415,35416,35420,35421,35425,35429,35431,35445,35446,35447,35449,35450,35451,35454,35455,35456,35459,35462,35467,35471,35472,35474,35478,35479,35481,35487,35495,35497,35502,35503,35507,35510,35511,35515,35518,35523,35526,35528,35529,35530,35537,35539,35540,35541,35543,35549,35551,35564,35568,35572,35573,35574,35580,35583,35589,35590,35595,35601,35612,35614,35615,35594,35629,35632,35639,35644,35650,35651,35652,35653,35654,35656,35666,35667,35668,35673,35661,35678,35683,35693,35702,35704,35705,35708,35710,35713,35716,35717,35723,35725,35727,35732,35733,35740,35742,35743,35896,35897,35901,35902,35909,35911,35913,35915,35919,35921,35923,35924,35927,35928,35931,35933,35929,35939,35940,35942,35944,35945,35949,35955,35957,35958,35963,35966,35974,35975,35979,35984,35986,35987,35993,35995,35996,36004,36025,36026,36037,36038,36041,36043,36047,36054,36053,36057,36061,36065,36072,36076,36079,36080,36082,36085,36087,36088,36094,36095,36097,36099,36105,36114,36119,36123,36197,36201,36204,36206,36223,36226,36228,36232,36237,36240,36241,36245,36254,36255,36256,36262,36267,36268,36271,36274,36277,36279,36281,36283,36288,36293,36294,36295,36296,36298,36302,36305,36308,36309,36311,36313,36324,36325,36327,36332,36336,36284,36337,36338,36340,36349,36353,36356,36357,36358,36363,36369,36372,36374,36384,36385,36386,36387,36390,36391,36401,36403,36406,36407,36408,36409,36413,36416,36417,36427,36429,36430,36431,36436,36443,36444,36445,36446,36449,36450,36457,36460,36461,36463,36464,36465,36473,36474,36475,36482,36483,36489,36496,36498,36501,36506,36507,36509,36510,36514,36519,36521,36525,36526,36531,36533,36538,36539,36544,36545,36547,36548,36551,36559,36561,36564,36572,36584,36590,36592,36593,36599,36601,36602,36589,36608,36610,36615,36616,36623,36624,36630,36631,36632,36638,36640,36641,36643,36645,36647,36648,36652,36653,36654,36660,36661,36662,36663,36666,36672,36673,36675,36679,36687,36689,36690,36691,36692,36693,36696,36701,36702,36709,36765,36768,36769,36772,36773,36774,36789,36790,36792,36798,36800,36801,36806,36810,36811,36813,36816,36818,36819,36821,36832,36835,36836,36840,36846,36849,36853,36854,36859,36862,36866,36868,36872,36876,36888,36891,36904,36905,36911,36906,36908,36909,36915,36916,36919,36927,36931,36932,36940,36955,36957,36962,36966,36967,36972,36976,36980,36985,36997,37000,37003,37004,37006,37008,37013,37015,37016,37017,37019,37024,37025,37026,37029,37040,37042,37043,37044,37046,37053,37068,37054,37059,37060,37061,37063,37064,37077,37079,37080,37081,37084,37085,37087,37093,37074,37110,37099,37103,37104,37108,37118,37119,37120,37124,37125,37126,37128,37133,37136,37140,37142,37143,37144,37146,37148,37150,37152,37157,37154,37155,37159,37161,37166,37167,37169,37172,37174,37175,37177,37178,37180,37181,37187,37191,37192,37199,37203,37207,37209,37210,37211,37217,37220,37223,37229,37236,37241,37242,37243,37249,37251,37253,37254,37258,37262,37265,37267,37268,37269,37272,37278,37281,37286,37288,37292,37293,37294,37296,37297,37298,37299,37302,37307,37308,37309,37311,37314,37315,37317,37331,37332,37335,37337,37338,37342,37348,37349,37353,37354,37356,37357,37358,37359,37360,37361,37367,37369,37371,37373,37376,37377,37380,37381,37382,37383,37385,37386,37388,37392,37394,37395,37398,37400,37404,37405,37411,37412,37413,37414,37416,37422,37423,37424,37427,37429,37430,37432,37433,37434,37436,37438,37440,37442,37443,37446,37447,37450,37453,37454,37455,37457,37464,37465,37468,37469,37472,37473,37477,37479,37480,37481,37486,37487,37488,37493,37494,37495,37496,37497,37499,37500,37501,37503,37512,37513,37514,37517,37518,37522,37527,37529,37535,37536,37540,37541,37543,37544,37547,37551,37554,37558,37560,37562,37563,37564,37565,37567,37568,37569,37570,37571,37573,37574,37575,37576,37579,37580,37581,37582,37584,37587,37589,37591,37592,37593,37596,37597,37599,37600,37601,37603,37605,37607,37608,37612,37614,37616,37625,37627,37631,37632,37634,37640,37645,37649,37652,37653,37660,37661,37662,37663,37665,37668,37669,37671,37673,37674,37683,37684,37686,37687,37703,37704,37705,37712,37713,37714,37717,37719,37720,37722,37726,37732,37733,37735,37737,37738,37741,37743,37744,37745,37747,37748,37750,37754,37757,37759,37760,37761,37762,37768,37770,37771,37773,37775,37778,37781,37784,37787,37790,37793,37795,37796,37798,37800,37803,37812,37813,37814,37818,37801,37825,37828,37829,37830,37831,37833,37834,37835,37836,37837,37843,37849,37852,37854,37855,37858,37862,37863,37881,37879,37880,37882,37883,37885,37889,37890,37892,37896,37897,37901,37902,37903,37909,37910,37911,37919,37934,37935,37937,37938,37939,37940,37947,37951,37949,37955,37957,37960,37962,37964,37973,37977,37980,37983,37985,37987,37992,37995,37997,37998,37999,38001,38002,38020,38019,38264,38265,38270,38276,38280,38284,38285,38286,38301,38302,38303,38305,38310,38313,38315,38316,38324,38326,38330,38333,38335,38342,38344,38345,38347,38352,38353,38354,38355,38361,38362,38365,38366,38367,38368,38372,38374,38429,38430,38434,38436,38437,38438,38444,38449,38451,38455,38456,38457,38458,38460,38461,38465,38482,38484,38486,38487,38488,38497,38510,38516,38523,38524,38526,38527,38529,38530,38531,38532,38537,38545,38550,38554,38557,38559,38564,38565,38566,38569,38574,38575,38579,38586,38602,38610,23986,38616,38618,38621,38622,38623,38633,38639,38641,38650,38658,38659,38661,38665,38682,38683,38685,38689,38690,38691,38696,38705,38707,38721,38723,38730,38734,38735,38741,38743,38744,38746,38747,38755,38759,38762,38766,38771,38774,38775,38776,38779,38781,38783,38784,38793,38805,38806,38807,38809,38810,38814,38815,38818,38828,38830,38833,38834,38837,38838,38840,38841,38842,38844,38846,38847,38849,38852,38853,38855,38857,38858,38860,38861,38862,38864,38865,38868,38871,38872,38873,38877,38878,38880,38875,38881,38884,38895,38897,38900,38903,38904,38906,38919,38922,38937,38925,38926,38932,38934,38940,38942,38944,38947,38950,38955,38958,38959,38960,38962,38963,38965,38949,38974,38980,38983,38986,38993,38994,38995,38998,38999,39001,39002,39010,39011,39013,39014,39018,39020,39083,39085,39086,39088,39092,39095,39096,39098,39099,39103,39106,39109,39112,39116,39137,39139,39141,39142,39143,39146,39155,39158,39170,39175,39176,39185,39189,39190,39191,39194,39195,39196,39199,39202,39206,39207,39211,39217,39218,39219,39220,39221,39225,39226,39227,39228,39232,39233,39238,39239,39240,39245,39246,39252,39256,39257,39259,39260,39262,39263,39264,39323,39325,39327,39334,39344,39345,39346,39349,39353,39354,39357,39359,39363,39369,39379,39380,39385,39386,39388,39390,39399,39402,39403,39404,39408,39412,39413,39417,39421,39422,39426,39427,39428,39435,39436,39440,39441,39446,39454,39456,39458,39459,39460,39463,39469,39470,39475,39477,39478,39480,39495,39489,39492,39498,39499,39500,39502,39505,39508,39510,39517,39594,39596,39598,39599,39602,39604,39605,39606,39609,39611,39614,39615,39617,39619,39622,39624,39630,39632,39634,39637,39638,39639,39643,39644,39648,39652,39653,39655,39657,39660,39666,39667,39669,39673,39674,39677,39679,39680,39681,39682,39683,39684,39685,39688,39689,39691,39692,39693,39694,39696,39698,39702,39705,39707,39708,39712,39718,39723,39725,39731,39732,39733,39735,39737,39738,39741,39752,39755,39756,39765,39766,39767,39771,39774,39777,39779,39781,39782,39784,39786,39787,39788,39789,39790,39795,39797,39799,39800,39801,39807,39808,39812,39813,39814,39815,39817,39818,39819,39821,39823,39824,39828,39834,39837,39838,39846,39847,39849,39852,39856,39857,39858,39863,39864,39867,39868,39870,39871,39873,39879,39880,39886,39888,39895,39896,39901,39903,39909,39911,39914,39915,39919,39923,39927,39928,39929,39930,39933,39935,39936,39938,39947,39951,39953,39958,39960,39961,39962,39964,39966,39970,39971,39974,39975,39976,39977,39978,39985,39989,39990,39991,39997,40001,40003,40004,40005,40009,40010,40014,40015,40016,40019,40020,40022,40024,40027,40029,40030,40031,40035,40041,40042,40028,40043,40040,40046,40048,40050,40053,40055,40059,40166,40178,40183,40185,40203,40194,40209,40215,40216,40220,40221,40222,40239,40240,40242,40243,40244,40250,40252,40261,40253,40258,40259,40263,40266,40275,40276,40287,40291,40290,40293,40297,40298,40299,40304,40310,40311,40315,40316,40318,40323,40324,40326,40330,40333,40334,40338,40339,40341,40342,40343,40344,40353,40362,40364,40366,40369,40373,40377,40380,40383,40387,40391,40393,40394,40404,40405,40406,40407,40410,40414,40415,40416,40421,40423,40425,40427,40430,40432,40435,40436,40446,40458,40450,40455,40462,40464,40465,40466,40469,40470,40473,40476,40477,40570,40571,40572,40576,40578,40579,40580,40581,40583,40590,40591,40598,40600,40603,40606,40612,40616,40620,40622,40623,40624,40627,40628,40629,40646,40648,40651,40661,40671,40676,40679,40684,40685,40686,40688,40689,40690,40693,40696,40703,40706,40707,40713,40719,40720,40721,40722,40724,40726,40727,40729,40730,40731,40735,40738,40742,40746,40747,40751,40753,40754,40756,40759,40761,40762,40764,40765,40767,40769,40771,40772,40773,40774,40775,40787,40789,40790,40791,40792,40794,40797,40798,40808,40809,40813,40814,40815,40816,40817,40819,40821,40826,40829,40847,40848,40849,40850,40852,40854,40855,40862,40865,40866,40867,40869,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160],"iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],"iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729],"iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729],"iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119],"iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null],"iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],"iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],"iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312],"iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217],"iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255],"iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],"iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255],"koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],"koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],"macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711],"windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null],"windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],"windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103],"windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],"windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],"windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255],"windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],"windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746],"windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729],"windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255],"x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364]};// For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + })(this||{});},{}],109:[function(require,module,exports){// This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + /** + * @fileoverview Global |this| required for resolving indexes in node. + * @suppress {globalThis} + */(function(global){// If we're in node require encoding-indexes and attach it to the global. + if(typeof module!=="undefined"&&module.exports&&!global["encoding-indexes"]){global["encoding-indexes"]=require("./encoding-indexes.js")["encoding-indexes"];}// + // Utilities + // + /** + * @param {number} a The number to test. + * @param {number} min The minimum value in the range, inclusive. + * @param {number} max The maximum value in the range, inclusive. + * @return {boolean} True if a >= min and a <= max. + */function inRange(a,min,max){return min<=a&&a<=max;}/** + * @param {!Array.<*>} array The array to check. + * @param {*} item The item to look for in the array. + * @return {boolean} True if the item appears in the array. + */function includes(array,item){return array.indexOf(item)!==-1;}var floor=Math.floor;/** + * @param {*} o + * @return {Object} + */function ToDictionary(o){if(o===undefined)return {};if(o===Object(o))return o;throw TypeError('Could not convert argument to dictionary');}/** + * @param {string} string Input string of UTF-16 code units. + * @return {!Array.} Code points. + */function stringToCodePoints(string){// https://heycam.github.io/webidl/#dfn-obtain-unicode + // 1. Let S be the DOMString value. + var s=String(string);// 2. Let n be the length of S. + var n=s.length;// 3. Initialize i to 0. + var i=0;// 4. Initialize U to be an empty sequence of Unicode characters. + var u=[];// 5. While i < n: + while(i 0xDFFF + if(c<0xD800||c>0xDFFF){// Append to U the Unicode character with code point c. + u.push(c);}// 0xDC00 ≤ c ≤ 0xDFFF + else if(0xDC00<=c&&c<=0xDFFF){// Append to U a U+FFFD REPLACEMENT CHARACTER. + u.push(0xFFFD);}// 0xD800 ≤ c ≤ 0xDBFF + else if(0xD800<=c&&c<=0xDBFF){// 1. If i = n−1, then append to U a U+FFFD REPLACEMENT + // CHARACTER. + if(i===n-1){u.push(0xFFFD);}// 2. Otherwise, i < n−1: + else {// 1. Let d be the code unit in S at index i+1. + var d=s.charCodeAt(i+1);// 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: + if(0xDC00<=d&&d<=0xDFFF){// 1. Let a be c & 0x3FF. + var a=c&0x3FF;// 2. Let b be d & 0x3FF. + var b=d&0x3FF;// 3. Append to U the Unicode character with code point + // 2^16+2^10*a+b. + u.push(0x10000+(a<<10)+b);// 4. Set i to i+1. + i+=1;}// 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a + // U+FFFD REPLACEMENT CHARACTER. + else {u.push(0xFFFD);}}}// 3. Set i to i+1. + i+=1;}// 6. Return U. + return u;}/** + * @param {!Array.} code_points Array of code points. + * @return {string} string String of UTF-16 code units. + */function codePointsToString(code_points){var s='';for(var i=0;i>10)+0xD800,(cp&0x3FF)+0xDC00);}}return s;}// + // Implementation of Encoding specification + // https://encoding.spec.whatwg.org/ + // + // + // 4. Terminology + // + /** + * An ASCII byte is a byte in the range 0x00 to 0x7F, inclusive. + * @param {number} a The number to test. + * @return {boolean} True if a is in the range 0x00 to 0x7F, inclusive. + */function isASCIIByte(a){return 0x00<=a&&a<=0x7F;}/** + * An ASCII code point is a code point in the range U+0000 to + * U+007F, inclusive. + */var isASCIICodePoint=isASCIIByte;/** + * End-of-stream is a special token that signifies no more tokens + * are in the stream. + * @const + */var end_of_stream=-1;/** + * A stream represents an ordered sequence of tokens. + * + * @constructor + * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide + * the stream. + */function Stream(tokens){/** @type {!Array.} */this.tokens=[].slice.call(tokens);// Reversed as push/pop is more efficient than shift/unshift. + this.tokens.reverse();}Stream.prototype={/** + * @return {boolean} True if end-of-stream has been hit. + */endOfStream:function endOfStream(){return !this.tokens.length;},/** + * When a token is read from a stream, the first token in the + * stream must be returned and subsequently removed, and + * end-of-stream must be returned otherwise. + * + * @return {number} Get the next token from the stream, or + * end_of_stream. + */read:function read(){if(!this.tokens.length)return end_of_stream;return this.tokens.pop();},/** + * When one or more tokens are prepended to a stream, those tokens + * must be inserted, in given order, before the first token in the + * stream. + * + * @param {(number|!Array.)} token The token(s) to prepend to the + * stream. + */prepend:function prepend(token){if(Array.isArray(token)){var tokens=/**@type {!Array.}*/token;while(tokens.length)this.tokens.push(tokens.pop());}else {this.tokens.push(token);}},/** + * When one or more tokens are pushed to a stream, those tokens + * must be inserted, in given order, after the last token in the + * stream. + * + * @param {(number|!Array.)} token The tokens(s) to push to the + * stream. + */push:function push(token){if(Array.isArray(token)){var tokens=/**@type {!Array.}*/token;while(tokens.length)this.tokens.unshift(tokens.shift());}else {this.tokens.unshift(token);}}};// + // 5. Encodings + // + // 5.1 Encoders and decoders + /** @const */var finished=-1;/** + * @param {boolean} fatal If true, decoding errors raise an exception. + * @param {number=} opt_code_point Override the standard fallback code point. + * @return {number} The code point to insert on a decoding error. + */function decoderError(fatal,opt_code_point){if(fatal)throw TypeError('Decoder error');return opt_code_point||0xFFFD;}/** + * @param {number} code_point The code point that could not be encoded. + * @return {number} Always throws, no value is actually returned. + */function encoderError(code_point){throw TypeError('The code point '+code_point+' could not be encoded.');}// 5.2 Names and labels + // TODO: Define @typedef for Encoding: {name:string,labels:Array.} + // https://github.com/google/closure-compiler/issues/247 + /** + * @param {string} label The encoding label. + * @return {?{name:string,labels:Array.}} + */function getEncoding(label){// 1. Remove any leading and trailing ASCII whitespace from label. + label=String(label).trim().toLowerCase();// 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, return the corresponding + // encoding, and failure otherwise. + if(Object.prototype.hasOwnProperty.call(label_to_encoding,label)){return label_to_encoding[label];}return null;}/** + * Encodings table: https://encoding.spec.whatwg.org/encodings.json + * @const + * @type {!Array.<{ + * heading: string, + * encodings: Array.<{name:string,labels:Array.}> + * }>} + */var encodings=[{"encodings":[{"labels":["unicode-1-1-utf-8","utf-8","utf8"],"name":"UTF-8"}],"heading":"The Encoding"},{"encodings":[{"labels":["866","cp866","csibm866","ibm866"],"name":"IBM866"},{"labels":["csisolatin2","iso-8859-2","iso-ir-101","iso8859-2","iso88592","iso_8859-2","iso_8859-2:1987","l2","latin2"],"name":"ISO-8859-2"},{"labels":["csisolatin3","iso-8859-3","iso-ir-109","iso8859-3","iso88593","iso_8859-3","iso_8859-3:1988","l3","latin3"],"name":"ISO-8859-3"},{"labels":["csisolatin4","iso-8859-4","iso-ir-110","iso8859-4","iso88594","iso_8859-4","iso_8859-4:1988","l4","latin4"],"name":"ISO-8859-4"},{"labels":["csisolatincyrillic","cyrillic","iso-8859-5","iso-ir-144","iso8859-5","iso88595","iso_8859-5","iso_8859-5:1988"],"name":"ISO-8859-5"},{"labels":["arabic","asmo-708","csiso88596e","csiso88596i","csisolatinarabic","ecma-114","iso-8859-6","iso-8859-6-e","iso-8859-6-i","iso-ir-127","iso8859-6","iso88596","iso_8859-6","iso_8859-6:1987"],"name":"ISO-8859-6"},{"labels":["csisolatingreek","ecma-118","elot_928","greek","greek8","iso-8859-7","iso-ir-126","iso8859-7","iso88597","iso_8859-7","iso_8859-7:1987","sun_eu_greek"],"name":"ISO-8859-7"},{"labels":["csiso88598e","csisolatinhebrew","hebrew","iso-8859-8","iso-8859-8-e","iso-ir-138","iso8859-8","iso88598","iso_8859-8","iso_8859-8:1988","visual"],"name":"ISO-8859-8"},{"labels":["csiso88598i","iso-8859-8-i","logical"],"name":"ISO-8859-8-I"},{"labels":["csisolatin6","iso-8859-10","iso-ir-157","iso8859-10","iso885910","l6","latin6"],"name":"ISO-8859-10"},{"labels":["iso-8859-13","iso8859-13","iso885913"],"name":"ISO-8859-13"},{"labels":["iso-8859-14","iso8859-14","iso885914"],"name":"ISO-8859-14"},{"labels":["csisolatin9","iso-8859-15","iso8859-15","iso885915","iso_8859-15","l9"],"name":"ISO-8859-15"},{"labels":["iso-8859-16"],"name":"ISO-8859-16"},{"labels":["cskoi8r","koi","koi8","koi8-r","koi8_r"],"name":"KOI8-R"},{"labels":["koi8-ru","koi8-u"],"name":"KOI8-U"},{"labels":["csmacintosh","mac","macintosh","x-mac-roman"],"name":"macintosh"},{"labels":["dos-874","iso-8859-11","iso8859-11","iso885911","tis-620","windows-874"],"name":"windows-874"},{"labels":["cp1250","windows-1250","x-cp1250"],"name":"windows-1250"},{"labels":["cp1251","windows-1251","x-cp1251"],"name":"windows-1251"},{"labels":["ansi_x3.4-1968","ascii","cp1252","cp819","csisolatin1","ibm819","iso-8859-1","iso-ir-100","iso8859-1","iso88591","iso_8859-1","iso_8859-1:1987","l1","latin1","us-ascii","windows-1252","x-cp1252"],"name":"windows-1252"},{"labels":["cp1253","windows-1253","x-cp1253"],"name":"windows-1253"},{"labels":["cp1254","csisolatin5","iso-8859-9","iso-ir-148","iso8859-9","iso88599","iso_8859-9","iso_8859-9:1989","l5","latin5","windows-1254","x-cp1254"],"name":"windows-1254"},{"labels":["cp1255","windows-1255","x-cp1255"],"name":"windows-1255"},{"labels":["cp1256","windows-1256","x-cp1256"],"name":"windows-1256"},{"labels":["cp1257","windows-1257","x-cp1257"],"name":"windows-1257"},{"labels":["cp1258","windows-1258","x-cp1258"],"name":"windows-1258"},{"labels":["x-mac-cyrillic","x-mac-ukrainian"],"name":"x-mac-cyrillic"}],"heading":"Legacy single-byte encodings"},{"encodings":[{"labels":["chinese","csgb2312","csiso58gb231280","gb2312","gb_2312","gb_2312-80","gbk","iso-ir-58","x-gbk"],"name":"GBK"},{"labels":["gb18030"],"name":"gb18030"}],"heading":"Legacy multi-byte Chinese (simplified) encodings"},{"encodings":[{"labels":["big5","big5-hkscs","cn-big5","csbig5","x-x-big5"],"name":"Big5"}],"heading":"Legacy multi-byte Chinese (traditional) encodings"},{"encodings":[{"labels":["cseucpkdfmtjapanese","euc-jp","x-euc-jp"],"name":"EUC-JP"},{"labels":["csiso2022jp","iso-2022-jp"],"name":"ISO-2022-JP"},{"labels":["csshiftjis","ms932","ms_kanji","shift-jis","shift_jis","sjis","windows-31j","x-sjis"],"name":"Shift_JIS"}],"heading":"Legacy multi-byte Japanese encodings"},{"encodings":[{"labels":["cseuckr","csksc56011987","euc-kr","iso-ir-149","korean","ks_c_5601-1987","ks_c_5601-1989","ksc5601","ksc_5601","windows-949"],"name":"EUC-KR"}],"heading":"Legacy multi-byte Korean encodings"},{"encodings":[{"labels":["csiso2022kr","hz-gb-2312","iso-2022-cn","iso-2022-cn-ext","iso-2022-kr"],"name":"replacement"},{"labels":["utf-16be"],"name":"UTF-16BE"},{"labels":["utf-16","utf-16le"],"name":"UTF-16LE"},{"labels":["x-user-defined"],"name":"x-user-defined"}],"heading":"Legacy miscellaneous encodings"}];// Label to encoding registry. + /** @type {Object.}>} */var label_to_encoding={};encodings.forEach(function(category){category.encodings.forEach(function(encoding){encoding.labels.forEach(function(label){label_to_encoding[label]=encoding;});});});// Registry of of encoder/decoder factories, by encoding name. + /** @type {Object.} */var encoders={};/** @type {Object.} */var decoders={};// + // 6. Indexes + // + /** + * @param {number} pointer The |pointer| to search for. + * @param {(!Array.|undefined)} index The |index| to search within. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in |index|. + */function indexCodePointFor(pointer,index){if(!index)return null;return index[pointer]||null;}/** + * @param {number} code_point The |code point| to search for. + * @param {!Array.} index The |index| to search within. + * @return {?number} The first pointer corresponding to |code point| in + * |index|, or null if |code point| is not in |index|. + */function indexPointerFor(code_point,index){var pointer=index.indexOf(code_point);return pointer===-1?null:pointer;}/** + * @param {string} name Name of the index. + * @return {(!Array.|!Array.>)} + * */function index(name){if(!('encoding-indexes'in global)){throw Error("Indexes missing."+" Did you forget to include encoding-indexes.js first?");}return global['encoding-indexes'][name];}/** + * @param {number} pointer The |pointer| to search for in the gb18030 index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the gb18030 index. + */function indexGB18030RangesCodePointFor(pointer){// 1. If pointer is greater than 39419 and less than 189000, or + // pointer is greater than 1237575, return null. + if(pointer>39419&&pointer<189000||pointer>1237575)return null;// 2. If pointer is 7457, return code point U+E7C7. + if(pointer===7457)return 0xE7C7;// 3. Let offset be the last pointer in index gb18030 ranges that + // is equal to or less than pointer and let code point offset be + // its corresponding code point. + var offset=0;var code_point_offset=0;var idx=index('gb18030-ranges');var i;for(i=0;i} */var entry=idx[i];if(entry[0]<=pointer){offset=entry[0];code_point_offset=entry[1];}else {break;}}// 4. Return a code point whose value is code point offset + + // pointer − offset. + return code_point_offset+pointer-offset;}/** + * @param {number} code_point The |code point| to locate in the gb18030 index. + * @return {number} The first pointer corresponding to |code point| in the + * gb18030 index. + */function indexGB18030RangesPointerFor(code_point){// 1. If code point is U+E7C7, return pointer 7457. + if(code_point===0xE7C7)return 7457;// 2. Let offset be the last code point in index gb18030 ranges + // that is equal to or less than code point and let pointer offset + // be its corresponding pointer. + var offset=0;var pointer_offset=0;var idx=index('gb18030-ranges');var i;for(i=0;i} */var entry=idx[i];if(entry[1]<=code_point){offset=entry[1];pointer_offset=entry[0];}else {break;}}// 3. Return a pointer whose value is pointer offset + code point + // − offset. + return pointer_offset+code_point-offset;}/** + * @param {number} code_point The |code_point| to search for in the Shift_JIS + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the Shift_JIS index. + */function indexShiftJISPointerFor(code_point){// 1. Let index be index jis0208 excluding all entries whose + // pointer is in the range 8272 to 8835, inclusive. + shift_jis_index=shift_jis_index||index('jis0208').map(function(code_point,pointer){return inRange(pointer,8272,8835)?null:code_point;});var index_=shift_jis_index;// 2. Return the index pointer for code point in index. + return index_.indexOf(code_point);}var shift_jis_index;/** + * @param {number} code_point The |code_point| to search for in the big5 + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the big5 index. + */function indexBig5PointerFor(code_point){// 1. Let index be index Big5 excluding all entries whose pointer + big5_index_no_hkscs=big5_index_no_hkscs||index('big5').map(function(code_point,pointer){return pointer<(0xA1-0x81)*157?null:code_point;});var index_=big5_index_no_hkscs;// 2. If code point is U+2550, U+255E, U+2561, U+256A, U+5341, or + // U+5345, return the last pointer corresponding to code point in + // index. + if(code_point===0x2550||code_point===0x255E||code_point===0x2561||code_point===0x256A||code_point===0x5341||code_point===0x5345){return index_.lastIndexOf(code_point);}// 3. Return the index pointer for code point in index. + return indexPointerFor(code_point,index_);}var big5_index_no_hkscs;// + // 8. API + // + /** @const */var DEFAULT_ENCODING='utf-8';// 8.1 Interface TextDecoder + /** + * @constructor + * @param {string=} label The label of the encoding; + * defaults to 'utf-8'. + * @param {Object=} options + */function TextDecoder(label,options){// Web IDL conventions + if(!(this instanceof TextDecoder))throw TypeError('Called as a function. Did you forget \'new\'?');label=label!==undefined?String(label):DEFAULT_ENCODING;options=ToDictionary(options);// A TextDecoder object has an associated encoding, decoder, + // stream, ignore BOM flag (initially unset), BOM seen flag + // (initially unset), error mode (initially replacement), and do + // not flush flag (initially unset). + /** @private */this._encoding=null;/** @private @type {?Decoder} */this._decoder=null;/** @private @type {boolean} */this._ignoreBOM=false;/** @private @type {boolean} */this._BOMseen=false;/** @private @type {string} */this._error_mode='replacement';/** @private @type {boolean} */this._do_not_flush=false;// 1. Let encoding be the result of getting an encoding from + // label. + var encoding=getEncoding(label);// 2. If encoding is failure or replacement, throw a RangeError. + if(encoding===null||encoding.name==='replacement')throw RangeError('Unknown encoding: '+label);if(!decoders[encoding.name]){throw Error('Decoder not present.'+' Did you forget to include encoding-indexes.js first?');}// 3. Let dec be a new TextDecoder object. + var dec=this;// 4. Set dec's encoding to encoding. + dec._encoding=encoding;// 5. If options's fatal member is true, set dec's error mode to + // fatal. + if(Boolean(options['fatal']))dec._error_mode='fatal';// 6. If options's ignoreBOM member is true, set dec's ignore BOM + // flag. + if(Boolean(options['ignoreBOM']))dec._ignoreBOM=true;// For pre-ES5 runtimes: + if(!Object.defineProperty){this.encoding=dec._encoding.name.toLowerCase();this.fatal=dec._error_mode==='fatal';this.ignoreBOM=dec._ignoreBOM;}// 7. Return dec. + return dec;}if(Object.defineProperty){// The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextDecoder.prototype,'encoding',{/** @this {TextDecoder} */get:function get(){return this._encoding.name.toLowerCase();}});// The fatal attribute's getter must return true if error mode + // is fatal, and false otherwise. + Object.defineProperty(TextDecoder.prototype,'fatal',{/** @this {TextDecoder} */get:function get(){return this._error_mode==='fatal';}});// The ignoreBOM attribute's getter must return true if ignore + // BOM flag is set, and false otherwise. + Object.defineProperty(TextDecoder.prototype,'ignoreBOM',{/** @this {TextDecoder} */get:function get(){return this._ignoreBOM;}});}/** + * @param {BufferSource=} input The buffer of bytes to decode. + * @param {Object=} options + * @return {string} The decoded string. + */TextDecoder.prototype.decode=function decode(input,options){var bytes;if(_typeof$1(input)==='object'&&input instanceof ArrayBuffer){bytes=new Uint8Array(input);}else if(_typeof$1(input)==='object'&&'buffer'in input&&input.buffer instanceof ArrayBuffer){bytes=new Uint8Array(input.buffer,input.byteOffset,input.byteLength);}else {bytes=new Uint8Array(0);}options=ToDictionary(options);// 1. If the do not flush flag is unset, set decoder to a new + // encoding's decoder, set stream to a new stream, and unset the + // BOM seen flag. + if(!this._do_not_flush){this._decoder=decoders[this._encoding.name]({fatal:this._error_mode==='fatal'});this._BOMseen=false;}// 2. If options's stream is true, set the do not flush flag, and + // unset the do not flush flag otherwise. + this._do_not_flush=Boolean(options['stream']);// 3. If input is given, push a copy of input to stream. + // TODO: Align with spec algorithm - maintain stream on instance. + var input_stream=new Stream(bytes);// 4. Let output be a new stream. + var output=[];/** @type {?(number|!Array.)} */var result;// 5. While true: + while(true){// 1. Let token be the result of reading from stream. + var token=input_stream.read();// 2. If token is end-of-stream and the do not flush flag is + // set, return output, serialized. + // TODO: Align with spec algorithm. + if(token===end_of_stream)break;// 3. Otherwise, run these subsubsteps: + // 1. Let result be the result of processing token for decoder, + // stream, output, and error mode. + result=this._decoder.handler(input_stream,token);// 2. If result is finished, return output, serialized. + if(result===finished)break;if(result!==null){if(Array.isArray(result))output.push.apply(output,/**@type {!Array.}*/result);else output.push(result);}// 3. Otherwise, if result is error, throw a TypeError. + // (Thrown in handler) + // 4. Otherwise, do nothing. + }// TODO: Align with spec algorithm. + if(!this._do_not_flush){do{result=this._decoder.handler(input_stream,input_stream.read());if(result===finished)break;if(result===null)continue;if(Array.isArray(result))output.push.apply(output,/**@type {!Array.}*/result);else output.push(result);}while(!input_stream.endOfStream());this._decoder=null;}// A TextDecoder object also has an associated serialize stream + // algorithm... + /** + * @param {!Array.} stream + * @return {string} + * @this {TextDecoder} + */function serializeStream(stream){// 1. Let token be the result of reading from stream. + // (Done in-place on array, rather than as a stream) + // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore + // BOM flag and BOM seen flag are unset, run these subsubsteps: + if(includes(['UTF-8','UTF-16LE','UTF-16BE'],this._encoding.name)&&!this._ignoreBOM&&!this._BOMseen){if(stream.length>0&&stream[0]===0xFEFF){// 1. If token is U+FEFF, set BOM seen flag. + this._BOMseen=true;stream.shift();}else if(stream.length>0){// 2. Otherwise, if token is not end-of-stream, set BOM seen + // flag and append token to stream. + this._BOMseen=true;}else;}// 4. Otherwise, return output. + return codePointsToString(stream);}return serializeStream.call(this,output);};// 8.2 Interface TextEncoder + /** + * @constructor + * @param {string=} label The label of the encoding. NONSTANDARD. + * @param {Object=} options NONSTANDARD. + */function TextEncoder(label,options){// Web IDL conventions + if(!(this instanceof TextEncoder))throw TypeError('Called as a function. Did you forget \'new\'?');options=ToDictionary(options);// A TextEncoder object has an associated encoding and encoder. + /** @private */this._encoding=null;/** @private @type {?Encoder} */this._encoder=null;// Non-standard + /** @private @type {boolean} */this._do_not_flush=false;/** @private @type {string} */this._fatal=Boolean(options['fatal'])?'fatal':'replacement';// 1. Let enc be a new TextEncoder object. + var enc=this;// 2. Set enc's encoding to UTF-8's encoder. + if(Boolean(options['NONSTANDARD_allowLegacyEncoding'])){// NONSTANDARD behavior. + label=label!==undefined?String(label):DEFAULT_ENCODING;var encoding=getEncoding(label);if(encoding===null||encoding.name==='replacement')throw RangeError('Unknown encoding: '+label);if(!encoders[encoding.name]){throw Error('Encoder not present.'+' Did you forget to include encoding-indexes.js first?');}enc._encoding=encoding;}else {// Standard behavior. + enc._encoding=getEncoding('utf-8');if(label!==undefined&&'console'in global){console.warn('TextEncoder constructor called with encoding label, '+'which is ignored.');}}// For pre-ES5 runtimes: + if(!Object.defineProperty)this.encoding=enc._encoding.name.toLowerCase();// 3. Return enc. + return enc;}if(Object.defineProperty){// The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextEncoder.prototype,'encoding',{/** @this {TextEncoder} */get:function get(){return this._encoding.name.toLowerCase();}});}/** + * @param {string=} opt_string The string to encode. + * @param {Object=} options + * @return {!Uint8Array} Encoded bytes, as a Uint8Array. + */TextEncoder.prototype.encode=function encode(opt_string,options){opt_string=opt_string===undefined?'':String(opt_string);options=ToDictionary(options);// NOTE: This option is nonstandard. None of the encodings + // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when + // the input is a USVString so streaming is not necessary. + if(!this._do_not_flush)this._encoder=encoders[this._encoding.name]({fatal:this._fatal==='fatal'});this._do_not_flush=Boolean(options['stream']);// 1. Convert input to a stream. + var input=new Stream(stringToCodePoints(opt_string));// 2. Let output be a new stream + var output=[];/** @type {?(number|!Array.)} */var result;// 3. While true, run these substeps: + while(true){// 1. Let token be the result of reading from input. + var token=input.read();if(token===end_of_stream)break;// 2. Let result be the result of processing token for encoder, + // input, output. + result=this._encoder.handler(input,token);if(result===finished)break;if(Array.isArray(result))output.push.apply(output,/**@type {!Array.}*/result);else output.push(result);}// TODO: Align with spec algorithm. + if(!this._do_not_flush){while(true){result=this._encoder.handler(input,input.read());if(result===finished)break;if(Array.isArray(result))output.push.apply(output,/**@type {!Array.}*/result);else output.push(result);}this._encoder=null;}// 3. If result is finished, convert output into a byte sequence, + // and then return a Uint8Array object wrapping an ArrayBuffer + // containing output. + return new Uint8Array(output);};// + // 9. The encoding + // + // 9.1 utf-8 + // 9.1.1 utf-8 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function UTF8Decoder(options){var fatal=options.fatal;// utf-8's decoder's has an associated utf-8 code point, utf-8 + // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 + // lower boundary (initially 0x80), and a utf-8 upper boundary + // (initially 0xBF). + var/** @type {number} */utf8_code_point=0,/** @type {number} */utf8_bytes_seen=0,/** @type {number} */utf8_bytes_needed=0,/** @type {number} */utf8_lower_boundary=0x80,/** @type {number} */utf8_upper_boundary=0xBF;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and utf-8 bytes needed is not 0, + // set utf-8 bytes needed to 0 and return error. + if(bite===end_of_stream&&utf8_bytes_needed!==0){utf8_bytes_needed=0;return decoderError(fatal);}// 2. If byte is end-of-stream, return finished. + if(bite===end_of_stream)return finished;// 3. If utf-8 bytes needed is 0, based on byte: + if(utf8_bytes_needed===0){// 0x00 to 0x7F + if(inRange(bite,0x00,0x7F)){// Return a code point whose value is byte. + return bite;}// 0xC2 to 0xDF + else if(inRange(bite,0xC2,0xDF)){// 1. Set utf-8 bytes needed to 1. + utf8_bytes_needed=1;// 2. Set UTF-8 code point to byte & 0x1F. + utf8_code_point=bite&0x1F;}// 0xE0 to 0xEF + else if(inRange(bite,0xE0,0xEF)){// 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. + if(bite===0xE0)utf8_lower_boundary=0xA0;// 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. + if(bite===0xED)utf8_upper_boundary=0x9F;// 3. Set utf-8 bytes needed to 2. + utf8_bytes_needed=2;// 4. Set UTF-8 code point to byte & 0xF. + utf8_code_point=bite&0xF;}// 0xF0 to 0xF4 + else if(inRange(bite,0xF0,0xF4)){// 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. + if(bite===0xF0)utf8_lower_boundary=0x90;// 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. + if(bite===0xF4)utf8_upper_boundary=0x8F;// 3. Set utf-8 bytes needed to 3. + utf8_bytes_needed=3;// 4. Set UTF-8 code point to byte & 0x7. + utf8_code_point=bite&0x7;}// Otherwise + else {// Return error. + return decoderError(fatal);}// Return continue. + return null;}// 4. If byte is not in the range utf-8 lower boundary to utf-8 + // upper boundary, inclusive, run these substeps: + if(!inRange(bite,utf8_lower_boundary,utf8_upper_boundary)){// 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 + // bytes seen to 0, set utf-8 lower boundary to 0x80, and set + // utf-8 upper boundary to 0xBF. + utf8_code_point=utf8_bytes_needed=utf8_bytes_seen=0;utf8_lower_boundary=0x80;utf8_upper_boundary=0xBF;// 2. Prepend byte to stream. + stream.prepend(bite);// 3. Return error. + return decoderError(fatal);}// 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary + // to 0xBF. + utf8_lower_boundary=0x80;utf8_upper_boundary=0xBF;// 6. Set UTF-8 code point to (UTF-8 code point << 6) | (byte & + // 0x3F) + utf8_code_point=utf8_code_point<<6|bite&0x3F;// 7. Increase utf-8 bytes seen by one. + utf8_bytes_seen+=1;// 8. If utf-8 bytes seen is not equal to utf-8 bytes needed, + // continue. + if(utf8_bytes_seen!==utf8_bytes_needed)return null;// 9. Let code point be utf-8 code point. + var code_point=utf8_code_point;// 10. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes + // seen to 0. + utf8_code_point=utf8_bytes_needed=utf8_bytes_seen=0;// 11. Return a code point whose value is code point. + return code_point;};}// 9.1.2 utf-8 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function UTF8Encoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. Set count and offset based on the range code point is in: + var count,offset;// U+0080 to U+07FF, inclusive: + if(inRange(code_point,0x0080,0x07FF)){// 1 and 0xC0 + count=1;offset=0xC0;}// U+0800 to U+FFFF, inclusive: + else if(inRange(code_point,0x0800,0xFFFF)){// 2 and 0xE0 + count=2;offset=0xE0;}// U+10000 to U+10FFFF, inclusive: + else if(inRange(code_point,0x10000,0x10FFFF)){// 3 and 0xF0 + count=3;offset=0xF0;}// 4. Let bytes be a byte sequence whose first byte is (code + // point >> (6 × count)) + offset. + var bytes=[(code_point>>6*count)+offset];// 5. Run these substeps while count is greater than 0: + while(count>0){// 1. Set temp to code point >> (6 × (count − 1)). + var temp=code_point>>6*(count-1);// 2. Append to bytes 0x80 | (temp & 0x3F). + bytes.push(0x80|temp&0x3F);// 3. Decrease count by one. + count-=1;}// 6. Return bytes bytes, in order. + return bytes;};}/** @param {{fatal: boolean}} options */encoders['UTF-8']=function(options){return new UTF8Encoder(options);};/** @param {{fatal: boolean}} options */decoders['UTF-8']=function(options){return new UTF8Decoder(options);};// + // 10. Legacy single-byte encodings + // + // 10.1 single-byte decoder + /** + * @constructor + * @implements {Decoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */function SingleByteDecoder(index,options){var fatal=options.fatal;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream, return finished. + if(bite===end_of_stream)return finished;// 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 3. Let code point be the index code point for byte − 0x80 in + // index single-byte. + var code_point=index[bite-0x80];// 4. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 5. Return a code point whose value is code point. + return code_point;};}// 10.2 single-byte encoder + /** + * @constructor + * @implements {Encoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */function SingleByteEncoder(index,options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. Let pointer be the index pointer for code point in index + // single-byte. + var pointer=indexPointerFor(code_point,index);// 4. If pointer is null, return error with code point. + if(pointer===null)encoderError(code_point);// 5. Return a byte whose value is pointer + 0x80. + return pointer+0x80;};}(function(){if(!('encoding-indexes'in global))return;encodings.forEach(function(category){if(category.heading!=='Legacy single-byte encodings')return;category.encodings.forEach(function(encoding){var name=encoding.name;var idx=index(name.toLowerCase());/** @param {{fatal: boolean}} options */decoders[name]=function(options){return new SingleByteDecoder(idx,options);};/** @param {{fatal: boolean}} options */encoders[name]=function(options){return new SingleByteEncoder(idx,options);};});});})();// + // 11. Legacy multi-byte Chinese (simplified) encodings + // + // 11.1 gbk + // 11.1.1 gbk decoder + // gbk's decoder is gb18030's decoder. + /** @param {{fatal: boolean}} options */decoders['GBK']=function(options){return new GB18030Decoder(options);};// 11.1.2 gbk encoder + // gbk's encoder is gb18030's encoder with its gbk flag set. + /** @param {{fatal: boolean}} options */encoders['GBK']=function(options){return new GB18030Encoder(options,true);};// 11.2 gb18030 + // 11.2.1 gb18030 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function GB18030Decoder(options){var fatal=options.fatal;// gb18030's decoder has an associated gb18030 first, gb18030 + // second, and gb18030 third (all initially 0x00). + var/** @type {number} */gb18030_first=0x00,/** @type {number} */gb18030_second=0x00,/** @type {number} */gb18030_third=0x00;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and gb18030 first, gb18030 + // second, and gb18030 third are 0x00, return finished. + if(bite===end_of_stream&&gb18030_first===0x00&&gb18030_second===0x00&&gb18030_third===0x00){return finished;}// 2. If byte is end-of-stream, and gb18030 first, gb18030 + // second, or gb18030 third is not 0x00, set gb18030 first, + // gb18030 second, and gb18030 third to 0x00, and return error. + if(bite===end_of_stream&&(gb18030_first!==0x00||gb18030_second!==0x00||gb18030_third!==0x00)){gb18030_first=0x00;gb18030_second=0x00;gb18030_third=0x00;decoderError(fatal);}var code_point;// 3. If gb18030 third is not 0x00, run these substeps: + if(gb18030_third!==0x00){// 1. Let code point be null. + code_point=null;// 2. If byte is in the range 0x30 to 0x39, inclusive, set + // code point to the index gb18030 ranges code point for + // (((gb18030 first − 0x81) × 10 + gb18030 second − 0x30) × + // 126 + gb18030 third − 0x81) × 10 + byte − 0x30. + if(inRange(bite,0x30,0x39)){code_point=indexGB18030RangesCodePointFor((((gb18030_first-0x81)*10+gb18030_second-0x30)*126+gb18030_third-0x81)*10+bite-0x30);}// 3. Let buffer be a byte sequence consisting of gb18030 + // second, gb18030 third, and byte, in order. + var buffer=[gb18030_second,gb18030_third,bite];// 4. Set gb18030 first, gb18030 second, and gb18030 third to + // 0x00. + gb18030_first=0x00;gb18030_second=0x00;gb18030_third=0x00;// 5. If code point is null, prepend buffer to stream and + // return error. + if(code_point===null){stream.prepend(buffer);return decoderError(fatal);}// 6. Return a code point whose value is code point. + return code_point;}// 4. If gb18030 second is not 0x00, run these substeps: + if(gb18030_second!==0x00){// 1. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 third to byte and return continue. + if(inRange(bite,0x81,0xFE)){gb18030_third=bite;return null;}// 2. Prepend gb18030 second followed by byte to stream, set + // gb18030 first and gb18030 second to 0x00, and return error. + stream.prepend([gb18030_second,bite]);gb18030_first=0x00;gb18030_second=0x00;return decoderError(fatal);}// 5. If gb18030 first is not 0x00, run these substeps: + if(gb18030_first!==0x00){// 1. If byte is in the range 0x30 to 0x39, inclusive, set + // gb18030 second to byte and return continue. + if(inRange(bite,0x30,0x39)){gb18030_second=bite;return null;}// 2. Let lead be gb18030 first, let pointer be null, and set + // gb18030 first to 0x00. + var lead=gb18030_first;var pointer=null;gb18030_first=0x00;// 3. Let offset be 0x40 if byte is less than 0x7F and 0x41 + // otherwise. + var offset=bite<0x7F?0x40:0x41;// 4. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 190 + + // (byte − offset). + if(inRange(bite,0x40,0x7E)||inRange(bite,0x80,0xFE))pointer=(lead-0x81)*190+(bite-offset);// 5. Let code point be null if pointer is null and the index + // code point for pointer in index gb18030 otherwise. + code_point=pointer===null?null:indexCodePointFor(pointer,index('gb18030'));// 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if(code_point===null&&isASCIIByte(bite))stream.prepend(bite);// 7. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 8. Return a code point whose value is code point. + return code_point;}// 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 7. If byte is 0x80, return code point U+20AC. + if(bite===0x80)return 0x20AC;// 8. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 first to byte and return continue. + if(inRange(bite,0x81,0xFE)){gb18030_first=bite;return null;}// 9. Return error. + return decoderError(fatal);};}// 11.2.2 gb18030 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + * @param {boolean=} gbk_flag + */function GB18030Encoder(options,gbk_flag){options.fatal;// gb18030's decoder has an associated gbk flag (initially unset). + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. If code point is U+E5E5, return error with code point. + if(code_point===0xE5E5)return encoderError(code_point);// 4. If the gbk flag is set and code point is U+20AC, return + // byte 0x80. + if(gbk_flag&&code_point===0x20AC)return 0x80;// 5. Let pointer be the index pointer for code point in index + // gb18030. + var pointer=indexPointerFor(code_point,index('gb18030'));// 6. If pointer is not null, run these substeps: + if(pointer!==null){// 1. Let lead be floor(pointer / 190) + 0x81. + var lead=floor(pointer/190)+0x81;// 2. Let trail be pointer % 190. + var trail=pointer%190;// 3. Let offset be 0x40 if trail is less than 0x3F and 0x41 otherwise. + var offset=trail<0x3F?0x40:0x41;// 4. Return two bytes whose values are lead and trail + offset. + return [lead,trail+offset];}// 7. If gbk flag is set, return error with code point. + if(gbk_flag)return encoderError(code_point);// 8. Set pointer to the index gb18030 ranges pointer for code + // point. + pointer=indexGB18030RangesPointerFor(code_point);// 9. Let byte1 be floor(pointer / 10 / 126 / 10). + var byte1=floor(pointer/10/126/10);// 10. Set pointer to pointer − byte1 × 10 × 126 × 10. + pointer=pointer-byte1*10*126*10;// 11. Let byte2 be floor(pointer / 10 / 126). + var byte2=floor(pointer/10/126);// 12. Set pointer to pointer − byte2 × 10 × 126. + pointer=pointer-byte2*10*126;// 13. Let byte3 be floor(pointer / 10). + var byte3=floor(pointer/10);// 14. Let byte4 be pointer − byte3 × 10. + var byte4=pointer-byte3*10;// 15. Return four bytes whose values are byte1 + 0x81, byte2 + + // 0x30, byte3 + 0x81, byte4 + 0x30. + return [byte1+0x81,byte2+0x30,byte3+0x81,byte4+0x30];};}/** @param {{fatal: boolean}} options */encoders['gb18030']=function(options){return new GB18030Encoder(options);};/** @param {{fatal: boolean}} options */decoders['gb18030']=function(options){return new GB18030Decoder(options);};// + // 12. Legacy multi-byte Chinese (traditional) encodings + // + // 12.1 Big5 + // 12.1.1 Big5 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function Big5Decoder(options){var fatal=options.fatal;// Big5's decoder has an associated Big5 lead (initially 0x00). + var/** @type {number} */Big5_lead=0x00;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and Big5 lead is not 0x00, set + // Big5 lead to 0x00 and return error. + if(bite===end_of_stream&&Big5_lead!==0x00){Big5_lead=0x00;return decoderError(fatal);}// 2. If byte is end-of-stream and Big5 lead is 0x00, return + // finished. + if(bite===end_of_stream&&Big5_lead===0x00)return finished;// 3. If Big5 lead is not 0x00, let lead be Big5 lead, let + // pointer be null, set Big5 lead to 0x00, and then run these + // substeps: + if(Big5_lead!==0x00){var lead=Big5_lead;var pointer=null;Big5_lead=0x00;// 1. Let offset be 0x40 if byte is less than 0x7F and 0x62 + // otherwise. + var offset=bite<0x7F?0x40:0x62;// 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 + + // (byte − offset). + if(inRange(bite,0x40,0x7E)||inRange(bite,0xA1,0xFE))pointer=(lead-0x81)*157+(bite-offset);// 3. If there is a row in the table below whose first column + // is pointer, return the two code points listed in its second + // column + // Pointer | Code points + // --------+-------------- + // 1133 | U+00CA U+0304 + // 1135 | U+00CA U+030C + // 1164 | U+00EA U+0304 + // 1166 | U+00EA U+030C + switch(pointer){case 1133:return [0x00CA,0x0304];case 1135:return [0x00CA,0x030C];case 1164:return [0x00EA,0x0304];case 1166:return [0x00EA,0x030C];}// 4. Let code point be null if pointer is null and the index + // code point for pointer in index Big5 otherwise. + var code_point=pointer===null?null:indexCodePointFor(pointer,index('big5'));// 5. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if(code_point===null&&isASCIIByte(bite))stream.prepend(bite);// 6. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 7. Return a code point whose value is code point. + return code_point;}// 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5 + // lead to byte and return continue. + if(inRange(bite,0x81,0xFE)){Big5_lead=bite;return null;}// 6. Return error. + return decoderError(fatal);};}// 12.1.2 Big5 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function Big5Encoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. Let pointer be the index Big5 pointer for code point. + var pointer=indexBig5PointerFor(code_point);// 4. If pointer is null, return error with code point. + if(pointer===null)return encoderError(code_point);// 5. Let lead be floor(pointer / 157) + 0x81. + var lead=floor(pointer/157)+0x81;// 6. If lead is less than 0xA1, return error with code point. + if(lead<0xA1)return encoderError(code_point);// 7. Let trail be pointer % 157. + var trail=pointer%157;// 8. Let offset be 0x40 if trail is less than 0x3F and 0x62 + // otherwise. + var offset=trail<0x3F?0x40:0x62;// Return two bytes whose values are lead and trail + offset. + return [lead,trail+offset];};}/** @param {{fatal: boolean}} options */encoders['Big5']=function(options){return new Big5Encoder(options);};/** @param {{fatal: boolean}} options */decoders['Big5']=function(options){return new Big5Decoder(options);};// + // 13. Legacy multi-byte Japanese encodings + // + // 13.1 euc-jp + // 13.1.1 euc-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function EUCJPDecoder(options){var fatal=options.fatal;// euc-jp's decoder has an associated euc-jp jis0212 flag + // (initially unset) and euc-jp lead (initially 0x00). + var/** @type {boolean} */eucjp_jis0212_flag=false,/** @type {number} */eucjp_lead=0x00;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and euc-jp lead is not 0x00, set + // euc-jp lead to 0x00, and return error. + if(bite===end_of_stream&&eucjp_lead!==0x00){eucjp_lead=0x00;return decoderError(fatal);}// 2. If byte is end-of-stream and euc-jp lead is 0x00, return + // finished. + if(bite===end_of_stream&&eucjp_lead===0x00)return finished;// 3. If euc-jp lead is 0x8E and byte is in the range 0xA1 to + // 0xDF, inclusive, set euc-jp lead to 0x00 and return a code + // point whose value is 0xFF61 − 0xA1 + byte. + if(eucjp_lead===0x8E&&inRange(bite,0xA1,0xDF)){eucjp_lead=0x00;return 0xFF61-0xA1+bite;}// 4. If euc-jp lead is 0x8F and byte is in the range 0xA1 to + // 0xFE, inclusive, set the euc-jp jis0212 flag, set euc-jp lead + // to byte, and return continue. + if(eucjp_lead===0x8F&&inRange(bite,0xA1,0xFE)){eucjp_jis0212_flag=true;eucjp_lead=bite;return null;}// 5. If euc-jp lead is not 0x00, let lead be euc-jp lead, set + // euc-jp lead to 0x00, and run these substeps: + if(eucjp_lead!==0x00){var lead=eucjp_lead;eucjp_lead=0x00;// 1. Let code point be null. + var code_point=null;// 2. If lead and byte are both in the range 0xA1 to 0xFE, + // inclusive, set code point to the index code point for (lead + // − 0xA1) × 94 + byte − 0xA1 in index jis0208 if the euc-jp + // jis0212 flag is unset and in index jis0212 otherwise. + if(inRange(lead,0xA1,0xFE)&&inRange(bite,0xA1,0xFE)){code_point=indexCodePointFor((lead-0xA1)*94+(bite-0xA1),index(!eucjp_jis0212_flag?'jis0208':'jis0212'));}// 3. Unset the euc-jp jis0212 flag. + eucjp_jis0212_flag=false;// 4. If byte is not in the range 0xA1 to 0xFE, inclusive, + // prepend byte to stream. + if(!inRange(bite,0xA1,0xFE))stream.prepend(bite);// 5. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 6. Return a code point whose value is code point. + return code_point;}// 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 7. If byte is 0x8E, 0x8F, or in the range 0xA1 to 0xFE, + // inclusive, set euc-jp lead to byte and return continue. + if(bite===0x8E||bite===0x8F||inRange(bite,0xA1,0xFE)){eucjp_lead=bite;return null;}// 8. Return error. + return decoderError(fatal);};}// 13.1.2 euc-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function EUCJPEncoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. If code point is U+00A5, return byte 0x5C. + if(code_point===0x00A5)return 0x5C;// 4. If code point is U+203E, return byte 0x7E. + if(code_point===0x203E)return 0x7E;// 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return two bytes whose values are 0x8E and code point − + // 0xFF61 + 0xA1. + if(inRange(code_point,0xFF61,0xFF9F))return [0x8E,code_point-0xFF61+0xA1];// 6. If code point is U+2212, set it to U+FF0D. + if(code_point===0x2212)code_point=0xFF0D;// 7. Let pointer be the index pointer for code point in index + // jis0208. + var pointer=indexPointerFor(code_point,index('jis0208'));// 8. If pointer is null, return error with code point. + if(pointer===null)return encoderError(code_point);// 9. Let lead be floor(pointer / 94) + 0xA1. + var lead=floor(pointer/94)+0xA1;// 10. Let trail be pointer % 94 + 0xA1. + var trail=pointer%94+0xA1;// 11. Return two bytes whose values are lead and trail. + return [lead,trail];};}/** @param {{fatal: boolean}} options */encoders['EUC-JP']=function(options){return new EUCJPEncoder(options);};/** @param {{fatal: boolean}} options */decoders['EUC-JP']=function(options){return new EUCJPDecoder(options);};// 13.2 iso-2022-jp + // 13.2.1 iso-2022-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function ISO2022JPDecoder(options){var fatal=options.fatal;/** @enum */var states={ASCII:0,Roman:1,Katakana:2,LeadByte:3,TrailByte:4,EscapeStart:5,Escape:6};// iso-2022-jp's decoder has an associated iso-2022-jp decoder + // state (initially ASCII), iso-2022-jp decoder output state + // (initially ASCII), iso-2022-jp lead (initially 0x00), and + // iso-2022-jp output flag (initially unset). + var/** @type {number} */iso2022jp_decoder_state=states.ASCII,/** @type {number} */iso2022jp_decoder_output_state=states.ASCII,/** @type {number} */iso2022jp_lead=0x00,/** @type {boolean} */iso2022jp_output_flag=false;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// switching on iso-2022-jp decoder state: + switch(iso2022jp_decoder_state){default:case states.ASCII:// ASCII + // Based on byte: + // 0x1B + if(bite===0x1B){// Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state=states.EscapeStart;return null;}// 0x00 to 0x7F, excluding 0x0E, 0x0F, and 0x1B + if(inRange(bite,0x00,0x7F)&&bite!==0x0E&&bite!==0x0F&&bite!==0x1B){// Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag=false;return bite;}// end-of-stream + if(bite===end_of_stream){// Return finished. + return finished;}// Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag=false;return decoderError(fatal);case states.Roman:// Roman + // Based on byte: + // 0x1B + if(bite===0x1B){// Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state=states.EscapeStart;return null;}// 0x5C + if(bite===0x5C){// Unset the iso-2022-jp output flag and return code point + // U+00A5. + iso2022jp_output_flag=false;return 0x00A5;}// 0x7E + if(bite===0x7E){// Unset the iso-2022-jp output flag and return code point + // U+203E. + iso2022jp_output_flag=false;return 0x203E;}// 0x00 to 0x7F, excluding 0x0E, 0x0F, 0x1B, 0x5C, and 0x7E + if(inRange(bite,0x00,0x7F)&&bite!==0x0E&&bite!==0x0F&&bite!==0x1B&&bite!==0x5C&&bite!==0x7E){// Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag=false;return bite;}// end-of-stream + if(bite===end_of_stream){// Return finished. + return finished;}// Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag=false;return decoderError(fatal);case states.Katakana:// Katakana + // Based on byte: + // 0x1B + if(bite===0x1B){// Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state=states.EscapeStart;return null;}// 0x21 to 0x5F + if(inRange(bite,0x21,0x5F)){// Unset the iso-2022-jp output flag and return a code point + // whose value is 0xFF61 − 0x21 + byte. + iso2022jp_output_flag=false;return 0xFF61-0x21+bite;}// end-of-stream + if(bite===end_of_stream){// Return finished. + return finished;}// Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag=false;return decoderError(fatal);case states.LeadByte:// Lead byte + // Based on byte: + // 0x1B + if(bite===0x1B){// Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state=states.EscapeStart;return null;}// 0x21 to 0x7E + if(inRange(bite,0x21,0x7E)){// Unset the iso-2022-jp output flag, set iso-2022-jp lead + // to byte, iso-2022-jp decoder state to trail byte, and + // return continue. + iso2022jp_output_flag=false;iso2022jp_lead=bite;iso2022jp_decoder_state=states.TrailByte;return null;}// end-of-stream + if(bite===end_of_stream){// Return finished. + return finished;}// Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag=false;return decoderError(fatal);case states.TrailByte:// Trail byte + // Based on byte: + // 0x1B + if(bite===0x1B){// Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state=states.EscapeStart;return decoderError(fatal);}// 0x21 to 0x7E + if(inRange(bite,0x21,0x7E)){// 1. Set the iso-2022-jp decoder state to lead byte. + iso2022jp_decoder_state=states.LeadByte;// 2. Let pointer be (iso-2022-jp lead − 0x21) × 94 + byte − 0x21. + var pointer=(iso2022jp_lead-0x21)*94+bite-0x21;// 3. Let code point be the index code point for pointer in + // index jis0208. + var code_point=indexCodePointFor(pointer,index('jis0208'));// 4. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 5. Return a code point whose value is code point. + return code_point;}// end-of-stream + if(bite===end_of_stream){// Set the iso-2022-jp decoder state to lead byte, prepend + // byte to stream, and return error. + iso2022jp_decoder_state=states.LeadByte;stream.prepend(bite);return decoderError(fatal);}// Otherwise + // Set iso-2022-jp decoder state to lead byte and return + // error. + iso2022jp_decoder_state=states.LeadByte;return decoderError(fatal);case states.EscapeStart:// Escape start + // 1. If byte is either 0x24 or 0x28, set iso-2022-jp lead to + // byte, iso-2022-jp decoder state to escape, and return + // continue. + if(bite===0x24||bite===0x28){iso2022jp_lead=bite;iso2022jp_decoder_state=states.Escape;return null;}// 2. Prepend byte to stream. + stream.prepend(bite);// 3. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state, and + // return error. + iso2022jp_output_flag=false;iso2022jp_decoder_state=iso2022jp_decoder_output_state;return decoderError(fatal);case states.Escape:// Escape + // 1. Let lead be iso-2022-jp lead and set iso-2022-jp lead to + // 0x00. + var lead=iso2022jp_lead;iso2022jp_lead=0x00;// 2. Let state be null. + var state=null;// 3. If lead is 0x28 and byte is 0x42, set state to ASCII. + if(lead===0x28&&bite===0x42)state=states.ASCII;// 4. If lead is 0x28 and byte is 0x4A, set state to Roman. + if(lead===0x28&&bite===0x4A)state=states.Roman;// 5. If lead is 0x28 and byte is 0x49, set state to Katakana. + if(lead===0x28&&bite===0x49)state=states.Katakana;// 6. If lead is 0x24 and byte is either 0x40 or 0x42, set + // state to lead byte. + if(lead===0x24&&(bite===0x40||bite===0x42))state=states.LeadByte;// 7. If state is non-null, run these substeps: + if(state!==null){// 1. Set iso-2022-jp decoder state and iso-2022-jp decoder + // output state to states. + iso2022jp_decoder_state=iso2022jp_decoder_state=state;// 2. Let output flag be the iso-2022-jp output flag. + var output_flag=iso2022jp_output_flag;// 3. Set the iso-2022-jp output flag. + iso2022jp_output_flag=true;// 4. Return continue, if output flag is unset, and error + // otherwise. + return !output_flag?null:decoderError(fatal);}// 8. Prepend lead and byte to stream. + stream.prepend([lead,bite]);// 9. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state and + // return error. + iso2022jp_output_flag=false;iso2022jp_decoder_state=iso2022jp_decoder_output_state;return decoderError(fatal);}};}// 13.2.2 iso-2022-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function ISO2022JPEncoder(options){options.fatal;// iso-2022-jp's encoder has an associated iso-2022-jp encoder + // state which is one of ASCII, Roman, and jis0208 (initially + // ASCII). + /** @enum */var states={ASCII:0,Roman:1,jis0208:2};var/** @type {number} */iso2022jp_state=states.ASCII;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream and iso-2022-jp encoder + // state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if(code_point===end_of_stream&&iso2022jp_state!==states.ASCII){stream.prepend(code_point);iso2022jp_state=states.ASCII;return [0x1B,0x28,0x42];}// 2. If code point is end-of-stream and iso-2022-jp encoder + // state is ASCII, return finished. + if(code_point===end_of_stream&&iso2022jp_state===states.ASCII)return finished;// 3. If ISO-2022-JP encoder state is ASCII or Roman, and code + // point is U+000E, U+000F, or U+001B, return error with U+FFFD. + if((iso2022jp_state===states.ASCII||iso2022jp_state===states.Roman)&&(code_point===0x000E||code_point===0x000F||code_point===0x001B)){return encoderError(0xFFFD);}// 4. If iso-2022-jp encoder state is ASCII and code point is an + // ASCII code point, return a byte whose value is code point. + if(iso2022jp_state===states.ASCII&&isASCIICodePoint(code_point))return code_point;// 5. If iso-2022-jp encoder state is Roman and code point is an + // ASCII code point, excluding U+005C and U+007E, or is U+00A5 + // or U+203E, run these substeps: + if(iso2022jp_state===states.Roman&&(isASCIICodePoint(code_point)&&code_point!==0x005C&&code_point!==0x007E||code_point==0x00A5||code_point==0x203E)){// 1. If code point is an ASCII code point, return a byte + // whose value is code point. + if(isASCIICodePoint(code_point))return code_point;// 2. If code point is U+00A5, return byte 0x5C. + if(code_point===0x00A5)return 0x5C;// 3. If code point is U+203E, return byte 0x7E. + if(code_point===0x203E)return 0x7E;}// 6. If code point is an ASCII code point, and iso-2022-jp + // encoder state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if(isASCIICodePoint(code_point)&&iso2022jp_state!==states.ASCII){stream.prepend(code_point);iso2022jp_state=states.ASCII;return [0x1B,0x28,0x42];}// 7. If code point is either U+00A5 or U+203E, and iso-2022-jp + // encoder state is not Roman, prepend code point to stream, set + // iso-2022-jp encoder state to Roman, and return three bytes + // 0x1B 0x28 0x4A. + if((code_point===0x00A5||code_point===0x203E)&&iso2022jp_state!==states.Roman){stream.prepend(code_point);iso2022jp_state=states.Roman;return [0x1B,0x28,0x4A];}// 8. If code point is U+2212, set it to U+FF0D. + if(code_point===0x2212)code_point=0xFF0D;// 9. Let pointer be the index pointer for code point in index + // jis0208. + var pointer=indexPointerFor(code_point,index('jis0208'));// 10. If pointer is null, return error with code point. + if(pointer===null)return encoderError(code_point);// 11. If iso-2022-jp encoder state is not jis0208, prepend code + // point to stream, set iso-2022-jp encoder state to jis0208, + // and return three bytes 0x1B 0x24 0x42. + if(iso2022jp_state!==states.jis0208){stream.prepend(code_point);iso2022jp_state=states.jis0208;return [0x1B,0x24,0x42];}// 12. Let lead be floor(pointer / 94) + 0x21. + var lead=floor(pointer/94)+0x21;// 13. Let trail be pointer % 94 + 0x21. + var trail=pointer%94+0x21;// 14. Return two bytes whose values are lead and trail. + return [lead,trail];};}/** @param {{fatal: boolean}} options */encoders['ISO-2022-JP']=function(options){return new ISO2022JPEncoder(options);};/** @param {{fatal: boolean}} options */decoders['ISO-2022-JP']=function(options){return new ISO2022JPDecoder(options);};// 13.3 Shift_JIS + // 13.3.1 Shift_JIS decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function ShiftJISDecoder(options){var fatal=options.fatal;// Shift_JIS's decoder has an associated Shift_JIS lead (initially + // 0x00). + var/** @type {number} */Shift_JIS_lead=0x00;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and Shift_JIS lead is not 0x00, + // set Shift_JIS lead to 0x00 and return error. + if(bite===end_of_stream&&Shift_JIS_lead!==0x00){Shift_JIS_lead=0x00;return decoderError(fatal);}// 2. If byte is end-of-stream and Shift_JIS lead is 0x00, + // return finished. + if(bite===end_of_stream&&Shift_JIS_lead===0x00)return finished;// 3. If Shift_JIS lead is not 0x00, let lead be Shift_JIS lead, + // let pointer be null, set Shift_JIS lead to 0x00, and then run + // these substeps: + if(Shift_JIS_lead!==0x00){var lead=Shift_JIS_lead;var pointer=null;Shift_JIS_lead=0x00;// 1. Let offset be 0x40, if byte is less than 0x7F, and 0x41 + // otherwise. + var offset=bite<0x7F?0x40:0x41;// 2. Let lead offset be 0x81, if lead is less than 0xA0, and + // 0xC1 otherwise. + var lead_offset=lead<0xA0?0x81:0xC1;// 3. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFC, inclusive, set pointer to (lead − lead offset) × + // 188 + byte − offset. + if(inRange(bite,0x40,0x7E)||inRange(bite,0x80,0xFC))pointer=(lead-lead_offset)*188+bite-offset;// 4. If pointer is in the range 8836 to 10715, inclusive, + // return a code point whose value is 0xE000 − 8836 + pointer. + if(inRange(pointer,8836,10715))return 0xE000-8836+pointer;// 5. Let code point be null, if pointer is null, and the + // index code point for pointer in index jis0208 otherwise. + var code_point=pointer===null?null:indexCodePointFor(pointer,index('jis0208'));// 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if(code_point===null&&isASCIIByte(bite))stream.prepend(bite);// 7. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 8. Return a code point whose value is code point. + return code_point;}// 4. If byte is an ASCII byte or 0x80, return a code point + // whose value is byte. + if(isASCIIByte(bite)||bite===0x80)return bite;// 5. If byte is in the range 0xA1 to 0xDF, inclusive, return a + // code point whose value is 0xFF61 − 0xA1 + byte. + if(inRange(bite,0xA1,0xDF))return 0xFF61-0xA1+bite;// 6. If byte is in the range 0x81 to 0x9F, inclusive, or 0xE0 + // to 0xFC, inclusive, set Shift_JIS lead to byte and return + // continue. + if(inRange(bite,0x81,0x9F)||inRange(bite,0xE0,0xFC)){Shift_JIS_lead=bite;return null;}// 7. Return error. + return decoderError(fatal);};}// 13.3.2 Shift_JIS encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function ShiftJISEncoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point or U+0080, return a + // byte whose value is code point. + if(isASCIICodePoint(code_point)||code_point===0x0080)return code_point;// 3. If code point is U+00A5, return byte 0x5C. + if(code_point===0x00A5)return 0x5C;// 4. If code point is U+203E, return byte 0x7E. + if(code_point===0x203E)return 0x7E;// 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return a byte whose value is code point − 0xFF61 + 0xA1. + if(inRange(code_point,0xFF61,0xFF9F))return code_point-0xFF61+0xA1;// 6. If code point is U+2212, set it to U+FF0D. + if(code_point===0x2212)code_point=0xFF0D;// 7. Let pointer be the index Shift_JIS pointer for code point. + var pointer=indexShiftJISPointerFor(code_point);// 8. If pointer is null, return error with code point. + if(pointer===null)return encoderError(code_point);// 9. Let lead be floor(pointer / 188). + var lead=floor(pointer/188);// 10. Let lead offset be 0x81, if lead is less than 0x1F, and + // 0xC1 otherwise. + var lead_offset=lead<0x1F?0x81:0xC1;// 11. Let trail be pointer % 188. + var trail=pointer%188;// 12. Let offset be 0x40, if trail is less than 0x3F, and 0x41 + // otherwise. + var offset=trail<0x3F?0x40:0x41;// 13. Return two bytes whose values are lead + lead offset and + // trail + offset. + return [lead+lead_offset,trail+offset];};}/** @param {{fatal: boolean}} options */encoders['Shift_JIS']=function(options){return new ShiftJISEncoder(options);};/** @param {{fatal: boolean}} options */decoders['Shift_JIS']=function(options){return new ShiftJISDecoder(options);};// + // 14. Legacy multi-byte Korean encodings + // + // 14.1 euc-kr + // 14.1.1 euc-kr decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function EUCKRDecoder(options){var fatal=options.fatal;// euc-kr's decoder has an associated euc-kr lead (initially 0x00). + var/** @type {number} */euckr_lead=0x00;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and euc-kr lead is not 0x00, set + // euc-kr lead to 0x00 and return error. + if(bite===end_of_stream&&euckr_lead!==0){euckr_lead=0x00;return decoderError(fatal);}// 2. If byte is end-of-stream and euc-kr lead is 0x00, return + // finished. + if(bite===end_of_stream&&euckr_lead===0)return finished;// 3. If euc-kr lead is not 0x00, let lead be euc-kr lead, let + // pointer be null, set euc-kr lead to 0x00, and then run these + // substeps: + if(euckr_lead!==0x00){var lead=euckr_lead;var pointer=null;euckr_lead=0x00;// 1. If byte is in the range 0x41 to 0xFE, inclusive, set + // pointer to (lead − 0x81) × 190 + (byte − 0x41). + if(inRange(bite,0x41,0xFE))pointer=(lead-0x81)*190+(bite-0x41);// 2. Let code point be null, if pointer is null, and the + // index code point for pointer in index euc-kr otherwise. + var code_point=pointer===null?null:indexCodePointFor(pointer,index('euc-kr'));// 3. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if(pointer===null&&isASCIIByte(bite))stream.prepend(bite);// 4. If code point is null, return error. + if(code_point===null)return decoderError(fatal);// 5. Return a code point whose value is code point. + return code_point;}// 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 5. If byte is in the range 0x81 to 0xFE, inclusive, set + // euc-kr lead to byte and return continue. + if(inRange(bite,0x81,0xFE)){euckr_lead=bite;return null;}// 6. Return error. + return decoderError(fatal);};}// 14.1.2 euc-kr encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function EUCKREncoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. Let pointer be the index pointer for code point in index + // euc-kr. + var pointer=indexPointerFor(code_point,index('euc-kr'));// 4. If pointer is null, return error with code point. + if(pointer===null)return encoderError(code_point);// 5. Let lead be floor(pointer / 190) + 0x81. + var lead=floor(pointer/190)+0x81;// 6. Let trail be pointer % 190 + 0x41. + var trail=pointer%190+0x41;// 7. Return two bytes whose values are lead and trail. + return [lead,trail];};}/** @param {{fatal: boolean}} options */encoders['EUC-KR']=function(options){return new EUCKREncoder(options);};/** @param {{fatal: boolean}} options */decoders['EUC-KR']=function(options){return new EUCKRDecoder(options);};// + // 15. Legacy miscellaneous encodings + // + // 15.1 replacement + // Not needed - API throws RangeError + // 15.2 Common infrastructure for utf-16be and utf-16le + /** + * @param {number} code_unit + * @param {boolean} utf16be + * @return {!Array.} bytes + */function convertCodeUnitToBytes(code_unit,utf16be){// 1. Let byte1 be code unit >> 8. + var byte1=code_unit>>8;// 2. Let byte2 be code unit & 0x00FF. + var byte2=code_unit&0x00FF;// 3. Then return the bytes in order: + // utf-16be flag is set: byte1, then byte2. + if(utf16be)return [byte1,byte2];// utf-16be flag is unset: byte2, then byte1. + return [byte2,byte1];}// 15.2.1 shared utf-16 decoder + /** + * @constructor + * @implements {Decoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */function UTF16Decoder(utf16_be,options){var fatal=options.fatal;var/** @type {?number} */utf16_lead_byte=null,/** @type {?number} */utf16_lead_surrogate=null;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream and either utf-16 lead byte or + // utf-16 lead surrogate is not null, set utf-16 lead byte and + // utf-16 lead surrogate to null, and return error. + if(bite===end_of_stream&&(utf16_lead_byte!==null||utf16_lead_surrogate!==null)){return decoderError(fatal);}// 2. If byte is end-of-stream and utf-16 lead byte and utf-16 + // lead surrogate are null, return finished. + if(bite===end_of_stream&&utf16_lead_byte===null&&utf16_lead_surrogate===null){return finished;}// 3. If utf-16 lead byte is null, set utf-16 lead byte to byte + // and return continue. + if(utf16_lead_byte===null){utf16_lead_byte=bite;return null;}// 4. Let code unit be the result of: + var code_unit;if(utf16_be){// utf-16be decoder flag is set + // (utf-16 lead byte << 8) + byte. + code_unit=(utf16_lead_byte<<8)+bite;}else {// utf-16be decoder flag is unset + // (byte << 8) + utf-16 lead byte. + code_unit=(bite<<8)+utf16_lead_byte;}// Then set utf-16 lead byte to null. + utf16_lead_byte=null;// 5. If utf-16 lead surrogate is not null, let lead surrogate + // be utf-16 lead surrogate, set utf-16 lead surrogate to null, + // and then run these substeps: + if(utf16_lead_surrogate!==null){var lead_surrogate=utf16_lead_surrogate;utf16_lead_surrogate=null;// 1. If code unit is in the range U+DC00 to U+DFFF, + // inclusive, return a code point whose value is 0x10000 + + // ((lead surrogate − 0xD800) << 10) + (code unit − 0xDC00). + if(inRange(code_unit,0xDC00,0xDFFF)){return 0x10000+(lead_surrogate-0xD800)*0x400+(code_unit-0xDC00);}// 2. Prepend the sequence resulting of converting code unit + // to bytes using utf-16be decoder flag to stream and return + // error. + stream.prepend(convertCodeUnitToBytes(code_unit,utf16_be));return decoderError(fatal);}// 6. If code unit is in the range U+D800 to U+DBFF, inclusive, + // set utf-16 lead surrogate to code unit and return continue. + if(inRange(code_unit,0xD800,0xDBFF)){utf16_lead_surrogate=code_unit;return null;}// 7. If code unit is in the range U+DC00 to U+DFFF, inclusive, + // return error. + if(inRange(code_unit,0xDC00,0xDFFF))return decoderError(fatal);// 8. Return code point code unit. + return code_unit;};}// 15.2.2 shared utf-16 encoder + /** + * @constructor + * @implements {Encoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */function UTF16Encoder(utf16_be,options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1. If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is in the range U+0000 to U+FFFF, inclusive, + // return the sequence resulting of converting code point to + // bytes using utf-16be encoder flag. + if(inRange(code_point,0x0000,0xFFFF))return convertCodeUnitToBytes(code_point,utf16_be);// 3. Let lead be ((code point − 0x10000) >> 10) + 0xD800, + // converted to bytes using utf-16be encoder flag. + var lead=convertCodeUnitToBytes((code_point-0x10000>>10)+0xD800,utf16_be);// 4. Let trail be ((code point − 0x10000) & 0x3FF) + 0xDC00, + // converted to bytes using utf-16be encoder flag. + var trail=convertCodeUnitToBytes((code_point-0x10000&0x3FF)+0xDC00,utf16_be);// 5. Return a byte sequence of lead followed by trail. + return lead.concat(trail);};}// 15.3 utf-16be + // 15.3.1 utf-16be decoder + /** @param {{fatal: boolean}} options */encoders['UTF-16BE']=function(options){return new UTF16Encoder(true,options);};// 15.3.2 utf-16be encoder + /** @param {{fatal: boolean}} options */decoders['UTF-16BE']=function(options){return new UTF16Decoder(true,options);};// 15.4 utf-16le + // 15.4.1 utf-16le decoder + /** @param {{fatal: boolean}} options */encoders['UTF-16LE']=function(options){return new UTF16Encoder(false,options);};// 15.4.2 utf-16le encoder + /** @param {{fatal: boolean}} options */decoders['UTF-16LE']=function(options){return new UTF16Decoder(false,options);};// 15.5 x-user-defined + // 15.5.1 x-user-defined decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */function XUserDefinedDecoder(options){options.fatal;/** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */this.handler=function(stream,bite){// 1. If byte is end-of-stream, return finished. + if(bite===end_of_stream)return finished;// 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if(isASCIIByte(bite))return bite;// 3. Return a code point whose value is 0xF780 + byte − 0x80. + return 0xF780+bite-0x80;};}// 15.5.2 x-user-defined encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */function XUserDefinedEncoder(options){options.fatal;/** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */this.handler=function(stream,code_point){// 1.If code point is end-of-stream, return finished. + if(code_point===end_of_stream)return finished;// 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if(isASCIICodePoint(code_point))return code_point;// 3. If code point is in the range U+F780 to U+F7FF, inclusive, + // return a byte whose value is code point − 0xF780 + 0x80. + if(inRange(code_point,0xF780,0xF7FF))return code_point-0xF780+0x80;// 4. Return error with code point. + return encoderError(code_point);};}/** @param {{fatal: boolean}} options */encoders['x-user-defined']=function(options){return new XUserDefinedEncoder(options);};/** @param {{fatal: boolean}} options */decoders['x-user-defined']=function(options){return new XUserDefinedDecoder(options);};if(!global['TextEncoder'])global['TextEncoder']=TextEncoder;if(!global['TextDecoder'])global['TextDecoder']=TextDecoder;if(typeof module!=="undefined"&&module.exports){module.exports={TextEncoder:global['TextEncoder'],TextDecoder:global['TextDecoder'],EncodingIndexes:global["encoding-indexes"]};}// For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + })(this||{});},{"./encoding-indexes.js":108}],110:[function(require,module,exports){if(typeof Object.create==='function'){// implementation from standard node.js 'util' module + module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:false,writable:true,configurable:true}});};}else {// old school shim for old browsers + module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function TempCtor(){};TempCtor.prototype=superCtor.prototype;ctor.prototype=new TempCtor();ctor.prototype.constructor=ctor;};}},{}],111:[function(require,module,exports){module.exports=function isBuffer(arg){return arg&&_typeof$1(arg)==='object'&&typeof arg.copy==='function'&&typeof arg.fill==='function'&&typeof arg.readUInt8==='function';};},{}],112:[function(require,module,exports){// Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + var formatRegExp=/%[sdj%]/g;exports.format=function(f){if(!isString(f)){var objects=[];for(var i=0;i=len)return x;switch(x){case'%s':return String(args[i++]);case'%d':return Number(args[i++]);case'%j':try{return JSON.stringify(args[i++]);}catch(_){return '[Circular]';}default:return x;}});for(var x=args[i];i=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){// legacy... + ctx.showHidden=opts;}else if(opts){// got an "options" object + exports._extend(ctx,opts);}// set default options + if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth);}exports.inspect=inspect;// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors={'bold':[1,22],'italic':[3,23],'underline':[4,24],'inverse':[7,27],'white':[37,39],'grey':[90,39],'black':[30,39],'blue':[34,39],'cyan':[36,39],'green':[32,39],'magenta':[35,39],'red':[31,39],'yellow':[33,39]};// Don't use 'blue' not visible on cmd.exe + inspect.styles={'special':'cyan','number':'yellow','boolean':'yellow','undefined':'grey','null':'bold','string':'green','date':'magenta',// "name": intentionally not styling + 'regexp':'red'};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return "\x1B["+inspect.colors[style][0]+'m'+str+"\x1B["+inspect.colors[style][1]+'m';}else {return str;}}function stylizeNoColor(str,styleType){return str;}function arrayToHash(array){var hash={};array.forEach(function(val,idx){hash[val]=true;});return hash;}function formatValue(ctx,value,recurseTimes){// Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if(ctx.customInspect&&value&&isFunction(value.inspect)&&// Filter out the util module, it's inspect function is special + value.inspect!==exports.inspect&&// Also filter out any prototype objects using the circular check. + !(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes);}return ret;}// Primitive types cannot have properties + var primitive=formatPrimitive(ctx,value);if(primitive){return primitive;}// Look up the keys of the object. + var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value);}// IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if(isError(value)&&(keys.indexOf('message')>=0||keys.indexOf('description')>=0)){return formatError(value);}// Some type of object without properties can be shortcutted. + if(keys.length===0){if(isFunction(value)){var name=value.name?': '+value.name:'';return ctx.stylize('[Function'+name+']','special');}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),'date');}if(isError(value)){return formatError(value);}}var base='',array=false,braces=['{','}'];// Make Array say that they are Array + if(isArray(value)){array=true;braces=['[',']'];}// Make functions say that they are functions + if(isFunction(value)){var n=value.name?': '+value.name:'';base=' [Function'+n+']';}// Make RegExps say that they are RegExps + if(isRegExp(value)){base=' '+RegExp.prototype.toString.call(value);}// Make dates with properties first say the date + if(isDate(value)){base=' '+Date.prototype.toUTCString.call(value);}// Make error with message first say the error + if(isError(value)){base=' '+formatError(value);}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1];}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}else {return ctx.stylize('[Object]','special');}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys);}else {output=keys.map(function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array);});}ctx.seen.pop();return reduceToSingleString(output,base,braces);}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize('undefined','undefined');if(isString(value)){var simple='\''+JSON.stringify(value).replace(/^"|"$/g,'').replace(/'/g,"\\'").replace(/\\"/g,'"')+'\'';return ctx.stylize(simple,'string');}if(isNumber(value))return ctx.stylize(''+value,'number');if(isBoolean(value))return ctx.stylize(''+value,'boolean');// For some reason typeof null is "object", so special case here. + if(isNull(value))return ctx.stylize('null','null');}function formatError(value){return '['+Error.prototype.toString.call(value)+']';}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i-1){if(array){str=str.split('\n').map(function(line){return ' '+line;}).join('\n').substr(2);}else {str='\n'+str.split('\n').map(function(line){return ' '+line;}).join('\n');}}}else {str=ctx.stylize('[Circular]','special');}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str;}name=JSON.stringify(''+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,'name');}else {name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,'string');}}return name+': '+str;}function reduceToSingleString(output,base,braces){var length=output.reduce(function(prev,cur){if(cur.indexOf('\n')>=0);return prev+cur.replace(/\u001b\[\d\d?m/g,'').length+1;},0);if(length>60){return braces[0]+(base===''?'':base+'\n ')+' '+output.join(',\n ')+' '+braces[1];}return braces[0]+base+' '+output.join(', ')+' '+braces[1];}// NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar){return Array.isArray(ar);}exports.isArray=isArray;function isBoolean(arg){return typeof arg==='boolean';}exports.isBoolean=isBoolean;function isNull(arg){return arg===null;}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null;}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==='number';}exports.isNumber=isNumber;function isString(arg){return typeof arg==='string';}exports.isString=isString;function isSymbol(arg){return _typeof$1(arg)==='symbol';}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0;}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==='[object RegExp]';}exports.isRegExp=isRegExp;function isObject(arg){return _typeof$1(arg)==='object'&&arg!==null;}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==='[object Date]';}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==='[object Error]'||e instanceof Error);}exports.isError=isError;function isFunction(arg){return typeof arg==='function';}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==='boolean'||typeof arg==='number'||typeof arg==='string'||_typeof$1(arg)==='symbol'||// ES6 symbol + typeof arg==='undefined';}exports.isPrimitive=isPrimitive;exports.isBuffer=require('./support/isBuffer');function objectToString(o){return Object.prototype.toString.call(o);}function pad(n){return n<10?'0'+n.toString(10):n.toString(10);}var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];// 26 Feb 16:19:34 + function timestamp(){var d=new Date();var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(':');return [d.getDate(),months[d.getMonth()],time].join(' ');}// log is just a thin wrapper to console.log that prepends a timestamp + exports.log=function(){console.log('%s - %s',timestamp(),exports.format.apply(exports,arguments));};/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */exports.inherits=require('inherits');exports._extend=function(origin,add){// Don't do anything if add isn't an object + if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]];}return origin;};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);}},{"./support/isBuffer":111,"inherits":110}],113:[function(require,module,exports){/*! + + diff v5.1.0 + + Software License Agreement (BSD License) + + Copyright (c) 2009-2015, Kevin Decker + + All rights reserved. + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + @license + */(function(global,factory){_typeof$1(exports)==='object'&&typeof module!=='undefined'?factory(exports):(global=global||self,factory(global.Diff={}));})(this,function(exports){function Diff(){}Diff.prototype={diff:function diff(oldString,newString){var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var callback=options.callback;if(typeof options==='function'){callback=options;options={};}this.options=options;var self=this;function done(value){if(callback){setTimeout(function(){callback(undefined,value);},0);return true;}else {return value;}}// Allow subclasses to massage the input prior to running + oldString=this.castInput(oldString);newString=this.castInput(newString);oldString=this.removeEmpty(this.tokenize(oldString));newString=this.removeEmpty(this.tokenize(newString));var newLen=newString.length,oldLen=oldString.length;var editLength=1;var maxEditLength=newLen+oldLen;if(options.maxEditLength){maxEditLength=Math.min(maxEditLength,options.maxEditLength);}var bestPath=[{newPos:-1,components:[]}];// Seed editLength = 0, i.e. the content starts with the same values + var oldPos=this.extractCommon(bestPath[0],newString,oldString,0);if(bestPath[0].newPos+1>=newLen&&oldPos+1>=oldLen){// Identity per the equality and tokenizer + return done([{value:this.join(newString),count:newString.length}]);}// Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength(){for(var diagonalPath=-1*editLength;diagonalPath<=editLength;diagonalPath+=2){var basePath=void 0;var addPath=bestPath[diagonalPath-1],removePath=bestPath[diagonalPath+1],_oldPos=(removePath?removePath.newPos:0)-diagonalPath;if(addPath){// No one else is going to attempt to use this value, clear it + bestPath[diagonalPath-1]=undefined;}var canAdd=addPath&&addPath.newPos+1=newLen&&_oldPos+1>=oldLen){return done(buildValues(self,basePath.components,newString,oldString,self.useLongestToken));}else {// Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath]=basePath;}}editLength++;}// Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced, or until the edit length exceeds options.maxEditLength (if given), + // in which case it will return undefined. + if(callback){(function exec(){setTimeout(function(){if(editLength>maxEditLength){return callback();}if(!execEditLength()){exec();}},0);})();}else {while(editLength<=maxEditLength){var ret=execEditLength();if(ret){return ret;}}}},pushComponent:function pushComponent(components,added,removed){var last=components[components.length-1];if(last&&last.added===added&&last.removed===removed){// We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length-1]={count:last.count+1,added:added,removed:removed};}else {components.push({count:1,added:added,removed:removed});}},extractCommon:function extractCommon(basePath,newString,oldString,diagonalPath){var newLen=newString.length,oldLen=oldString.length,newPos=basePath.newPos,oldPos=newPos-diagonalPath,commonCount=0;while(newPos+1value.length?oldValue:value;});component.value=diff.join(value);}else {component.value=diff.join(newString.slice(newPos,newPos+component.count));}newPos+=component.count;// Common case + if(!component.added){oldPos+=component.count;}}else {component.value=diff.join(oldString.slice(oldPos,oldPos+component.count));oldPos+=component.count;// Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + if(componentPos&&components[componentPos-1].added){var tmp=components[componentPos-1];components[componentPos-1]=components[componentPos];components[componentPos]=tmp;}}}// Special case handle for when one terminal is ignored (i.e. whitespace). + // For this case we merge the terminal into the prior string and drop the change. + // This is only available for string mode. + var lastComponent=components[componentLen-1];if(componentLen>1&&typeof lastComponent.value==='string'&&(lastComponent.added||lastComponent.removed)&&diff.equals('',lastComponent.value)){components[componentLen-2].value+=lastComponent.value;components.pop();}return components;}function clonePath(path){return {newPos:path.newPos,components:path.components.slice(0)};}var characterDiff=new Diff();function diffChars(oldStr,newStr,options){return characterDiff.diff(oldStr,newStr,options);}function generateOptions(options,defaults){if(typeof options==='function'){defaults.callback=options;}else if(options){for(var name in options){/* istanbul ignore else */if(options.hasOwnProperty(name)){defaults[name]=options[name];}}}return defaults;}// + // Ranges and exceptions: + // Latin-1 Supplement, 0080–00FF + // - U+00D7 × Multiplication sign + // - U+00F7 ÷ Division sign + // Latin Extended-A, 0100–017F + // Latin Extended-B, 0180–024F + // IPA Extensions, 0250–02AF + // Spacing Modifier Letters, 02B0–02FF + // - U+02C7 ˇ ˇ Caron + // - U+02D8 ˘ ˘ Breve + // - U+02D9 ˙ ˙ Dot Above + // - U+02DA ˚ ˚ Ring Above + // - U+02DB ˛ ˛ Ogonek + // - U+02DC ˜ ˜ Small Tilde + // - U+02DD ˝ ˝ Double Acute Accent + // Latin Extended Additional, 1E00–1EFF + var extendedWordChars=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;var reWhitespace=/\S/;var wordDiff=new Diff();wordDiff.equals=function(left,right){if(this.options.ignoreCase){left=left.toLowerCase();right=right.toLowerCase();}return left===right||this.options.ignoreWhitespace&&!reWhitespace.test(left)&&!reWhitespace.test(right);};wordDiff.tokenize=function(value){// All whitespace symbols except newline group into one token, each newline - in separate token + var tokens=value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);// Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + for(var i=0;iarr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:{};var diffstr=uniDiff.split(/\r\n|[\n\v\f\r\x85]/),delimiters=uniDiff.match(/\r\n|[\n\v\f\r\x85]/g)||[],list=[],i=0;function parseIndex(){var index={};list.push(index);// Parse diff metadata + while(i2&&arguments[2]!==undefined?arguments[2]:{};if(typeof uniDiff==='string'){uniDiff=parsePatch(uniDiff);}if(Array.isArray(uniDiff)){if(uniDiff.length>1){throw new Error('applyPatch only works with a single input.');}uniDiff=uniDiff[0];}// Apply the diff to the input + var lines=source.split(/\r\n|[\n\v\f\r\x85]/),delimiters=source.match(/\r\n|[\n\v\f\r\x85]/g)||[],hunks=uniDiff.hunks,compareLine=options.compareLine||function(lineNumber,line,operation,patchContent){return line===patchContent;},errorCount=0,fuzzFactor=options.fuzzFactor||0,minLine=0,offset=0,removeEOFNL,addEOFNL;/** + * Checks if the hunk exactly fits on the provided location + */function hunkFits(hunk,toPos){for(var j=0;j0?line[0]:' ',content=line.length>0?line.substr(1):line;if(operation===' '||operation==='-'){// Context sanity check + if(!compareLine(toPos+1,lines[toPos],operation,content)){errorCount++;if(errorCount>fuzzFactor){return false;}}toPos++;}}return true;}// Search best fit offsets for each hunk based on the previous ones + for(var i=0;i0?line[0]:' ',content=line.length>0?line.substr(1):line,delimiter=_hunk.linedelimiters[j];if(operation===' '){_toPos++;}else if(operation==='-'){lines.splice(_toPos,1);delimiters.splice(_toPos,1);/* istanbul ignore else */}else if(operation==='+'){lines.splice(_toPos,0,content);delimiters.splice(_toPos,0,delimiter);_toPos++;}else if(operation==='\\'){var previousOperation=_hunk.lines[j-1]?_hunk.lines[j-1][0]:null;if(previousOperation==='+'){removeEOFNL=true;}else if(previousOperation==='-'){addEOFNL=true;}}}}// Handle EOFNL insertion/removal + if(removeEOFNL){while(!lines[lines.length-1]){lines.pop();delimiters.pop();}}else if(addEOFNL){lines.push('');delimiters.push('\n');}for(var _k=0;_k0?contextLines(prev.lines.slice(-options.context)):[];oldRangeStart-=curRange.length;newRangeStart-=curRange.length;}}// Output our changes + (_curRange=curRange).push.apply(_curRange,_toConsumableArray(lines.map(function(entry){return (current.added?'+':'-')+entry;})));// Track the updated file position + if(current.added){newLine+=lines.length;}else {oldLine+=lines.length;}}else {// Identical context lines. Track line changes + if(oldRangeStart){// Close out any changes that have been output (or join overlapping) + if(lines.length<=options.context*2&&i=diff.length-2&&lines.length<=options.context){// EOF is inside this hunk + var oldEOFNewline=/\n$/.test(oldStr);var newEOFNewline=/\n$/.test(newStr);var noNlBeforeAdds=lines.length==0&&curRange.length>hunk.oldLines;if(!oldEOFNewline&&noNlBeforeAdds&&oldStr.length>0){// special case: old has no eol and no trailing context; no-nl can end up before adds + // however, if the old file is empty, do not output the no-nl line + curRange.splice(hunk.oldLines,0,'\\ No newline at end of file');}if(!oldEOFNewline&&!noNlBeforeAdds||!newEOFNewline){curRange.push('\\ No newline at end of file');}}hunks.push(hunk);oldRangeStart=0;newRangeStart=0;curRange=[];}}oldLine+=lines.length;newLine+=lines.length;}};for(var i=0;iarray.length){return false;}for(var i=0;i');}else if(change.removed){ret.push('');}ret.push(escapeHTML(change.value));if(change.added){ret.push('');}else if(change.removed){ret.push('');}}return ret.join('');}function escapeHTML(s){var n=s;n=n.replace(/&/g,'&');n=n.replace(//g,'>');n=n.replace(/"/g,'"');return n;}exports.Diff=Diff;exports.applyPatch=applyPatch;exports.applyPatches=applyPatches;exports.canonicalize=canonicalize;exports.convertChangesToDMP=convertChangesToDMP;exports.convertChangesToXML=convertChangesToXML;exports.createPatch=createPatch;exports.createTwoFilesPatch=createTwoFilesPatch;exports.diffArrays=diffArrays;exports.diffChars=diffChars;exports.diffCss=diffCss;exports.diffJson=diffJson;exports.diffLines=diffLines;exports.diffSentences=diffSentences;exports.diffTrimmedLines=diffTrimmedLines;exports.diffWords=diffWords;exports.diffWordsWithSpace=diffWordsWithSpace;exports.merge=merge;exports.parsePatch=parsePatch;exports.structuredPatch=structuredPatch;Object.defineProperty(exports,'__esModule',{value:true});});},{}],114:[function(require,module,exports){module.exports=extend;/* + var obj = {a: 3, b: 5}; + extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 4, b: 5, c: 8} + + var obj = {a: 3, b: 5}; + extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 3, b: 5} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3]} + + extend({a: 4, b: 5}); // {a: 4, b: 5} + extend({a: 4, b: 5}, 3); {a: 4, b: 5} + extend({a: 4, b: 5}, true); {a: 4, b: 5} + extend('hello', {a: 4, b: 5}); // throws + extend(3, {a: 4, b: 5}); // throws + */function extend(/* [deep], obj1, obj2, [objn] */){var args=[].slice.call(arguments);var deep=false;if(typeof args[0]=='boolean'){deep=args.shift();}var result=args[0];if(isUnextendable(result)){throw new Error('extendee must be an object');}var extenders=args.slice(1);var len=extenders.length;for(var i=0;i + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ /** Used as the `TypeError` message for "Functions" methods. */var FUNC_ERROR_TEXT='Expected a function';/** Used to stand-in for `undefined` hash values. */var HASH_UNDEFINED='__lodash_hash_undefined__';/** Used as references for various `Number` constants. */var INFINITY=1/0;/** `Object#toString` result references. */var funcTag='[object Function]',genTag='[object GeneratorFunction]',symbolTag='[object Symbol]';/** Used to match property names within property paths. */var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,reLeadingDot=/^\./,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */var reRegExpChar=/[\\^$.*+?()[\]{}|]/g;/** Used to match backslashes in property paths. */var reEscapeChar=/\\(\\)?/g;/** Used to detect host constructors (Safari). */var reIsHostCtor=/^\[object .+?Constructor\]$/;/** Detect free variable `global` from Node.js. */var freeGlobal=_typeof$1(commonjsGlobal$1)=='object'&&commonjsGlobal$1&&commonjsGlobal$1.Object===Object&&commonjsGlobal$1;/** Detect free variable `self`. */var freeSelf=(typeof self==="undefined"?"undefined":_typeof$1(self))=='object'&&self&&self.Object===Object&&self;/** Used as a reference to the global object. */var root=freeGlobal||freeSelf||Function('return this')();/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */function getValue(object,key){return object==null?undefined:object[key];}/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */function isHostObject(value){// Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result=false;if(value!=null&&typeof value.toString!='function'){try{result=!!(value+'');}catch(e){}}return result;}/** Used for built-in method references. */var arrayProto=Array.prototype,funcProto=Function.prototype,objectProto=Object.prototype;/** Used to detect overreaching core-js shims. */var coreJsData=root['__core-js_shared__'];/** Used to detect methods masquerading as native. */var maskSrcKey=function(){var uid=/[^.]+$/.exec(coreJsData&&coreJsData.keys&&coreJsData.keys.IE_PROTO||'');return uid?'Symbol(src)_1.'+uid:'';}();/** Used to resolve the decompiled source of functions. */var funcToString=funcProto.toString;/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty;/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */var objectToString=objectProto.toString;/** Used to detect if a method is native. */var reIsNative=RegExp('^'+funcToString.call(hasOwnProperty).replace(reRegExpChar,'\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,'$1.*?')+'$');/** Built-in value references. */var _Symbol=root.Symbol,splice=arrayProto.splice;/* Built-in method references that are verified to be native. */var Map=getNative(root,'Map'),nativeCreate=getNative(Object,'create');/** Used to convert symbols to primitives and strings. */var symbolProto=_Symbol?_Symbol.prototype:undefined,symbolToString=symbolProto?symbolProto.toString:undefined;/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */function Hash(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index-1;}/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */function listCacheSet(key,value){var data=this.__data__,index=assocIndexOf(data,key);if(index<0){data.push([key,value]);}else {data[index][1]=value;}return this;}// Add methods to `ListCache`. + ListCache.prototype.clear=listCacheClear;ListCache.prototype['delete']=listCacheDelete;ListCache.prototype.get=listCacheGet;ListCache.prototype.has=listCacheHas;ListCache.prototype.set=listCacheSet;/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */function MapCache(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */function memoize(func,resolver){if(typeof func!='function'||resolver&&typeof resolver!='function'){throw new TypeError(FUNC_ERROR_TEXT);}var memoized=function memoized(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key);}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result;};memoized.cache=new(memoize.Cache||MapCache)();return memoized;}// Assign cache to `_.memoize`. + memoize.Cache=MapCache;/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */function eq(value,other){return value===other||value!==value&&other!==other;}/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */var isArray=Array.isArray;/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */function isFunction(value){// The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag=isObject(value)?objectToString.call(value):'';return tag==funcTag||tag==genTag;}/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */function isObject(value){var type=_typeof$1(value);return !!value&&(type=='object'||type=='function');}/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */function isObjectLike(value){return !!value&&_typeof$1(value)=='object';}/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */function isSymbol(value){return _typeof$1(value)=='symbol'||isObjectLike(value)&&objectToString.call(value)==symbolTag;}/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */function toString(value){return value==null?'':baseToString(value);}/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */function get(object,path,defaultValue){var result=object==null?undefined:baseGet(object,path);return result===undefined?defaultValue:result;}module.exports=get;},{}],116:[function(require,module,exports){// cache a reference to setTimeout, so that our reference won't be stubbed out + // when using fake timers and errors will still get logged + // https://github.com/cjohansen/Sinon.JS/issues/381 + var realSetTimeout=setTimeout;function configureLogger(config){// eslint-disable-next-line no-param-reassign + config=config||{};// Function which prints errors. + if(!config.hasOwnProperty("logger")){// eslint-disable-next-line no-empty-function + config.logger=function(){};}// When set to true, any errors logged will be thrown immediately; + // If set to false, the errors will be thrown in separate execution frame. + if(!config.hasOwnProperty("useImmediateExceptions")){config.useImmediateExceptions=true;}// wrap realSetTimeout with something we can stub in tests + if(!config.hasOwnProperty("setTimeout")){config.setTimeout=realSetTimeout;}return function logError(label,e){var msg="".concat(label," threw exception: ");var err={name:e.name||label,message:e.message||e.toString(),stack:e.stack};function throwLoggedError(){err.message=msg+err.message;throw err;}config.logger("".concat(msg,"[").concat(err.name,"] ").concat(err.message));if(err.stack){config.logger(err.stack);}if(config.useImmediateExceptions){throwLoggedError();}else {config.setTimeout(throwLoggedError,0);}};}module.exports=configureLogger;},{}],117:[function(require,module,exports){var Event=require("./event");function CustomEvent(type,customData,target){this.initEvent(type,false,false,target);this.detail=customData.detail||null;}CustomEvent.prototype=new Event();CustomEvent.prototype.constructor=CustomEvent;module.exports=CustomEvent;},{"./event":119}],118:[function(require,module,exports){function flattenOptions(options){if(options!==Object(options)){return {capture:Boolean(options),once:false,passive:false};}return {capture:Boolean(options.capture),once:Boolean(options.once),passive:Boolean(options.passive)};}function not(fn){return function(){return !fn.apply(this,arguments);};}function hasListenerFilter(listener,capture){return function(listenerSpec){return listenerSpec.capture===capture&&listenerSpec.listener===listener;};}var EventTarget={// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener + addEventListener:function addEventListener(event,listener,providedOptions){// 3. Let capture, passive, and once be the result of flattening more options. + // Flatten property before executing step 2, + // feture detection is usually based on registering handler with options object, + // that has getter defined + // addEventListener("load", () => {}, { + // get once() { supportsOnce = true; } + // }); + var options=flattenOptions(providedOptions);// 2. If callback is null, then return. + if(listener===null||listener===undefined){return;}this.eventListeners=this.eventListeners||{};this.eventListeners[event]=this.eventListeners[event]||[];// 4. If context object’s associated list of event listener + // does not contain an event listener whose type is type, + // callback is callback, and capture is capture, then append + // a new event listener to it, whose type is type, callback is + // callback, capture is capture, passive is passive, and once is once. + if(!this.eventListeners[event].some(hasListenerFilter(listener,options.capture))){this.eventListeners[event].push({listener:listener,capture:options.capture,once:options.once});}},// https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener + removeEventListener:function removeEventListener(event,listener,providedOptions){if(!this.eventListeners||!this.eventListeners[event]){return;}// 2. Let capture be the result of flattening options. + var options=flattenOptions(providedOptions);// 3. If there is an event listener in the associated list of + // event listeners whose type is type, callback is callback, + // and capture is capture, then set that event listener’s + // removed to true and remove it from the associated list of event listeners. + this.eventListeners[event]=this.eventListeners[event].filter(not(hasListenerFilter(listener,options.capture)));},dispatchEvent:function dispatchEvent(event){if(!this.eventListeners||!this.eventListeners[event.type]){return Boolean(event.defaultPrevented);}var self=this;var type=event.type;var listeners=self.eventListeners[type];// Remove listeners, that should be dispatched once + // before running dispatch loop to avoid nested dispatch issues + self.eventListeners[type]=listeners.filter(function(listenerSpec){return !listenerSpec.once;});listeners.forEach(function(listenerSpec){var listener=listenerSpec.listener;if(typeof listener==="function"){listener.call(self,event);}else {listener.handleEvent(event);}});return Boolean(event.defaultPrevented);}};module.exports=EventTarget;},{}],119:[function(require,module,exports){function Event(type,bubbles,cancelable,target){this.initEvent(type,bubbles,cancelable,target);}Event.prototype={initEvent:function initEvent(type,bubbles,cancelable,target){this.type=type;this.bubbles=bubbles;this.cancelable=cancelable;this.target=target;this.currentTarget=target;},// eslint-disable-next-line no-empty-function + stopPropagation:function stopPropagation(){},preventDefault:function preventDefault(){this.defaultPrevented=true;}};module.exports=Event;},{}],120:[function(require,module,exports){module.exports={Event:require("./event"),ProgressEvent:require("./progress-event"),CustomEvent:require("./custom-event"),EventTarget:require("./event-target")};},{"./custom-event":117,"./event":119,"./event-target":118,"./progress-event":121}],121:[function(require,module,exports){var Event=require("./event");function ProgressEvent(type,progressEventRaw,target){this.initEvent(type,false,false,target);this.loaded=typeof progressEventRaw.loaded==="number"?progressEventRaw.loaded:null;this.total=typeof progressEventRaw.total==="number"?progressEventRaw.total:null;this.lengthComputable=Boolean(progressEventRaw.total);}ProgressEvent.prototype=new Event();ProgressEvent.prototype.constructor=ProgressEvent;module.exports=ProgressEvent;},{"./event":119}],122:[function(require,module,exports){var FakeTimers=require("@sinonjs/fake-timers");var fakeServer=require("./index");// eslint-disable-next-line no-empty-function + function Server(){}Server.prototype=fakeServer;var fakeServerWithClock=new Server();fakeServerWithClock.addRequest=function addRequest(xhr){if(xhr.async){if(_typeof$1(setTimeout.clock)==="object"){this.clock=setTimeout.clock;}else {this.clock=FakeTimers.install();this.resetClock=true;}if(!this.longestTimeout){var clockSetTimeout=this.clock.setTimeout;var clockSetInterval=this.clock.setInterval;var server=this;this.clock.setTimeout=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetTimeout.apply(this,arguments);};this.clock.setInterval=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetInterval.apply(this,arguments);};}}return fakeServer.addRequest.call(this,xhr);};fakeServerWithClock.respond=function respond(){var returnVal=fakeServer.respond.apply(this,arguments);if(this.clock){this.clock.tick(this.longestTimeout||0);this.longestTimeout=0;if(this.resetClock){this.clock.uninstall();this.resetClock=false;}}return returnVal;};fakeServerWithClock.restore=function restore(){if(this.clock){this.clock.uninstall();}return fakeServer.restore.apply(this,arguments);};module.exports=fakeServerWithClock;},{"./index":123,"@sinonjs/fake-timers":60}],123:[function(require,module,exports){var fakeXhr=require("../fake-xhr");var push=[].push;var log=require("./log");var configureLogError=require("../configure-logger");var pathToRegexp=require("path-to-regexp");var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";function responseArray(handler){var response=handler;if(Object.prototype.toString.call(handler)!=="[object Array]"){response=[200,{},handler];}if(typeof response[2]!=="string"){if(!supportsArrayBuffer){throw new TypeError("Fake server response body should be a string, but was ".concat(_typeof$1(response[2])));}else if(!(response[2]instanceof ArrayBuffer)){throw new TypeError("Fake server response body should be a string or ArrayBuffer, but was ".concat(_typeof$1(response[2])));}}return response;}function getDefaultWindowLocation(){var winloc={hostname:"localhost",port:process.env.PORT||80,protocol:"http:"};winloc.host=winloc.hostname+(String(winloc.port)==="80"?"":":".concat(winloc.port));return winloc;}function getWindowLocation(){if(typeof window==="undefined"){// Fallback + return getDefaultWindowLocation();}if(typeof window.location!=="undefined"){// Browsers place location on window + return window.location;}if(typeof window.window!=="undefined"&&typeof window.window.location!=="undefined"){// React Native on Android places location on window.window + return window.window.location;}return getDefaultWindowLocation();}function matchOne(response,reqMethod,reqUrl){var rmeth=response.method;var matchMethod=!rmeth||rmeth.toLowerCase()===reqMethod.toLowerCase();var url=response.url;var matchUrl=!url||url===reqUrl||typeof url.test==="function"&&url.test(reqUrl)||typeof url==="function"&&url(reqUrl)===true;return matchMethod&&matchUrl;}function match(response,request){var wloc=getWindowLocation();var rCurrLoc=new RegExp("^".concat(wloc.protocol,"//").concat(wloc.host,"/"));var requestUrl=request.url;if(!/^https?:\/\//.test(requestUrl)||rCurrLoc.test(requestUrl)){requestUrl=requestUrl.replace(rCurrLoc,"/");}if(matchOne(response,this.getHTTPMethod(request),requestUrl)){if(typeof response.response==="function"){var ru=response.url;var args=[request].concat(ru&&typeof ru.exec==="function"?ru.exec(requestUrl).slice(1):[]);return response.response.apply(response,args);}return true;}return false;}function incrementRequestCount(){var count=++this.requestCount;this.requested=true;this.requestedOnce=count===1;this.requestedTwice=count===2;this.requestedThrice=count===3;this.firstRequest=this.getRequest(0);this.secondRequest=this.getRequest(1);this.thirdRequest=this.getRequest(2);this.lastRequest=this.getRequest(count-1);}var fakeServer={create:function create(config){var server=Object.create(this);server.configure(config);this.xhr=fakeXhr.useFakeXMLHttpRequest();server.requests=[];server.requestCount=0;server.queue=[];server.responses=[];this.xhr.onCreate=function(xhrObj){xhrObj.unsafeHeadersEnabled=function(){return !(server.unsafeHeadersEnabled===false);};server.addRequest(xhrObj);};return server;},configure:function configure(config){var self=this;var allowlist={autoRespond:true,autoRespondAfter:true,respondImmediately:true,fakeHTTPMethods:true,logger:true,unsafeHeadersEnabled:true};// eslint-disable-next-line no-param-reassign + config=config||{};Object.keys(config).forEach(function(setting){if(setting in allowlist){self[setting]=config[setting];}});self.logError=configureLogError(config);},addRequest:function addRequest(xhrObj){var server=this;push.call(this.requests,xhrObj);incrementRequestCount.call(this);xhrObj.onSend=function(){server.handleRequest(this);if(server.respondImmediately){server.respond();}else if(server.autoRespond&&!server.responding){setTimeout(function(){server.responding=false;server.respond();},server.autoRespondAfter||10);server.responding=true;}};},getHTTPMethod:function getHTTPMethod(request){if(this.fakeHTTPMethods&&/post/i.test(request.method)){var matches=(request.requestBody||"").match(/_method=([^\b;]+)/);return matches?matches[1]:request.method;}return request.method;},handleRequest:function handleRequest(xhr){if(xhr.async){push.call(this.queue,xhr);}else {this.processRequest(xhr);}},logger:function logger(){// no-op; override via configure() + },logError:configureLogError({}),log:log,respondWith:function respondWith(method,url,body){if(arguments.length===1&&typeof method!=="function"){this.response=responseArray(method);return;}if(arguments.length===1){// eslint-disable-next-line no-param-reassign + body=method;// eslint-disable-next-line no-param-reassign + url=method=null;}if(arguments.length===2){// eslint-disable-next-line no-param-reassign + body=url;// eslint-disable-next-line no-param-reassign + url=method;// eslint-disable-next-line no-param-reassign + method=null;}// Escape port number to prevent "named" parameters in 'path-to-regexp' module + if(typeof url==="string"&&url!==""&&/:[0-9]+\//.test(url)){var m=url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/);// eslint-disable-next-line no-param-reassign + url="".concat(m[1],"\\:").concat(m[2]);}push.call(this.responses,{method:method,url:typeof url==="string"&&url!==""?pathToRegexp(url):url,response:typeof body==="function"?body:responseArray(body)});},respond:function respond(){if(arguments.length>0){this.respondWith.apply(this,arguments);}var queue=this.queue||[];var requests=queue.splice(0,queue.length);var self=this;requests.forEach(function(request){self.processRequest(request);});},respondAll:function respondAll(){if(this.respondImmediately){return;}this.queue=this.requests.slice(0);var request;while(request=this.queue.shift()){this.processRequest(request);}},processRequest:function processRequest(request){try{if(request.aborted){return;}var response=this.response||[404,{},""];if(this.responses){for(var l=this.responses.length,i=l-1;i>=0;i--){if(match.call(this,this.responses[i],request)){response=this.responses[i].response;break;}}}if(request.readyState!==4){this.log(response,request);request.respond(response[0],response[1],response[2]);}}catch(e){this.logError("Fake server request processing",e);}},restore:function restore(){return this.xhr.restore&&this.xhr.restore.apply(this.xhr,arguments);},getRequest:function getRequest(index){return this.requests[index]||null;},reset:function reset(){this.resetBehavior();this.resetHistory();},resetBehavior:function resetBehavior(){this.responses.length=this.queue.length=0;},resetHistory:function resetHistory(){this.requests.length=this.requestCount=0;this.requestedOnce=this.requestedTwice=this.requestedThrice=this.requested=false;this.firstRequest=this.secondRequest=this.thirdRequest=this.lastRequest=null;}};module.exports=fakeServer;},{"../configure-logger":116,"../fake-xhr":126,"./log":124,"path-to-regexp":147}],124:[function(require,module,exports){var inspect=require("util").inspect;function log(response,request){var str;str="Request:\n".concat(inspect(request),"\n\n");str+="Response:\n".concat(inspect(response),"\n\n");/* istanbul ignore else: when this.logger is not a function, it can't be called */if(typeof this.logger==="function"){this.logger(str);}}module.exports=log;},{"util":112}],125:[function(require,module,exports){exports.isSupported=function(){try{return Boolean(new Blob());}catch(e){return false;}}();},{}],126:[function(require,module,exports){var GlobalTextEncoder=typeof TextEncoder!=="undefined"?TextEncoder:require("@sinonjs/text-encoding").TextEncoder;var globalObject=require("@sinonjs/commons").global;var configureLogError=require("../configure-logger");var sinonEvent=require("../event");var extend=require("just-extend");var supportsProgress=typeof ProgressEvent!=="undefined";var supportsCustomEvent=typeof CustomEvent!=="undefined";var supportsFormData=typeof FormData!=="undefined";var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";var supportsBlob=require("./blob").isSupported;function getWorkingXHR(globalScope){var supportsXHR=typeof globalScope.XMLHttpRequest!=="undefined";if(supportsXHR){return globalScope.XMLHttpRequest;}var supportsActiveX=typeof globalScope.ActiveXObject!=="undefined";if(supportsActiveX){return function(){return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");};}return false;}// Ref: https://fetch.spec.whatwg.org/#forbidden-header-name + var unsafeHeaders={"Accept-Charset":true,"Access-Control-Request-Headers":true,"Access-Control-Request-Method":true,"Accept-Encoding":true,Connection:true,"Content-Length":true,Cookie:true,Cookie2:true,"Content-Transfer-Encoding":true,Date:true,DNT:true,Expect:true,Host:true,"Keep-Alive":true,Origin:true,Referer:true,TE:true,Trailer:true,"Transfer-Encoding":true,Upgrade:true,"User-Agent":true,Via:true};function EventTargetHandler(){var self=this;var events=["loadstart","progress","abort","error","load","timeout","loadend"];function addEventListener(eventName){self.addEventListener(eventName,function(event){var listener=self["on".concat(eventName)];if(listener&&typeof listener==="function"){listener.call(this,event);}});}events.forEach(addEventListener);}EventTargetHandler.prototype=sinonEvent.EventTarget;function normalizeHeaderValue(value){// Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes + /*eslint no-control-regex: "off"*/return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g,"");}function getHeader(headers,header){var foundHeader=Object.keys(headers).filter(function(h){return h.toLowerCase()===header.toLowerCase();});return foundHeader[0]||null;}function excludeSetCookie2Header(header){return !/^Set-Cookie2?$/i.test(header);}function verifyResponseBodyType(body,responseType){var error=null;var isString=typeof body==="string";if(responseType==="arraybuffer"){if(!isString&&!(body instanceof ArrayBuffer)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string or ArrayBuffer."));error.name="InvalidBodyException";}}else if(responseType==="blob"){if(!isString&&!(body instanceof ArrayBuffer)&&supportsBlob&&!(body instanceof Blob)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string, ArrayBuffer, or Blob."));error.name="InvalidBodyException";}}else if(!isString){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string."));error.name="InvalidBodyException";}if(error){throw error;}}function convertToArrayBuffer(body,encoding){if(body instanceof ArrayBuffer){return body;}return new GlobalTextEncoder(encoding||"utf-8").encode(body).buffer;}function isXmlContentType(contentType){return !contentType||/(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);}function clearResponse(xhr){if(xhr.responseType===""||xhr.responseType==="text"){xhr.response=xhr.responseText="";}else {xhr.response=xhr.responseText=null;}xhr.responseXML=null;}function fakeXMLHttpRequestFor(globalScope){var isReactNative=globalScope.navigator&&globalScope.navigator.product==="ReactNative";var sinonXhr={XMLHttpRequest:globalScope.XMLHttpRequest};sinonXhr.GlobalXMLHttpRequest=globalScope.XMLHttpRequest;sinonXhr.GlobalActiveXObject=globalScope.ActiveXObject;sinonXhr.supportsActiveX=typeof sinonXhr.GlobalActiveXObject!=="undefined";sinonXhr.supportsXHR=typeof sinonXhr.GlobalXMLHttpRequest!=="undefined";sinonXhr.workingXHR=getWorkingXHR(globalScope);sinonXhr.supportsTimeout=sinonXhr.supportsXHR&&"timeout"in new sinonXhr.GlobalXMLHttpRequest();sinonXhr.supportsCORS=isReactNative||sinonXhr.supportsXHR&&"withCredentials"in new sinonXhr.GlobalXMLHttpRequest();// Note that for FakeXMLHttpRequest to work pre ES5 + // we lose some of the alignment with the spec. + // To ensure as close a match as possible, + // set responseType before calling open, send or respond; + function FakeXMLHttpRequest(config){EventTargetHandler.call(this);this.readyState=FakeXMLHttpRequest.UNSENT;this.requestHeaders={};this.requestBody=null;this.status=0;this.statusText="";this.upload=new EventTargetHandler();this.responseType="";this.response="";this.logError=configureLogError(config);if(sinonXhr.supportsTimeout){this.timeout=0;}if(sinonXhr.supportsCORS){this.withCredentials=false;}if(typeof FakeXMLHttpRequest.onCreate==="function"){FakeXMLHttpRequest.onCreate(this);}}function verifyState(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){throw new Error("INVALID_STATE_ERR");}if(xhr.sendFlag){throw new Error("INVALID_STATE_ERR");}}// largest arity in XHR is 5 - XHR#open + var apply=function apply(obj,method,args){switch(args.length){case 0:return obj[method]();case 1:return obj[method](args[0]);case 2:return obj[method](args[0],args[1]);case 3:return obj[method](args[0],args[1],args[2]);case 4:return obj[method](args[0],args[1],args[2],args[3]);case 5:return obj[method](args[0],args[1],args[2],args[3],args[4]);default:throw new Error("Unhandled case");}};FakeXMLHttpRequest.filters=[];FakeXMLHttpRequest.addFilter=function addFilter(fn){this.filters.push(fn);};FakeXMLHttpRequest.defake=function defake(fakeXhr,xhrArgs){var xhr=new sinonXhr.workingXHR();// eslint-disable-line new-cap + ["open","setRequestHeader","abort","getResponseHeader","getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"].forEach(function(method){fakeXhr[method]=function(){return apply(xhr,method,arguments);};});fakeXhr.send=function(){// Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute + if(xhr.responseType!==fakeXhr.responseType){xhr.responseType=fakeXhr.responseType;}return apply(xhr,"send",arguments);};var copyAttrs=function copyAttrs(args){args.forEach(function(attr){fakeXhr[attr]=xhr[attr];});};var stateChangeStart=function stateChangeStart(){fakeXhr.readyState=xhr.readyState;if(xhr.readyState>=FakeXMLHttpRequest.HEADERS_RECEIVED){copyAttrs(["status","statusText"]);}if(xhr.readyState>=FakeXMLHttpRequest.LOADING){copyAttrs(["response"]);if(xhr.responseType===""||xhr.responseType==="text"){copyAttrs(["responseText"]);}}if(xhr.readyState===FakeXMLHttpRequest.DONE&&(xhr.responseType===""||xhr.responseType==="document")){copyAttrs(["responseXML"]);}};var stateChangeEnd=function stateChangeEnd(){if(fakeXhr.onreadystatechange){// eslint-disable-next-line no-useless-call + fakeXhr.onreadystatechange.call(fakeXhr,{target:fakeXhr,currentTarget:fakeXhr});}};var stateChange=function stateChange(){stateChangeStart();stateChangeEnd();};if(xhr.addEventListener){xhr.addEventListener("readystatechange",stateChangeStart);Object.keys(fakeXhr.eventListeners).forEach(function(event){/*eslint-disable no-loop-func*/fakeXhr.eventListeners[event].forEach(function(handler){xhr.addEventListener(event,handler.listener,{capture:handler.capture,once:handler.once});});/*eslint-enable no-loop-func*/});xhr.addEventListener("readystatechange",stateChangeEnd);}else {xhr.onreadystatechange=stateChange;}apply(xhr,"open",xhrArgs);};FakeXMLHttpRequest.useFilters=false;function verifyRequestOpened(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){var errorMessage=xhr.readyState===FakeXMLHttpRequest.UNSENT?"INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first...":"INVALID_STATE_ERR - ".concat(xhr.readyState);throw new Error(errorMessage);}}function verifyRequestSent(xhr){if(xhr.readyState===FakeXMLHttpRequest.DONE){throw new Error("Request done");}}function verifyHeadersReceived(xhr){if(xhr.async&&xhr.readyState!==FakeXMLHttpRequest.HEADERS_RECEIVED){throw new Error("No headers received");}}function convertResponseBody(responseType,contentType,body){if(responseType===""||responseType==="text"){return body;}else if(supportsArrayBuffer&&responseType==="arraybuffer"){return convertToArrayBuffer(body);}else if(responseType==="json"){try{return JSON.parse(body);}catch(e){// Return parsing failure as null + return null;}}else if(supportsBlob&&responseType==="blob"){if(body instanceof Blob){return body;}var blobOptions={};if(contentType){blobOptions.type=contentType;}return new Blob([convertToArrayBuffer(body)],blobOptions);}else if(responseType==="document"){if(isXmlContentType(contentType)){return FakeXMLHttpRequest.parseXML(body);}return null;}throw new Error("Invalid responseType ".concat(responseType));}/** + * Steps to follow when there is an error, according to: + * https://xhr.spec.whatwg.org/#request-error-steps + */function requestErrorSteps(xhr){clearResponse(xhr);xhr.errorFlag=true;xhr.requestHeaders={};xhr.responseHeaders={};if(xhr.readyState!==FakeXMLHttpRequest.UNSENT&&xhr.sendFlag&&xhr.readyState!==FakeXMLHttpRequest.DONE){xhr.readyStateChange(FakeXMLHttpRequest.DONE);xhr.sendFlag=false;}}FakeXMLHttpRequest.parseXML=function parseXML(text){// Treat empty string as parsing failure + if(text!==""){try{if(typeof DOMParser!=="undefined"){var parser=new DOMParser();var parsererrorNS="";try{var parsererrors=parser.parseFromString("INVALID","text/xml").getElementsByTagName("parsererror");if(parsererrors.length){parsererrorNS=parsererrors[0].namespaceURI;}}catch(e){// passing invalid XML makes IE11 throw + // so no namespace needs to be determined + }var result;try{result=parser.parseFromString(text,"text/xml");}catch(err){return null;}return result.getElementsByTagNameNS(parsererrorNS,"parsererror").length?null:result;}var xmlDoc=new window.ActiveXObject("Microsoft.XMLDOM");xmlDoc.async="false";xmlDoc.loadXML(text);return xmlDoc.parseError.errorCode!==0?null:xmlDoc;}catch(e){// Unable to parse XML - no biggie + }}return null;};FakeXMLHttpRequest.statusCodes={100:"Continue",101:"Switching Protocols",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",300:"Multiple Choice",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported"};extend(FakeXMLHttpRequest.prototype,sinonEvent.EventTarget,{async:true,open:function open(method,url,async,username,password){this.method=method;this.url=url;this.async=typeof async==="boolean"?async:true;this.username=username;this.password=password;clearResponse(this);this.requestHeaders={};this.sendFlag=false;if(FakeXMLHttpRequest.useFilters===true){var xhrArgs=arguments;var defake=FakeXMLHttpRequest.filters.some(function(filter){return filter.apply(this,xhrArgs);});if(defake){FakeXMLHttpRequest.defake(this,arguments);return;}}this.readyStateChange(FakeXMLHttpRequest.OPENED);},readyStateChange:function readyStateChange(state){this.readyState=state;var readyStateChangeEvent=new sinonEvent.Event("readystatechange",false,false,this);if(typeof this.onreadystatechange==="function"){try{this.onreadystatechange(readyStateChangeEvent);}catch(e){this.logError("Fake XHR onreadystatechange handler",e);}}if(this.readyState!==FakeXMLHttpRequest.DONE){this.dispatchEvent(readyStateChangeEvent);}else {var event,progress;if(this.timedOut||this.aborted||this.status===0){progress={loaded:0,total:0};event=this.timedOut&&"timeout"||this.aborted&&"abort"||"error";}else {progress={loaded:100,total:100};event="load";}if(supportsProgress){this.upload.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}this.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.dispatchEvent(readyStateChangeEvent);this.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}},// Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method + setRequestHeader:function setRequestHeader(header,value){if(typeof value!=="string"){throw new TypeError("By RFC7230, section 3.2.4, header values should be strings. Got ".concat(_typeof$1(value)));}verifyState(this);var checkUnsafeHeaders=true;if(typeof this.unsafeHeadersEnabled==="function"){checkUnsafeHeaders=this.unsafeHeadersEnabled();}if(checkUnsafeHeaders&&(getHeader(unsafeHeaders,header)!==null||/^(Sec-|Proxy-)/i.test(header))){throw new Error(// eslint-disable-next-line quotes + "Refused to set unsafe header \"".concat(header,"\""));}// eslint-disable-next-line no-param-reassign + value=normalizeHeaderValue(value);var existingHeader=getHeader(this.requestHeaders,header);if(existingHeader){this.requestHeaders[existingHeader]+=", ".concat(value);}else {this.requestHeaders[header]=value;}},setStatus:function setStatus(status){var sanitizedStatus=typeof status==="number"?status:200;verifyRequestOpened(this);this.status=sanitizedStatus;this.statusText=FakeXMLHttpRequest.statusCodes[sanitizedStatus];},// Helps testing + setResponseHeaders:function setResponseHeaders(headers){verifyRequestOpened(this);var responseHeaders=this.responseHeaders={};Object.keys(headers).forEach(function(header){responseHeaders[header]=headers[header];});if(this.async){this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);}else {this.readyState=FakeXMLHttpRequest.HEADERS_RECEIVED;}},// Currently treats ALL data as a DOMString (i.e. no Document) + send:function send(data){verifyState(this);if(!/^(head)$/i.test(this.method)){var contentType=getHeader(this.requestHeaders,"Content-Type");if(this.requestHeaders[contentType]){var value=this.requestHeaders[contentType].split(";");this.requestHeaders[contentType]="".concat(value[0],";charset=utf-8");}else if(supportsFormData&&!(data instanceof FormData)){this.requestHeaders["Content-Type"]="text/plain;charset=utf-8";}this.requestBody=data;}this.errorFlag=false;this.sendFlag=this.async;clearResponse(this);if(typeof this.onSend==="function"){this.onSend(this);}// Only listen if setInterval and Date are a stubbed. + if(sinonXhr.supportsTimeout&&_typeof$1(setInterval.clock)==="object"&&_typeof$1(Date.clock)==="object"){var initiatedTime=Date.now();var self=this;// Listen to any possible tick by fake timers and check to see if timeout has + // been exceeded. It's important to note that timeout can be changed while a request + // is in flight, so we must check anytime the end user forces a clock tick to make + // sure timeout hasn't changed. + // https://xhr.spec.whatwg.org/#dfnReturnLink-2 + var clearIntervalId=setInterval(function(){// Check if the readyState has been reset or is done. If this is the case, there + // should be no timeout. This will also prevent aborted requests and + // fakeServerWithClock from triggering unnecessary responses. + if(self.readyState===FakeXMLHttpRequest.UNSENT||self.readyState===FakeXMLHttpRequest.DONE){clearInterval(clearIntervalId);}else if(typeof self.timeout==="number"&&self.timeout>0){if(Date.now()>=initiatedTime+self.timeout){self.triggerTimeout();clearInterval(clearIntervalId);}}},1);}this.dispatchEvent(new sinonEvent.Event("loadstart",false,false,this));},abort:function abort(){this.aborted=true;requestErrorSteps(this);this.readyState=FakeXMLHttpRequest.UNSENT;},error:function error(){clearResponse(this);this.errorFlag=true;this.requestHeaders={};this.responseHeaders={};this.readyStateChange(FakeXMLHttpRequest.DONE);},triggerTimeout:function triggerTimeout(){if(sinonXhr.supportsTimeout){this.timedOut=true;requestErrorSteps(this);}},getResponseHeader:function getResponseHeader(header){if(this.readyState=FakeXMLHttpRequest.LOADING){throw new Error("INVALID_STATE_ERR");}this.overriddenMimeType=type;}});var states={UNSENT:0,OPENED:1,HEADERS_RECEIVED:2,LOADING:3,DONE:4};extend(FakeXMLHttpRequest,states);extend(FakeXMLHttpRequest.prototype,states);function useFakeXMLHttpRequest(){FakeXMLHttpRequest.restore=function restore(keepOnCreate){if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=sinonXhr.GlobalXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=sinonXhr.GlobalActiveXObject;}delete FakeXMLHttpRequest.restore;if(keepOnCreate!==true){delete FakeXMLHttpRequest.onCreate;}};if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=FakeXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=function ActiveXObject(objId){if(objId==="Microsoft.XMLHTTP"||/^Msxml2\.XMLHTTP/i.test(objId)){return new FakeXMLHttpRequest();}return new sinonXhr.GlobalActiveXObject(objId);};}return FakeXMLHttpRequest;}return {xhr:sinonXhr,FakeXMLHttpRequest:FakeXMLHttpRequest,useFakeXMLHttpRequest:useFakeXMLHttpRequest};}module.exports=extend(fakeXMLHttpRequestFor(globalObject),{fakeXMLHttpRequestFor:fakeXMLHttpRequestFor});},{"../configure-logger":116,"../event":120,"./blob":125,"@sinonjs/commons":134,"@sinonjs/text-encoding":107,"just-extend":114}],127:[function(require,module,exports){module.exports={fakeServer:require("./fake-server"),fakeServerWithClock:require("./fake-server/fake-server-with-clock"),fakeXhr:require("./fake-xhr")};},{"./fake-server":123,"./fake-server/fake-server-with-clock":122,"./fake-xhr":126}],128:[function(require,module,exports){arguments[4][41][0].apply(exports,arguments);},{"./prototypes/array":136,"dup":41}],129:[function(require,module,exports){arguments[4][42][0].apply(exports,arguments);},{"./function-name":132,"dup":42}],130:[function(require,module,exports){arguments[4][43][0].apply(exports,arguments);},{"dup":43}],131:[function(require,module,exports){arguments[4][44][0].apply(exports,arguments);},{"dup":44}],132:[function(require,module,exports){arguments[4][45][0].apply(exports,arguments);},{"dup":45}],133:[function(require,module,exports){arguments[4][46][0].apply(exports,arguments);},{"dup":46}],134:[function(require,module,exports){arguments[4][47][0].apply(exports,arguments);},{"./called-in-order":128,"./class-name":129,"./deprecated":130,"./every":131,"./function-name":132,"./global":133,"./order-by-first-call":135,"./prototypes":139,"./type-of":145,"./value-to-string":146,"dup":47}],135:[function(require,module,exports){arguments[4][48][0].apply(exports,arguments);},{"./prototypes/array":136,"dup":48}],136:[function(require,module,exports){arguments[4][49][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":49}],137:[function(require,module,exports){arguments[4][50][0].apply(exports,arguments);},{"./throws-on-proto":144,"dup":50}],138:[function(require,module,exports){arguments[4][51][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":51}],139:[function(require,module,exports){arguments[4][52][0].apply(exports,arguments);},{"./array":136,"./function":138,"./map":140,"./object":141,"./set":142,"./string":143,"dup":52}],140:[function(require,module,exports){arguments[4][53][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":53}],141:[function(require,module,exports){arguments[4][54][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":54}],142:[function(require,module,exports){arguments[4][55][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":55}],143:[function(require,module,exports){arguments[4][56][0].apply(exports,arguments);},{"./copy-prototype-methods":137,"dup":56}],144:[function(require,module,exports){arguments[4][57][0].apply(exports,arguments);},{"dup":57}],145:[function(require,module,exports){arguments[4][58][0].apply(exports,arguments);},{"dup":58,"type-detect":150}],146:[function(require,module,exports){arguments[4][59][0].apply(exports,arguments);},{"dup":59}],147:[function(require,module,exports){var isarray=require('isarray');/** + * Expose `pathToRegexp`. + */module.exports=pathToRegexp;module.exports.parse=parse;module.exports.compile=compile;module.exports.tokensToFunction=tokensToFunction;module.exports.tokensToRegExp=tokensToRegExp;/** + * The main path matching regexp utility. + * + * @type {RegExp} + */var PATH_REGEXP=new RegExp([// Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)',// Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'].join('|'),'g');/** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */function parse(str,options){var tokens=[];var key=0;var index=0;var path='';var defaultDelimiter=options&&options.delimiter||'/';var res;while((res=PATH_REGEXP.exec(str))!=null){var m=res[0];var escaped=res[1];var offset=res.index;path+=str.slice(index,offset);index=offset+m.length;// Ignore already escaped sequences. + if(escaped){path+=escaped[1];continue;}var next=str[index];var prefix=res[2];var name=res[3];var capture=res[4];var group=res[5];var modifier=res[6];var asterisk=res[7];// Push the current path onto the tokens. + if(path){tokens.push(path);path='';}var partial=prefix!=null&&next!=null&&next!==prefix;var repeat=modifier==='+'||modifier==='*';var optional=modifier==='?'||modifier==='*';var delimiter=res[2]||defaultDelimiter;var pattern=capture||group;tokens.push({name:name||key++,prefix:prefix||'',delimiter:delimiter,optional:optional,repeat:repeat,partial:partial,asterisk:!!asterisk,pattern:pattern?escapeGroup(pattern):asterisk?'.*':'[^'+escapeString(delimiter)+']+?'});}// Match any characters still remaining. + if(index + * MIT Licensed + */var promiseExists=typeof Promise==='function';/* eslint-disable no-undef */var globalObject=(typeof self==="undefined"?"undefined":_typeof$1(self))==='object'?self:commonjsGlobal$1;// eslint-disable-line id-blacklist + var symbolExists=typeof Symbol!=='undefined';var mapExists=typeof Map!=='undefined';var setExists=typeof Set!=='undefined';var weakMapExists=typeof WeakMap!=='undefined';var weakSetExists=typeof WeakSet!=='undefined';var dataViewExists=typeof DataView!=='undefined';var symbolIteratorExists=symbolExists&&typeof Symbol.iterator!=='undefined';var symbolToStringTagExists=symbolExists&&typeof Symbol.toStringTag!=='undefined';var setEntriesExists=setExists&&typeof Set.prototype.entries==='function';var mapEntriesExists=mapExists&&typeof Map.prototype.entries==='function';var setIteratorPrototype=setEntriesExists&&Object.getPrototypeOf(new Set().entries());var mapIteratorPrototype=mapEntriesExists&&Object.getPrototypeOf(new Map().entries());var arrayIteratorExists=symbolIteratorExists&&typeof Array.prototype[Symbol.iterator]==='function';var arrayIteratorPrototype=arrayIteratorExists&&Object.getPrototypeOf([][Symbol.iterator]());var stringIteratorExists=symbolIteratorExists&&typeof String.prototype[Symbol.iterator]==='function';var stringIteratorPrototype=stringIteratorExists&&Object.getPrototypeOf(''[Symbol.iterator]());var toStringLeftSliceLength=8;var toStringRightSliceLength=-1;/** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */function typeDetect(obj){/* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */var typeofObj=_typeof$1(obj);if(typeofObj!=='object'){return typeofObj;}/* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */if(obj===null){return 'null';}/* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */if(obj===globalObject){return 'global';}/* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) + */if(Array.isArray(obj)&&(symbolToStringTagExists===false||!(Symbol.toStringTag in obj))){return 'Array';}// Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if((typeof window==="undefined"?"undefined":_typeof$1(window))==='object'&&window!==null){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" + */if(_typeof$1(window.location)==='object'&&obj===window.location){return 'Location';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */if(_typeof$1(window.document)==='object'&&obj===window.document){return 'Document';}if(_typeof$1(window.navigator)==='object'){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */if(_typeof$1(window.navigator.mimeTypes)==='object'&&obj===window.navigator.mimeTypes){return 'MimeTypeArray';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */if(_typeof$1(window.navigator.plugins)==='object'&&obj===window.navigator.plugins){return 'PluginArray';}}if((typeof window.HTMLElement==='function'||_typeof$1(window.HTMLElement)==='object')&&obj instanceof window.HTMLElement){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */if(obj.tagName==='BLOCKQUOTE'){return 'HTMLQuoteElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TD'){return 'HTMLTableDataCellElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TH'){return 'HTMLTableHeaderCellElement';}}}/* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */var stringTag=symbolToStringTagExists&&obj[Symbol.toStringTag];if(typeof stringTag==='string'){return stringTag;}var objPrototype=Object.getPrototypeOf(obj);/* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */if(objPrototype===RegExp.prototype){return 'RegExp';}/* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */if(objPrototype===Date.prototype){return 'Date';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */if(promiseExists&&objPrototype===Promise.prototype){return 'Promise';}/* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */if(setExists&&objPrototype===Set.prototype){return 'Set';}/* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */if(mapExists&&objPrototype===Map.prototype){return 'Map';}/* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */if(weakSetExists&&objPrototype===WeakSet.prototype){return 'WeakSet';}/* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */if(weakMapExists&&objPrototype===WeakMap.prototype){return 'WeakMap';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */if(dataViewExists&&objPrototype===DataView.prototype){return 'DataView';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */if(mapExists&&objPrototype===mapIteratorPrototype){return 'Map Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" + */if(setExists&&objPrototype===setIteratorPrototype){return 'Set Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(arrayIteratorExists&&objPrototype===arrayIteratorPrototype){return 'Array Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(stringIteratorExists&&objPrototype===stringIteratorPrototype){return 'String Iterator';}/* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */if(objPrototype===null){return 'Object';}return Object.prototype.toString.call(obj).slice(toStringLeftSliceLength,toStringRightSliceLength);}return typeDetect;});},{}]},{},[1])(1);});})(sinon$3,sinon$3.exports);var sinonExports=sinon$3.exports;var sinon$2=/*@__PURE__*/getDefaultExportFromCjs(sinonExports);var commonjsGlobal$2=typeof globalThis!=='undefined'?globalThis:typeof window!=='undefined'?window:typeof commonjsGlobal!=='undefined'?commonjsGlobal:typeof self!=='undefined'?self:{};function unwrapExports(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,'default')?x['default']:x;}function createCommonjsModule(fn,module){return module={exports:{}},fn(module,module.exports),module.exports;}/** + * Helpers. + */var s=1000;var m=s*60;var h=m*60;var d=h*24;var w=d*7;var y=d*365.25;/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */var ms=function ms(val,options){options=options||{};var type=_typeof$1(val);if(type==='string'&&val.length>0){return parse(val);}else if(type==='number'&&isFinite(val)){return options["long"]?fmtLong(val):fmtShort(val);}throw new Error('val is not a non-empty string or a valid number. val='+JSON.stringify(val));};/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */function parse(str){str=String(str);if(str.length>100){return;}var match=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);if(!match){return;}var n=parseFloat(match[1]);var type=(match[2]||'ms').toLowerCase();switch(type){case'years':case'year':case'yrs':case'yr':case'y':return n*y;case'weeks':case'week':case'w':return n*w;case'days':case'day':case'd':return n*d;case'hours':case'hour':case'hrs':case'hr':case'h':return n*h;case'minutes':case'minute':case'mins':case'min':case'm':return n*m;case'seconds':case'second':case'secs':case'sec':case's':return n*s;case'milliseconds':case'millisecond':case'msecs':case'msec':case'ms':return n;default:return undefined;}}/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */function fmtShort(ms){var msAbs=Math.abs(ms);if(msAbs>=d){return Math.round(ms/d)+'d';}if(msAbs>=h){return Math.round(ms/h)+'h';}if(msAbs>=m){return Math.round(ms/m)+'m';}if(msAbs>=s){return Math.round(ms/s)+'s';}return ms+'ms';}/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */function fmtLong(ms){var msAbs=Math.abs(ms);if(msAbs>=d){return plural(ms,msAbs,d,'day');}if(msAbs>=h){return plural(ms,msAbs,h,'hour');}if(msAbs>=m){return plural(ms,msAbs,m,'minute');}if(msAbs>=s){return plural(ms,msAbs,s,'second');}return ms+' ms';}/** + * Pluralization helper. + */function plural(ms,msAbs,n,name){var isPlural=msAbs>=n*1.5;return Math.round(ms/n)+' '+name+(isPlural?'s':'');}/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */function setup(env){createDebug.debug=createDebug;createDebug["default"]=createDebug;createDebug.coerce=coerce;createDebug.disable=disable;createDebug.enable=enable;createDebug.enabled=enabled;createDebug.humanize=ms;Object.keys(env).forEach(function(key){createDebug[key]=env[key];});/** + * Active `debug` instances. + */createDebug.instances=[];/** + * The currently active debug mode names, and names to skip. + */createDebug.names=[];createDebug.skips=[];/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */createDebug.formatters={};/** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */function selectColor(namespace){var hash=0;for(var i=0;i= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ // eslint-disable-next-line complexity + function useColors(){// NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if(typeof window!=='undefined'&&window.process&&(window.process.type==='renderer'||window.process.__nwjs)){return true;}// Internet Explorer and Edge do not support colors. + if(typeof navigator!=='undefined'&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)){return false;}// Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return typeof document!=='undefined'&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||// Is firebug? http://stackoverflow.com/a/398120/376773 + typeof window!=='undefined'&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||// Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + typeof navigator!=='undefined'&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||// Double check webkit in userAgent just in case we are in a worker + typeof navigator!=='undefined'&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);}/** + * Colorize log arguments if enabled. + * + * @api public + */function formatArgs(args){args[0]=(this.useColors?'%c':'')+this.namespace+(this.useColors?' %c':' ')+args[0]+(this.useColors?'%c ':' ')+'+'+module.exports.humanize(this.diff);if(!this.useColors){return;}var c='color: '+this.color;args.splice(1,0,c,'color: inherit');// The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index=0;var lastC=0;args[0].replace(/%[a-zA-Z%]/g,function(match){if(match==='%%'){return;}index++;if(match==='%c'){// We only are interested in the *last* %c + // (the user may have provided their own) + lastC=index;}});args.splice(lastC,0,c);}/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */function log(){var _console;// This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return (typeof console==="undefined"?"undefined":_typeof$1(console))==='object'&&console.log&&(_console=console).log.apply(_console,arguments);}/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */function save(namespaces){try{if(namespaces){exports.storage.setItem('debug',namespaces);}else {exports.storage.removeItem('debug');}}catch(error){// Swallow + // XXX (@Qix-) should we be logging these? + }}/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */function load(){var r;try{r=exports.storage.getItem('debug');}catch(error){// Swallow + // XXX (@Qix-) should we be logging these? + }// If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if(!r&&typeof process!=='undefined'&&'env'in process){r=process.env.DEBUG;}return r;}/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */function localstorage(){try{// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage;}catch(error){// Swallow + // XXX (@Qix-) should we be logging these? + }}module.exports=common(exports);var formatters=module.exports.formatters;/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */formatters.j=function(v){try{return JSON.stringify(v);}catch(error){return '[UnexpectedJSONParseError]: '+error.message;}};});browser.log;browser.formatArgs;browser.save;browser.load;browser.useColors;browser.storage;browser.colors;var debugFunc;var phase='default';var namespace='';var newDebug=function newDebug(){debugFunc=namespace?browser("fetch-mock:".concat(phase,":").concat(namespace)):browser("fetch-mock:".concat(phase));};var newDebugSandbox=function newDebugSandbox(ns){return browser("fetch-mock:".concat(phase,":").concat(ns));};newDebug();var debug_1={debug:function debug(){debugFunc.apply(void 0,arguments);},setDebugNamespace:function setDebugNamespace(str){namespace=str;newDebug();},setDebugPhase:function setDebugPhase(str){phase=str||'default';newDebug();},getDebug:function getDebug(namespace){return newDebugSandbox(namespace);}};var globToRegexp=function globToRegexp(glob,opts){if(typeof glob!=='string'){throw new TypeError('Expected a string');}var str=String(glob);// The regexp we are building, as a string. + var reStr="";// Whether we are matching so called "extended" globs (like bash) and should + // support single character matching, matching ranges of characters, group + // matching, etc. + var extended=opts?!!opts.extended:false;// When globstar is _false_ (default), '/foo/*' is translated a regexp like + // '^\/foo\/.*$' which will match any string beginning with '/foo/' + // When globstar is _true_, '/foo/*' is translated to regexp like + // '^\/foo\/[^/]*$' which will match any string beginning with '/foo/' BUT + // which does not have a '/' to the right of it. + // E.g. with '/foo/*' these will match: '/foo/bar', '/foo/bar.txt' but + // these will not '/foo/bar/baz', '/foo/bar/baz.txt' + // Lastely, when globstar is _true_, '/foo/**' is equivelant to '/foo/*' when + // globstar is _false_ + var globstar=opts?!!opts.globstar:false;// If we are doing extended matching, this boolean is true when we are inside + // a group (eg {*.html,*.js}), and false otherwise. + var inGroup=false;// RegExp flags (eg "i" ) to pass in to RegExp constructor. + var flags=opts&&typeof opts.flags==="string"?opts.flags:"";var c;for(var i=0,len=str.length;i1// multiple "*"'s + &&(prevChar==="/"||prevChar===undefined)// from the start of the segment + &&(nextChar==="/"||nextChar===undefined);// to the end of the segment + if(isGlobstar){// it's a globstar, so match zero or more path segments + reStr+="((?:[^/]*(?:\/|$))*)";i++;// move over the "/" + }else {// it's not a globstar, so only match one path segment + reStr+="([^/]*)";}}break;default:reStr+=c;}}// When regexp 'g' flag is specified don't + // constrain the regular expression with ^ & $ + if(!flags||!~flags.indexOf('g')){reStr="^"+reStr+"$";}return new RegExp(reStr,flags);};/** + * Expose `pathToRegexp`. + */var pathToRegexp_1=pathToRegexp;var parse_1=parse$1;var compile_1=compile;var tokensToFunction_1=tokensToFunction;var tokensToRegExp_1=tokensToRegExp;/** + * Default configs. + */var DEFAULT_DELIMITER='/';var DEFAULT_DELIMITERS='./';/** + * The main path matching regexp utility. + * + * @type {RegExp} + */var PATH_REGEXP=new RegExp([// Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)',// Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // ":test(\\d+)?" => ["test", "\d+", undefined, "?"] + // "(\\d+)" => [undefined, undefined, "\d+", undefined] + '(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?'].join('|'),'g');/** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */function parse$1(str,options){var tokens=[];var key=0;var index=0;var path='';var defaultDelimiter=options&&options.delimiter||DEFAULT_DELIMITER;var delimiters=options&&options.delimiters||DEFAULT_DELIMITERS;var pathEscaped=false;var res;while((res=PATH_REGEXP.exec(str))!==null){var m=res[0];var escaped=res[1];var offset=res.index;path+=str.slice(index,offset);index=offset+m.length;// Ignore already escaped sequences. + if(escaped){path+=escaped[1];pathEscaped=true;continue;}var prev='';var next=str[index];var name=res[2];var capture=res[3];var group=res[4];var modifier=res[5];if(!pathEscaped&&path.length){var k=path.length-1;if(delimiters.indexOf(path[k])>-1){prev=path[k];path=path.slice(0,k);}}// Push the current path onto the tokens. + if(path){tokens.push(path);path='';pathEscaped=false;}var partial=prev!==''&&next!==undefined&&next!==prev;var repeat=modifier==='+'||modifier==='*';var optional=modifier==='?'||modifier==='*';var delimiter=prev||defaultDelimiter;var pattern=capture||group;tokens.push({name:name||key++,prefix:prev,delimiter:delimiter,optional:optional,repeat:repeat,partial:partial,pattern:pattern?escapeGroup(pattern):'[^'+escapeString(delimiter)+']+?'});}// Push any remaining characters. + if(path||index-1;}else {var capture=token.repeat?'(?:'+token.pattern+')(?:'+escapeString(token.delimiter)+'(?:'+token.pattern+'))*':token.pattern;if(keys)keys.push(token);if(token.optional){if(token.partial){route+=escapeString(token.prefix)+'('+capture+')?';}else {route+='(?:'+escapeString(token.prefix)+'('+capture+'))?';}}else {route+=escapeString(token.prefix)+'('+capture+')';}}}if(end){if(!strict)route+='(?:'+delimiter+')?';route+=endsWith==='$'?'$':'(?='+endsWith+')';}else {if(!strict)route+='(?:'+delimiter+'(?='+endsWith+'))?';if(!isEndDelimited)route+='(?='+delimiter+'|'+endsWith+')';}return new RegExp(route,flags(options));}/** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(string|RegExp|Array)} path + * @param {Array=} keys + * @param {Object=} options + * @return {!RegExp} + */function pathToRegexp(path,keys,options){if(path instanceof RegExp){return regexpToRegexp(path,keys);}if(Array.isArray(path)){return arrayToRegexp(/** @type {!Array} */path,keys,options);}return stringToRegexp(/** @type {string} */path,keys,options);}pathToRegexp_1.parse=parse_1;pathToRegexp_1.compile=compile_1;pathToRegexp_1.tokensToFunction=tokensToFunction_1;pathToRegexp_1.tokensToRegExp=tokensToRegExp_1;// Copyright Joyent, Inc. and other Node contributors. + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);}var decode=function decode(qs,sep,eq,options){sep=sep||'&';eq=eq||'=';var obj={};if(typeof qs!=='string'||qs.length===0){return obj;}var regexp=/\+/g;qs=qs.split(sep);var maxKeys=1000;if(options&&typeof options.maxKeys==='number'){maxKeys=options.maxKeys;}var len=qs.length;// maxKeys <= 0 means that we should not limit keys count + if(maxKeys>0&&len>maxKeys){len=maxKeys;}for(var i=0;i=0){kstr=x.substr(0,idx);vstr=x.substr(idx+1);}else {kstr=x;vstr='';}k=decodeURIComponent(kstr);v=decodeURIComponent(vstr);if(!hasOwnProperty(obj,k)){obj[k]=v;}else if(Array.isArray(obj[k])){obj[k].push(v);}else {obj[k]=[obj[k],v];}}return obj;};// Copyright Joyent, Inc. and other Node contributors. + var stringifyPrimitive=function stringifyPrimitive(v){switch(_typeof$1(v)){case'string':return v;case'boolean':return v?'true':'false';case'number':return isFinite(v)?v:'';default:return '';}};var encode=function encode(obj,sep,eq,name){sep=sep||'&';eq=eq||'=';if(obj===null){obj=undefined;}if(_typeof$1(obj)==='object'){return Object.keys(obj).map(function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;if(Array.isArray(obj[k])){return obj[k].map(function(v){return ks+encodeURIComponent(stringifyPrimitive(v));}).join(sep);}else {return ks+encodeURIComponent(stringifyPrimitive(obj[k]));}}).join(sep);}if(!name)return '';return encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj));};var querystring=createCommonjsModule(function(module,exports){exports.decode=exports.parse=decode;exports.encode=exports.stringify=encode;});querystring.decode;querystring.parse;querystring.encode;querystring.stringify;var isSubset_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,'__esModule',{value:true});/** + * Check if an object is contained within another object. + * + * Returns `true` if: + * - all enumerable keys of *subset* are also enumerable in *superset*, and + * - every value assigned to an enumerable key of *subset* strictly equals + * the value assigned to the same key of *superset* – or is a subset of it. + * + * @param {Object} superset + * @param {Object} subset + * + * @returns {Boolean} + * + * @module is-subset + * @function default + * @alias isSubset + */var isSubset=function(_isSubset){function isSubset(_x,_x2){return _isSubset.apply(this,arguments);}isSubset.toString=function(){return _isSubset.toString();};return isSubset;}(function(superset,subset){if(_typeof$1(superset)!=='object'||superset===null||_typeof$1(subset)!=='object'||subset===null)return false;return Object.keys(subset).every(function(key){if(!superset.propertyIsEnumerable(key))return false;var subsetItem=subset[key];var supersetItem=superset[key];if(_typeof$1(subsetItem)==='object'&&subsetItem!==null?!isSubset(supersetItem,subsetItem):supersetItem!==subsetItem)return false;return true;});});exports['default']=isSubset;module.exports=exports['default'];});unwrapExports(isSubset_1);var URL;// https://stackoverflow.com/a/19709846/308237 + var absoluteUrlRX=new RegExp('^(?:[a-z]+:)?//','i');var headersToArray=function headersToArray(headers){// node-fetch 1 Headers + if(typeof headers.raw==='function'){return Object.entries(headers.raw());}else if(headers[Symbol.iterator]){return _toConsumableArray(headers);}else {return Object.entries(headers);}};var zipObject=function zipObject(entries){return entries.reduce(function(obj,_ref){var _ref2=_slicedToArray(_ref,2),key=_ref2[0],val=_ref2[1];return Object.assign(obj,_defineProperty({},key,val));},{});};var normalizeUrl=function normalizeUrl(url){if(typeof url==='function'||url instanceof RegExp||/^(begin|end|glob|express|path)\:/.test(url)){return url;}if(absoluteUrlRX.test(url)){var u=new URL(url);return u.href;}else {var _u2=new URL(url,'http://dummy');return _u2.pathname+_u2.search;}};var extractBody=/*#__PURE__*/function(){var _ref3=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(request){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:_context.prev=0;if(!('body'in request)){_context.next=3;break;}return _context.abrupt("return",request.body.toString());case 3:return _context.abrupt("return",request.clone().text());case 6:_context.prev=6;_context.t0=_context["catch"](0);return _context.abrupt("return");case 9:case"end":return _context.stop();}},_callee,null,[[0,6]]);}));return function extractBody(_x3){return _ref3.apply(this,arguments);};}();var requestUtils={setUrlImplementation:function setUrlImplementation(it){URL=it;},normalizeRequest:function normalizeRequest(url,options,Request){if(Request.prototype.isPrototypeOf(url)){var derivedOptions={method:url.method};var body=extractBody(url);if(typeof body!=='undefined'){derivedOptions.body=body;}var normalizedRequestObject={url:normalizeUrl(url.url),options:Object.assign(derivedOptions,options),request:url,signal:options&&options.signal||url.signal};var headers=headersToArray(url.headers);if(headers.length){normalizedRequestObject.options.headers=zipObject(headers);}return normalizedRequestObject;}else if(typeof url==='string'||// horrible URL object duck-typing + _typeof$1(url)==='object'&&'href'in url){return {url:normalizeUrl(url),options:options,signal:options&&options.signal};}else if(_typeof$1(url)==='object'){throw new TypeError('fetch-mock: Unrecognised Request object. Read the Config and Installation sections of the docs');}else {throw new TypeError('fetch-mock: Invalid arguments passed to fetch');}},normalizeUrl:normalizeUrl,getPath:function getPath(url){var u=absoluteUrlRX.test(url)?new URL(url):new URL(url,'http://dummy');return u.pathname;},getQuery:function getQuery(url){var u=absoluteUrlRX.test(url)?new URL(url):new URL(url,'http://dummy');return u.search?u.search.substr(1):'';},headers:{normalize:function normalize(headers){return zipObject(headersToArray(headers));},toLowerCase:function toLowerCase(headers){return Object.keys(headers).reduce(function(obj,k){obj[k.toLowerCase()]=headers[k];return obj;},{});},equal:function equal(actualHeader,expectedHeader){actualHeader=Array.isArray(actualHeader)?actualHeader:[actualHeader];expectedHeader=Array.isArray(expectedHeader)?expectedHeader:[expectedHeader];if(actualHeader.length!==expectedHeader.length){return false;}return actualHeader.every(function(val,i){return val===expectedHeader[i];});}}};var lodash_isequal=createCommonjsModule(function(module,exports){/** + * Lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright JS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ /** Used as the size to enable large array optimizations. */var LARGE_ARRAY_SIZE=200;/** Used to stand-in for `undefined` hash values. */var HASH_UNDEFINED='__lodash_hash_undefined__';/** Used to compose bitmasks for value comparisons. */var COMPARE_PARTIAL_FLAG=1,COMPARE_UNORDERED_FLAG=2;/** Used as references for various `Number` constants. */var MAX_SAFE_INTEGER=9007199254740991;/** `Object#toString` result references. */var argsTag='[object Arguments]',arrayTag='[object Array]',asyncTag='[object AsyncFunction]',boolTag='[object Boolean]',dateTag='[object Date]',errorTag='[object Error]',funcTag='[object Function]',genTag='[object GeneratorFunction]',mapTag='[object Map]',numberTag='[object Number]',nullTag='[object Null]',objectTag='[object Object]',promiseTag='[object Promise]',proxyTag='[object Proxy]',regexpTag='[object RegExp]',setTag='[object Set]',stringTag='[object String]',symbolTag='[object Symbol]',undefinedTag='[object Undefined]',weakMapTag='[object WeakMap]';var arrayBufferTag='[object ArrayBuffer]',dataViewTag='[object DataView]',float32Tag='[object Float32Array]',float64Tag='[object Float64Array]',int8Tag='[object Int8Array]',int16Tag='[object Int16Array]',int32Tag='[object Int32Array]',uint8Tag='[object Uint8Array]',uint8ClampedTag='[object Uint8ClampedArray]',uint16Tag='[object Uint16Array]',uint32Tag='[object Uint32Array]';/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */var reRegExpChar=/[\\^$.*+?()[\]{}|]/g;/** Used to detect host constructors (Safari). */var reIsHostCtor=/^\[object .+?Constructor\]$/;/** Used to detect unsigned integer values. */var reIsUint=/^(?:0|[1-9]\d*)$/;/** Used to identify `toStringTag` values of typed arrays. */var typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=true;typedArrayTags[argsTag]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dataViewTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=false;/** Detect free variable `global` from Node.js. */var freeGlobal=_typeof$1(commonjsGlobal$2)=='object'&&commonjsGlobal$2&&commonjsGlobal$2.Object===Object&&commonjsGlobal$2;/** Detect free variable `self`. */var freeSelf=(typeof self==="undefined"?"undefined":_typeof$1(self))=='object'&&self&&self.Object===Object&&self;/** Used as a reference to the global object. */var root=freeGlobal||freeSelf||Function('return this')();/** Detect free variable `exports`. */var freeExports=exports&&!exports.nodeType&&exports;/** Detect free variable `module`. */var freeModule=freeExports&&'object'=='object'&&module&&!module.nodeType&&module;/** Detect the popular CommonJS extension `module.exports`. */var moduleExports=freeModule&&freeModule.exports===freeExports;/** Detect free variable `process` from Node.js. */var freeProcess=moduleExports&&freeGlobal.process;/** Used to access faster Node.js helpers. */var nodeUtil=function(){try{return freeProcess&&freeProcess.binding&&freeProcess.binding('util');}catch(e){}}();/* Node.js helper references. */var nodeIsTypedArray=nodeUtil&&nodeUtil.isTypedArray;/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */function arrayFilter(array,predicate){var index=-1,length=array==null?0:array.length,resIndex=0,result=[];while(++index-1;}/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */function listCacheSet(key,value){var data=this.__data__,index=assocIndexOf(data,key);if(index<0){++this.size;data.push([key,value]);}else {data[index][1]=value;}return this;}// Add methods to `ListCache`. + ListCache.prototype.clear=listCacheClear;ListCache.prototype['delete']=listCacheDelete;ListCache.prototype.get=listCacheGet;ListCache.prototype.has=listCacheHas;ListCache.prototype.set=listCacheSet;/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */function MapCache(entries){var index=-1,length=entries==null?0:entries.length;this.clear();while(++indexarrLength)){return false;}// Assume cyclic values are equal. + var stacked=stack.get(array);if(stacked&&stack.get(other)){return stacked==other;}var index=-1,result=true,seen=bitmask&COMPARE_UNORDERED_FLAG?new SetCache():undefined;stack.set(array,other);stack.set(other,array);// Ignore non-index properties. + while(++index-1&&value%1==0&&value true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */function eq(value,other){return value===other||value!==value&&other!==other;}/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */var isArguments=baseIsArguments(function(){return arguments;}())?baseIsArguments:function(value){return isObjectLike(value)&&hasOwnProperty.call(value,'callee')&&!propertyIsEnumerable.call(value,'callee');};/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */var isArray=Array.isArray;/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */function isArrayLike(value){return value!=null&&isLength(value.length)&&!isFunction(value);}/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */var isBuffer=nativeIsBuffer||stubFalse;/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */function isEqual(value,other){return baseIsEqual(value,other);}/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */function isFunction(value){if(!isObject(value)){return false;}// The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag=baseGetTag(value);return tag==funcTag||tag==genTag||tag==asyncTag||tag==proxyTag;}/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */function isLength(value){return typeof value=='number'&&value>-1&&value%1==0&&value<=MAX_SAFE_INTEGER;}/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */function isObject(value){var type=_typeof$1(value);return value!=null&&(type=='object'||type=='function');}/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */function isObjectLike(value){return value!=null&&_typeof$1(value)=='object';}/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */var isTypedArray=nodeIsTypedArray?baseUnary(nodeIsTypedArray):baseIsTypedArray;/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */function keys(object){return isArrayLike(object)?arrayLikeKeys(object):baseKeys(object);}/** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */function stubArray(){return [];}/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */function stubFalse(){return false;}module.exports=isEqual;});var debug=debug_1.debug,setDebugNamespace=debug_1.setDebugNamespace;var headerUtils=requestUtils.headers,getPath=requestUtils.getPath,getQuery=requestUtils.getQuery,normalizeUrl$1=requestUtils.normalizeUrl;var debuggableUrlFunc=function debuggableUrlFunc(func){return function(url){debug('Actual url:',url);return func(url);};};var stringMatchers={begin:function begin(targetString){return debuggableUrlFunc(function(url){return url.indexOf(targetString)===0;});},end:function end(targetString){return debuggableUrlFunc(function(url){return url.substr(-targetString.length)===targetString;});},glob:function glob(targetString){var urlRX=globToRegexp(targetString);return debuggableUrlFunc(function(url){return urlRX.test(url);});},express:function express(targetString){var urlRX=pathToRegexp_1(targetString);return debuggableUrlFunc(function(url){return urlRX.test(getPath(url));});},path:function path(targetString){return debuggableUrlFunc(function(url){return getPath(url)===targetString;});}};var getHeaderMatcher=function getHeaderMatcher(_ref4){var expectedHeaders=_ref4.headers;debug('Generating header matcher');if(!expectedHeaders){debug(' No header expectations defined - skipping');return;}var expectation=headerUtils.toLowerCase(expectedHeaders);debug(' Expected headers:',expectation);return function(url,_ref5){var _ref5$headers=_ref5.headers,headers=_ref5$headers===void 0?{}:_ref5$headers;debug('Attempting to match headers');var lowerCaseHeaders=headerUtils.toLowerCase(headerUtils.normalize(headers));debug(' Expected headers:',expectation);debug(' Actual headers:',lowerCaseHeaders);return Object.keys(expectation).every(function(headerName){return headerUtils.equal(lowerCaseHeaders[headerName],expectation[headerName]);});};};var getMethodMatcher=function getMethodMatcher(_ref6){var expectedMethod=_ref6.method;debug('Generating method matcher');if(!expectedMethod){debug(' No method expectations defined - skipping');return;}debug(' Expected method:',expectedMethod);return function(url,_ref7){var method=_ref7.method;debug('Attempting to match method');var actualMethod=method?method.toLowerCase():'get';debug(' Expected method:',expectedMethod);debug(' Actual method:',actualMethod);return expectedMethod===actualMethod;};};var getQueryStringMatcher=function getQueryStringMatcher(_ref8){var expectedQuery=_ref8.query;debug('Generating query parameters matcher');if(!expectedQuery){debug(' No query parameters expectations defined - skipping');return;}debug(' Expected query parameters:',expectedQuery);var keys=Object.keys(expectedQuery);return function(url){debug('Attempting to match query parameters');var query=querystring.parse(getQuery(url));debug(' Expected query parameters:',expectedQuery);debug(' Actual query parameters:',query);return keys.every(function(key){return query[key]===expectedQuery[key];});};};var getParamsMatcher=function getParamsMatcher(_ref9){var expectedParams=_ref9.params,matcherUrl=_ref9.url;debug('Generating path parameters matcher');if(!expectedParams){debug(' No path parameters expectations defined - skipping');return;}if(!/express:/.test(matcherUrl)){throw new Error('fetch-mock: matching on params is only possible when using an express: matcher');}debug(' Expected path parameters:',expectedParams);var expectedKeys=Object.keys(expectedParams);var keys=[];var re=pathToRegexp_1(matcherUrl.replace(/^express:/,''),keys);return function(url){debug('Attempting to match path parameters');var vals=re.exec(getPath(url))||[];vals.shift();var params=keys.reduce(function(map,_ref10,i){var name=_ref10.name;return vals[i]?Object.assign(map,_defineProperty({},name,vals[i])):map;},{});debug(' Expected path parameters:',expectedParams);debug(' Actual path parameters:',params);return expectedKeys.every(function(key){return params[key]===expectedParams[key];});};};var getBodyMatcher=function getBodyMatcher(route,fetchMock){var matchPartialBody=fetchMock.getOption('matchPartialBody',route);var expectedBody=route.body;debug('Generating body matcher');return function(url,_ref11){var body=_ref11.body,_ref11$method=_ref11.method,method=_ref11$method===void 0?'get':_ref11$method;debug('Attempting to match body');if(method.toLowerCase()==='get'){debug(' GET request - skip matching body');// GET requests don’t send a body so the body matcher should be ignored for them + return true;}var sentBody;try{debug(' Parsing request body as JSON');sentBody=JSON.parse(body);}catch(err){debug(' Failed to parse request body as JSON',err);}debug('Expected body:',expectedBody);debug('Actual body:',sentBody);if(matchPartialBody){debug('matchPartialBody is true - checking for partial match only');}return sentBody&&(matchPartialBody?isSubset_1(sentBody,expectedBody):lodash_isequal(sentBody,expectedBody));};};var getFullUrlMatcher=function getFullUrlMatcher(route,matcherUrl,query){// if none of the special syntaxes apply, it's just a simple string match + // but we have to be careful to normalize the url we check and the name + // of the route to allow for e.g. http://it.at.there being indistinguishable + // from http://it.at.there/ once we start generating Request/Url objects + debug(' Matching using full url',matcherUrl);var expectedUrl=normalizeUrl$1(matcherUrl);debug(' Normalised url to:',matcherUrl);if(route.identifier===matcherUrl){debug(' Updating route identifier to match normalized url:',matcherUrl);route.identifier=expectedUrl;}return function(matcherUrl){debug('Expected url:',expectedUrl);debug('Actual url:',matcherUrl);if(query&&expectedUrl.indexOf('?')){debug('Ignoring query string when matching url');return matcherUrl.indexOf(expectedUrl)===0;}return normalizeUrl$1(matcherUrl)===expectedUrl;};};var getFunctionMatcher=function getFunctionMatcher(_ref12){var functionMatcher=_ref12.functionMatcher;debug('Detected user defined function matcher',functionMatcher);return function(){for(var _len4=arguments.length,args=new Array(_len4),_key5=0;_key5<_len4;_key5++){args[_key5]=arguments[_key5];}debug('Calling function matcher with arguments',args);return functionMatcher.apply(void 0,args);};};var getUrlMatcher=function getUrlMatcher(route){debug('Generating url matcher');var matcherUrl=route.url,query=route.query;if(matcherUrl==='*'){debug(' Using universal * rule to match any url');return function(){return true;};}if(matcherUrl instanceof RegExp){debug(' Using regular expression to match url:',matcherUrl);return function(url){return matcherUrl.test(url);};}if(matcherUrl.href){debug(" Using URL object to match url",matcherUrl);return getFullUrlMatcher(route,matcherUrl.href,query);}for(var shorthand in stringMatchers){if(matcherUrl.indexOf(shorthand+':')===0){debug(" Using ".concat(shorthand,": pattern to match url"),matcherUrl);var urlFragment=matcherUrl.replace(new RegExp("^".concat(shorthand,":")),'');return stringMatchers[shorthand](urlFragment);}}return getFullUrlMatcher(route,matcherUrl,query);};var generateMatcher=function generateMatcher(route,fetchMock){setDebugNamespace('generateMatcher()');debug('Compiling matcher for route');var matchers=[route.query&&getQueryStringMatcher(route),route.method&&getMethodMatcher(route),route.headers&&getHeaderMatcher(route),route.params&&getParamsMatcher(route),route.body&&getBodyMatcher(route,fetchMock),route.functionMatcher&&getFunctionMatcher(route),route.url&&getUrlMatcher(route)].filter(function(matcher){return !!matcher;});debug('Compiled matcher for route');setDebugNamespace();return function(url){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var request=arguments.length>2?arguments[2]:undefined;return matchers.every(function(matcher){return matcher(url,options,request);});};};var getDebug=debug_1.getDebug;var matcherProperties=['query','method','headers','params','body','functionMatcher','url'];var isUrlMatcher=function isUrlMatcher(matcher){return matcher instanceof RegExp||typeof matcher==='string'||_typeof$1(matcher)==='object'&&'href'in matcher;};var isFunctionMatcher=function isFunctionMatcher(matcher){return typeof matcher==='function';};var argsToRoute=function argsToRoute(args){var _args4=_slicedToArray(args,3),matcher=_args4[0],response=_args4[1],_args4$=_args4[2],options=_args4$===void 0?{}:_args4$;var routeConfig={};if(isUrlMatcher(matcher)||isFunctionMatcher(matcher)){routeConfig.matcher=matcher;}else {Object.assign(routeConfig,matcher);}if(response){routeConfig.response=response;}Object.assign(routeConfig,options);return routeConfig;};var sanitizeRoute=function sanitizeRoute(route){var debug=getDebug('sanitizeRoute()');debug('Sanitizing route properties');route=Object.assign({},route);if(route.method){debug("Converting method ".concat(route.method," to lower case"));route.method=route.method.toLowerCase();}if(isUrlMatcher(route.matcher)){debug('Mock uses a url matcher',route.matcher);route.url=route.matcher;delete route.matcher;}route.functionMatcher=route.matcher||route.functionMatcher;debug('Setting route.identifier...');debug(" route.name is ".concat(route.name));debug(" route.url is ".concat(route.url));debug(" route.functionMatcher is ".concat(route.functionMatcher));route.identifier=route.name||route.url||route.functionMatcher;debug(" -> route.identifier set to ".concat(route.identifier));return route;};var validateRoute=function validateRoute(route){if(!('response'in route)){throw new Error('fetch-mock: Each route must define a response');}if(!matcherProperties.some(function(matcherType){return matcherType in route;})){throw new Error("fetch-mock: Each route must specify some criteria for matching calls to fetch. To match all calls use '*'");}};var limit=function limit(route){var debug=getDebug('limit()');debug('Limiting number of requests to handle by route');if(!route.repeat){debug(' No `repeat` value set on route. Will match any number of requests');return;}debug(" Route set to repeat ".concat(route.repeat," times"));var matcher=route.matcher;var timesLeft=route.repeat;route.matcher=function(url,options){var match=timesLeft&&matcher(url,options);if(match){timesLeft--;return true;}};route.reset=function(){return timesLeft=route.repeat;};};var delayResponse=function delayResponse(route){var debug=getDebug('delayResponse()');debug("Applying response delay settings");var delay=route.delay;if(delay){debug(" Wrapping response in delay of ".concat(delay," miliseconds"));var response=route.response;route.response=function(){debug("Delaying response by ".concat(delay," miliseconds"));return new Promise(function(res){return setTimeout(function(){return res(response);},delay);});};}else {debug(" No delay set on route. Will respond 'immediately' (but asynchronously)");}};var compileRoute=function compileRoute(args){var debug=getDebug('compileRoute()');debug('Compiling route');var route=sanitizeRoute(argsToRoute(args));validateRoute(route);route.matcher=generateMatcher(route,this);limit(route);delayResponse(route);return route;};var compileRoute_1={compileRoute:compileRoute,sanitizeRoute:sanitizeRoute};var debug$1=debug_1.debug,setDebugPhase=debug_1.setDebugPhase;var compileRoute$1=compileRoute_1.compileRoute;var FetchMock={};FetchMock.mock=function(){setDebugPhase('setup');for(var _len5=arguments.length,args=new Array(_len5),_key6=0;_key6<_len5;_key6++){args[_key6]=arguments[_key6];}if(args.length){this.addRoute(args);}return this._mock();};FetchMock.addRoute=function(uncompiledRoute){var _this2=this;debug$1('Adding route',uncompiledRoute);var route=this.compileRoute(uncompiledRoute);var clashes=this.routes.filter(function(_ref13){var identifier=_ref13.identifier,method=_ref13.method;return identifier===route.identifier&&(!method||!route.method||method===route.method);});if(this.getOption('overwriteRoutes',route)===false||!clashes.length){this._uncompiledRoutes.push(uncompiledRoute);return this.routes.push(route);}if(this.getOption('overwriteRoutes',route)===true){clashes.forEach(function(clash){var index=_this2.routes.indexOf(clash);_this2._uncompiledRoutes.splice(index,1,uncompiledRoute);_this2.routes.splice(index,1,route);});return this.routes;}if(clashes.length){throw new Error('fetch-mock: Adding route with same name or matcher as existing route. See `overwriteRoutes` option.');}this._uncompiledRoutes.push(uncompiledRoute);this.routes.push(route);};FetchMock._mock=function(){if(!this.isSandbox){// Do this here rather than in the constructor to ensure it's scoped to the test + this.realFetch=this.realFetch||this.global.fetch;this.global.fetch=this.fetchHandler;}setDebugPhase();return this;};FetchMock["catch"]=function(response){if(this.fallbackResponse){console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response');// eslint-disable-line + }this.fallbackResponse=response||'ok';return this._mock();};FetchMock.spy=function(){this._mock();return this["catch"](this.getNativeFetch());};FetchMock.compileRoute=compileRoute$1;var defineShorthand=function defineShorthand(methodName,underlyingMethod,shorthandOptions){FetchMock[methodName]=function(matcher,response,options){return this[underlyingMethod](matcher,response,Object.assign(options||{},shorthandOptions));};};defineShorthand('once','mock',{repeat:1});['get','post','put','delete','head','patch'].forEach(function(method){defineShorthand(method,'mock',{method:method});defineShorthand("".concat(method,"Once"),'once',{method:method});});FetchMock.resetBehavior=function(){if(this.realFetch){this.global.fetch=this.realFetch;this.realFetch=undefined;}this.fallbackResponse=undefined;this.routes=[];this._uncompiledRoutes=[];return this;};FetchMock.resetHistory=function(){this._calls=[];this._holdingPromises=[];this.routes.forEach(function(route){return route.reset&&route.reset();});return this;};FetchMock.restore=FetchMock.reset=function(){this.resetBehavior();this.resetHistory();return this;};var setUpAndTearDown=FetchMock;var getDebug$1=debug_1.getDebug;var responseConfigProps=['body','headers','throws','status','redirectUrl'];var ResponseBuilder=/*#__PURE__*/function(){function ResponseBuilder(options){_classCallCheck(this,ResponseBuilder);this.debug=getDebug$1('ResponseBuilder()');this.debug('Response builder created with options',options);Object.assign(this,options);}_createClass(ResponseBuilder,[{key:"exec",value:function exec(){this.debug('building response');this.normalizeResponseConfig();this.constructFetchOpts();this.constructResponseBody();return this.buildObservableResponse(new this.fetchMock.config.Response(this.body,this.options));}},{key:"sendAsObject",value:function sendAsObject(){var _this3=this;if(responseConfigProps.some(function(prop){return _this3.responseConfig[prop];})){if(Object.keys(this.responseConfig).every(function(key){return responseConfigProps.includes(key);})){return false;}else {return true;}}else {return true;}}},{key:"normalizeResponseConfig",value:function normalizeResponseConfig(){// If the response config looks like a status, start to generate a simple response + if(typeof this.responseConfig==='number'){this.debug('building response using status',this.responseConfig);this.responseConfig={status:this.responseConfig};// If the response config is not an object, or is an object that doesn't use + // any reserved properties, assume it is meant to be the body of the response + }else if(typeof this.responseConfig==='string'||this.sendAsObject()){this.debug('building text response from',this.responseConfig);this.responseConfig={body:this.responseConfig};}}},{key:"validateStatus",value:function validateStatus(status){if(!status){this.debug('No status provided. Defaulting to 200');return 200;}if(typeof status==='number'&&parseInt(status,10)!==status&&status>=200||status<600){this.debug('Valid status provided',status);return status;}throw new TypeError("fetch-mock: Invalid status ".concat(status," passed on response object.\nTo respond with a JSON object that has status as a property assign the object to body\ne.g. {\"body\": {\"status: \"registered\"}}"));}},{key:"constructFetchOpts",value:function constructFetchOpts(){this.options=this.responseConfig.options||{};this.options.url=this.responseConfig.redirectUrl||this.url;this.options.status=this.validateStatus(this.responseConfig.status);this.options.statusText=this.fetchMock.statusTextMap[''+this.options.status];// Set up response headers. The empty object is to cope with + // new Headers(undefined) throwing in Chrome + // https://code.google.com/p/chromium/issues/detail?id=335871 + this.options.headers=new this.fetchMock.config.Headers(this.responseConfig.headers||{});}},{key:"getOption",value:function getOption(name){return this.fetchMock.getOption(name,this.route);}},{key:"convertToJson",value:function convertToJson(){// convert to json if we need to + if(this.getOption('sendAsJson')&&this.responseConfig.body!=null&&//eslint-disable-line + _typeof$1(this.body)==='object'){this.debug('Stringifying JSON response body');this.body=JSON.stringify(this.body);if(!this.options.headers.has('Content-Type')){this.options.headers.set('Content-Type','application/json');}}}},{key:"setContentLength",value:function setContentLength(){// add a Content-Length header if we need to + if(this.getOption('includeContentLength')&&typeof this.body==='string'&&!this.options.headers.has('Content-Length')){this.debug('Setting content-length header:',this.body.length.toString());this.options.headers.set('Content-Length',this.body.length.toString());}}},{key:"constructResponseBody",value:function constructResponseBody(){// start to construct the body + this.body=this.responseConfig.body;this.convertToJson();this.setContentLength();// On the server we need to manually construct the readable stream for the + // Response object (on the client this done automatically) + if(this.Stream){this.debug('Creating response stream');var stream=new this.Stream.Readable();if(this.body!=null){//eslint-disable-line + stream.push(this.body,'utf-8');}stream.push(null);this.body=stream;}this.body=this.body;}},{key:"buildObservableResponse",value:function buildObservableResponse(response){var _this4=this;var fetchMock=this.fetchMock;// Using a proxy means we can set properties that may not be writable on + // the original Response. It also means we can track the resolution of + // promises returned by res.json(), res.text() etc + this.debug('Wrappipng Response in ES proxy for observability');return new Proxy(response,{get:function get(originalResponse,name){if(_this4.responseConfig.redirectUrl){if(name==='url'){_this4.debug('Retrieving redirect url',_this4.responseConfig.redirectUrl);return _this4.responseConfig.redirectUrl;}if(name==='redirected'){_this4.debug('Retrieving redirected status',true);return true;}}if(typeof originalResponse[name]==='function'){_this4.debug('Wrapping body promises in ES proxies for observability');return new Proxy(originalResponse[name],{apply:function apply(func,thisArg,args){_this4.debug("Calling res.".concat(name));var result=func.apply(response,args);if(result.then){fetchMock._holdingPromises.push(result["catch"](function(){return null;}));}return result;}});}return originalResponse[name];}});}}]);return ResponseBuilder;}();var responseBuilder=function responseBuilder(options){return new ResponseBuilder(options).exec();};var debug$2=debug_1.debug,setDebugPhase$1=debug_1.setDebugPhase,getDebug$2=debug_1.getDebug;var FetchMock$1={};// see https://heycam.github.io/webidl/#aborterror for the standardised interface + // Note that this differs slightly from node-fetch + var AbortError=/*#__PURE__*/function(_Error){_inherits(AbortError,_Error);var _super2=_createSuper(AbortError);function AbortError(){var _this5;_classCallCheck(this,AbortError);_this5=_super2.apply(this,arguments);_this5.name='AbortError';_this5.message='The operation was aborted.';// Do not include this class in the stacktrace + if(Error.captureStackTrace){Error.captureStackTrace(_assertThisInitialized(_this5),_this5.constructor);}return _this5;}return _createClass(AbortError);}(/*#__PURE__*/_wrapNativeSuper(Error));var resolve=/*#__PURE__*/function(){var _ref15=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref14,url,options,request){var response,_ref14$responseIsFetc,responseIsFetch,debug;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:response=_ref14.response,_ref14$responseIsFetc=_ref14.responseIsFetch,responseIsFetch=_ref14$responseIsFetc===void 0?false:_ref14$responseIsFetc;debug=getDebug$2('resolve()');debug('Recursively resolving function and promise responses');// We want to allow things like + // - function returning a Promise for a response + // - delaying (using a timeout Promise) a function's execution to generate + // a response + // Because of this we can't safely check for function before Promisey-ness, + // or vice versa. So to keep it DRY, and flexible, we keep trying until we + // have something that looks like neither Promise nor function + case 3:if(!(typeof response==='function')){_context2.next=18;break;}debug(' Response is a function');// in the case of falling back to the network we need to make sure we're using + // the original Request instance, not our normalised url + options + if(!responseIsFetch){_context2.next=14;break;}if(!request){_context2.next=10;break;}debug(' -> Calling fetch with Request instance');return _context2.abrupt("return",response(request));case 10:debug(' -> Calling fetch with url and options');return _context2.abrupt("return",response(url,options));case 14:debug(' -> Calling response function');response=response(url,options,request);case 16:_context2.next=29;break;case 18:if(!(typeof response.then==='function')){_context2.next=26;break;}debug(' Response is a promise');debug(' -> Resolving promise');_context2.next=23;return response;case 23:response=_context2.sent;_context2.next=29;break;case 26:debug(' Response is not a function or a promise');debug(' -> Exiting response resolution recursion');return _context2.abrupt("return",response);case 29:_context2.next=3;break;case 31:case"end":return _context2.stop();}},_callee2);}));return function resolve(_x4,_x5,_x6,_x7){return _ref15.apply(this,arguments);};}();FetchMock$1.fetchHandler=function(url,options,request){setDebugPhase$1('handle');var debug=getDebug$2('fetchHandler()');debug('fetch called with:',url,options);var normalizedRequest=requestUtils.normalizeRequest(url,options,this.config.Request);url=normalizedRequest.url;options=normalizedRequest.options;request=normalizedRequest.request;var signal=normalizedRequest.signal;debug('Request normalised');debug(' url',url);debug(' options',options);debug(' request',request);debug(' signal',signal);if(request&&this.routes.some(function(_ref16){var body=_ref16.body;return !!body;})){debug('Need to wait for Body to be streamed before calling router: switching to async mode');return this._asyncFetchHandler(url,options,request,signal);}return this._fetchHandler(url,options,request,signal);};FetchMock$1._asyncFetchHandler=/*#__PURE__*/function(){var _ref17=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(url,options,request,signal){return _regeneratorRuntime.wrap(function _callee3$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:_context3.next=2;return options.body;case 2:options.body=_context3.sent;return _context3.abrupt("return",this._fetchHandler(url,options,request,signal));case 4:case"end":return _context3.stop();}},_callee3,this);}));return function(_x8,_x9,_x10,_x11){return _ref17.apply(this,arguments);};}();FetchMock$1._fetchHandler=function(url,options,request,signal){var _this6=this;var route=this.executeRouter(url,options,request);// this is used to power the .flush() method + var done;this._holdingPromises.push(new this.config.Promise(function(res){return done=res;}));// wrapped in this promise to make sure we respect custom Promise + // constructors defined by the user + return new this.config.Promise(function(res,rej){if(signal){debug$2('signal exists - enabling fetch abort');var abort=function abort(){debug$2('aborting fetch');// note that DOMException is not available in node.js; even node-fetch uses a custom error class: https://github.com/bitinn/node-fetch/blob/master/src/abort-error.js + rej(typeof DOMException!=='undefined'?new DOMException('The operation was aborted.','AbortError'):new AbortError());done();};if(signal.aborted){debug$2('signal is already aborted - aborting the fetch');abort();}signal.addEventListener('abort',abort);}_this6.generateResponse(route,url,options,request).then(res,rej).then(done,done).then(function(){setDebugPhase$1();});});};FetchMock$1.fetchHandler.isMock=true;FetchMock$1.executeRouter=function(url,options,request){var debug=getDebug$2('executeRouter()');debug("Attempting to match request to a route");if(this.getOption('fallbackToNetwork')==='always'){debug(' Configured with fallbackToNetwork=always - passing through to fetch');return {response:this.getNativeFetch(),responseIsFetch:true};}var match=this.router(url,options,request);if(match){debug(' Matching route found');return match;}if(this.getOption('warnOnFallback')){console.warn("Unmatched ".concat(options&&options.method||'GET'," to ").concat(url));// eslint-disable-line + }this.push({url:url,options:options,request:request,isUnmatched:true});if(this.fallbackResponse){debug(' No matching route found - using fallbackResponse');return {response:this.fallbackResponse};}if(!this.getOption('fallbackToNetwork')){throw new Error("fetch-mock: No fallback response defined for ".concat(options&&options.method||'GET'," to ").concat(url));}debug(' Configured to fallbackToNetwork - passing through to fetch');return {response:this.getNativeFetch(),responseIsFetch:true};};FetchMock$1.generateResponse=/*#__PURE__*/function(){var _ref18=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(route,url,options,request){var debug,response;return _regeneratorRuntime.wrap(function _callee4$(_context4){while(1)switch(_context4.prev=_context4.next){case 0:debug=getDebug$2('generateResponse()');_context4.next=3;return resolve(route,url,options,request);case 3:response=_context4.sent;if(!(response["throws"]&&typeof response!=='function')){_context4.next=7;break;}debug('response.throws is defined - throwing an error');throw response["throws"];case 7:if(!this.config.Response.prototype.isPrototypeOf(response)){_context4.next=10;break;}debug('response is already a Response instance - returning it');return _context4.abrupt("return",response);case 10:return _context4.abrupt("return",responseBuilder({url:url,responseConfig:response,fetchMock:this,route:route}));case 11:case"end":return _context4.stop();}},_callee4,this);}));return function(_x12,_x13,_x14,_x15){return _ref18.apply(this,arguments);};}();FetchMock$1.router=function(url,options,request){var route=this.routes.find(function(route,i){debug$2("Trying to match route ".concat(i));return route.matcher(url,options,request);});if(route){this.push({url:url,options:options,request:request,identifier:route.identifier});return route;}};FetchMock$1.getNativeFetch=function(){var func=this.realFetch||this.isSandbox&&this.config.fetch;if(!func){throw new Error('fetch-mock: Falling back to network only available on global fetch-mock, or by setting config.fetch on sandboxed fetch-mock');}return func;};FetchMock$1.push=function(_ref19){var url=_ref19.url,options=_ref19.options,request=_ref19.request,isUnmatched=_ref19.isUnmatched,identifier=_ref19.identifier;debug$2('Recording fetch call',{url:url,options:options,request:request,isUnmatched:isUnmatched,identifier:identifier});var args=[url,options];args.request=request;args.identifier=identifier;args.isUnmatched=isUnmatched;this._calls.push(args);};var fetchHandler=FetchMock$1;var setDebugPhase$2=debug_1.setDebugPhase,setDebugNamespace$1=debug_1.setDebugNamespace,debug$3=debug_1.debug;var normalizeUrl$2=requestUtils.normalizeUrl;var FetchMock$2={};var sanitizeRoute$1=compileRoute_1.sanitizeRoute;var isName=function isName(nameOrMatcher){return typeof nameOrMatcher==='string'&&/^[\da-zA-Z\-]+$/.test(nameOrMatcher);};var filterCallsWithMatcher=function filterCallsWithMatcher(matcher){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var calls=arguments.length>2?arguments[2]:undefined;matcher=generateMatcher(sanitizeRoute$1(Object.assign({matcher:matcher},options)),this);return calls.filter(function(_ref20){var _ref21=_slicedToArray(_ref20,2),url=_ref21[0],options=_ref21[1];return matcher(normalizeUrl$2(url),options);});};var formatDebug=function formatDebug(func){return function(){setDebugPhase$2('inspect');for(var _len6=arguments.length,args=new Array(_len6),_key7=0;_key7<_len6;_key7++){args[_key7]=arguments[_key7];}var result=func.call.apply(func,[this].concat(args));setDebugPhase$2();return result;};};FetchMock$2.filterCalls=function(nameOrMatcher,options){debug$3('Filtering fetch calls');var calls=this._calls;var matcher='*';if([true,'matched'].includes(nameOrMatcher)){debug$3("Filter provided is ".concat(nameOrMatcher,". Returning matched calls only"));calls=calls.filter(function(_ref22){var isUnmatched=_ref22.isUnmatched;return !isUnmatched;});}else if([false,'unmatched'].includes(nameOrMatcher)){debug$3("Filter provided is ".concat(nameOrMatcher,". Returning unmatched calls only"));calls=calls.filter(function(_ref23){var isUnmatched=_ref23.isUnmatched;return isUnmatched;});}else if(typeof nameOrMatcher==='undefined'){debug$3("Filter provided is undefined. Returning all calls");calls=calls;}else if(isName(nameOrMatcher)){debug$3("Filter provided, looks like the name of a named route. Returning only calls handled by that route");calls=calls.filter(function(_ref24){var identifier=_ref24.identifier;return identifier===nameOrMatcher;});}else {matcher=normalizeUrl$2(nameOrMatcher);if(this.routes.some(function(_ref25){var identifier=_ref25.identifier;return identifier===matcher;})){debug$3("Filter provided, ".concat(nameOrMatcher,", identifies a route. Returning only calls handled by that route"));calls=calls.filter(function(call){return call.identifier===matcher;});}}if((options||matcher!=='*')&&calls.length){if(typeof options==='string'){options={method:options};}debug$3('Compiling filter and options to route in order to filter all calls',nameOrMatcher);calls=filterCallsWithMatcher.call(this,matcher,options,calls);}debug$3("Retrieved ".concat(calls.length," calls"));return calls;};FetchMock$2.calls=formatDebug(function(nameOrMatcher,options){debug$3('retrieving matching calls');return this.filterCalls(nameOrMatcher,options);});FetchMock$2.lastCall=formatDebug(function(nameOrMatcher,options){debug$3('retrieving last matching call');return _toConsumableArray(this.filterCalls(nameOrMatcher,options)).pop();});FetchMock$2.lastUrl=formatDebug(function(nameOrMatcher,options){debug$3('retrieving url of last matching call');return (this.lastCall(nameOrMatcher,options)||[])[0];});FetchMock$2.lastOptions=formatDebug(function(nameOrMatcher,options){debug$3('retrieving options of last matching call');return (this.lastCall(nameOrMatcher,options)||[])[1];});FetchMock$2.called=formatDebug(function(nameOrMatcher,options){debug$3('checking if matching call was made');return !!this.filterCalls(nameOrMatcher,options).length;});FetchMock$2.flush=formatDebug(/*#__PURE__*/function(){var _ref26=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(waitForResponseMethods){var queuedPromises;return _regeneratorRuntime.wrap(function _callee5$(_context5){while(1)switch(_context5.prev=_context5.next){case 0:setDebugNamespace$1('flush');debug$3("flushing all fetch calls. ".concat(waitForResponseMethods?'':'Not ',"waiting for response bodies to complete download"));queuedPromises=this._holdingPromises;this._holdingPromises=[];debug$3("".concat(queuedPromises.length," fetch calls to be awaited"));_context5.next=7;return Promise.all(queuedPromises);case 7:debug$3("All fetch calls have completed");if(!(waitForResponseMethods&&this._holdingPromises.length)){_context5.next=13;break;}debug$3("Awaiting all fetch bodies to download");_context5.next=12;return this.flush(waitForResponseMethods);case 12:debug$3("All fetch bodies have completed downloading");case 13:setDebugNamespace$1();case 14:case"end":return _context5.stop();}},_callee5,this);}));return function(_x16){return _ref26.apply(this,arguments);};}());FetchMock$2.done=formatDebug(function(nameOrMatcher){var _this7=this;setDebugPhase$2('inspect');setDebugNamespace$1('done');debug$3('Checking to see if expected calls have been made');var routesToCheck;if(nameOrMatcher&&typeof nameOrMatcher!=='boolean'){debug$3('Checking to see if expected calls have been made for single route:',nameOrMatcher);routesToCheck=[{identifier:nameOrMatcher}];}else {debug$3('Checking to see if expected calls have been made for all routes');routesToCheck=this.routes;}// Can't use array.every because would exit after first failure, which would + // break the logging + var result=routesToCheck.map(function(_ref27){var identifier=_ref27.identifier;if(!_this7.called(identifier)){debug$3('No calls made for route:',identifier);console.warn("Warning: ".concat(identifier," not called"));// eslint-disable-line + return false;}var expectedTimes=(_this7.routes.find(function(r){return r.identifier===identifier;})||{}).repeat;if(!expectedTimes){debug$3('Route has been called at least once, and no expectation of more set:',identifier);return true;}var actualTimes=_this7.filterCalls(identifier).length;debug$3("Route called ".concat(actualTimes," times:"),identifier);if(expectedTimes>actualTimes){debug$3("Route called ".concat(actualTimes," times, but expected ").concat(expectedTimes,":"),identifier);console.warn("Warning: ".concat(identifier," only called ").concat(actualTimes," times, but ").concat(expectedTimes," expected"));// eslint-disable-line + return false;}else {return true;}}).every(function(isDone){return isDone;});setDebugNamespace$1();setDebugPhase$2();return result;});var inspecting=FetchMock$2;var debug$4=debug_1.debug;var FetchMock$3=Object.assign({},fetchHandler,setUpAndTearDown,inspecting);FetchMock$3.config={fallbackToNetwork:false,includeContentLength:true,sendAsJson:true,warnOnFallback:true,overwriteRoutes:undefined};FetchMock$3.createInstance=function(){debug$4('Creating fetch-mock instance');var instance=Object.create(FetchMock$3);instance._uncompiledRoutes=(this._uncompiledRoutes||[]).slice();instance.routes=instance._uncompiledRoutes.map(function(config){return instance.compileRoute(config);});instance.fallbackResponse=this.fallbackResponse||undefined;instance.config=Object.assign({},this.config||FetchMock$3.config);instance._calls=[];instance._holdingPromises=[];instance.bindMethods();return instance;};FetchMock$3.bindMethods=function(){this.fetchHandler=FetchMock$3.fetchHandler.bind(this);this.reset=this.restore=FetchMock$3.reset.bind(this);this.resetHistory=FetchMock$3.resetHistory.bind(this);this.resetBehavior=FetchMock$3.resetBehavior.bind(this);};FetchMock$3.sandbox=function(){debug$4('Creating sandboxed fetch-mock instance');// this construct allows us to create a fetch-mock instance which is also + // a callable function, while circumventing circularity when defining the + // object that this function should be bound to + var proxy=function proxy(url,options){return sandbox.fetchHandler(url,options);};var sandbox=Object.assign(proxy,// Ensures that the entire returned object is a callable function + FetchMock$3,// prototype methods + this.createInstance()// instance data + );sandbox.bindMethods();sandbox.isSandbox=true;return sandbox;};FetchMock$3.getOption=function(name){var route=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return name in route?route[name]:this.config[name];};var lib=FetchMock$3;var statusTextMap={'100':'Continue','101':'Switching Protocols','102':'Processing','200':'OK','201':'Created','202':'Accepted','203':'Non-Authoritative Information','204':'No Content','205':'Reset Content','206':'Partial Content','207':'Multi-Status','208':'Already Reported','226':'IM Used','300':'Multiple Choices','301':'Moved Permanently','302':'Found','303':'See Other','304':'Not Modified','305':'Use Proxy','307':'Temporary Redirect','308':'Permanent Redirect','400':'Bad Request','401':'Unauthorized','402':'Payment Required','403':'Forbidden','404':'Not Found','405':'Method Not Allowed','406':'Not Acceptable','407':'Proxy Authentication Required','408':'Request Timeout','409':'Conflict','410':'Gone','411':'Length Required','412':'Precondition Failed','413':'Payload Too Large','414':'URI Too Long','415':'Unsupported Media Type','416':'Range Not Satisfiable','417':'Expectation Failed','418':"I'm a teapot",'421':'Misdirected Request','422':'Unprocessable Entity','423':'Locked','424':'Failed Dependency','425':'Unordered Collection','426':'Upgrade Required','428':'Precondition Required','429':'Too Many Requests','431':'Request Header Fields Too Large','451':'Unavailable For Legal Reasons','500':'Internal Server Error','501':'Not Implemented','502':'Bad Gateway','503':'Service Unavailable','504':'Gateway Timeout','505':'HTTP Version Not Supported','506':'Variant Also Negotiates','507':'Insufficient Storage','508':'Loop Detected','509':'Bandwidth Limit Exceeded','510':'Not Extended','511':'Network Authentication Required'};var statusText=statusTextMap;var theGlobal=typeof window!=='undefined'?window:self;var setUrlImplementation=requestUtils.setUrlImplementation;setUrlImplementation(theGlobal.URL);lib.global=theGlobal;lib.statusTextMap=statusText;lib.config=Object.assign(lib.config,{Promise:theGlobal.Promise,Request:theGlobal.Request,Response:theGlobal.Response,Headers:theGlobal.Headers});var client=lib.createInstance();function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r-1){lowercaseLetterExists=true;}});Should(lowercaseLetterExists).not.be.ok();done();});it('ends existing session with an event that includes SessionLength',function(done){mParticle.startNewSession();mParticle.endSession();var sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');sessionEndEvent.should.be.ok();sessionEndEvent.data.should.have.property('session_duration_ms');done();});it('creates a new dateLastEventSent when logging an event, and retains the previous one when ending session',function(done){mParticle.logEvent('Test Event1');var testEvent1=findEventFromRequest$7(client._calls,'Test Event1');setTimeout(function(){mParticle.logEvent('Test Event2');var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');mParticle.endSession();var sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');var result1=testEvent1.data.timestamp_unixtime_ms===testEvent2.data.timestamp_unixtime_ms;var result2=testEvent2.data.timestamp_unixtime_ms===sessionEndEvent.data.timestamp_unixtime_ms;Should(result1).not.be.ok();Should(result2).be.ok();done();},5);});it('should process ready queue when initialized',function(done){var readyFuncCalled=false;mParticle._resetForTests(MPConfig);mParticle.ready(function(){readyFuncCalled=true;});mParticle.init(apiKey,window.mParticle.config);Should(readyFuncCalled).equal(true);done();});it('should set app version',function(done){mParticle.setAppVersion('1.0');window.mParticle.logEvent('Test Event',mParticle.EventType.Navigation);var testEventBatch=findBatch$6(client._calls,'Test Event');testEventBatch.application_info.should.have.property('application_version','1.0');done();});it('should get app version',function(done){mParticle.setAppVersion('2.0');var appVersion=mParticle.getAppVersion();appVersion.should.equal('2.0');done();});it('should get environment setting when set to `production`',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,_objectSpread(_objectSpread({},window.mParticle.config),{},{isDevelopmentMode:false}));mParticle.getEnvironment().should.equal('production');done();});it('should get environment setting when set to `development`',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,_objectSpread(_objectSpread({},window.mParticle.config),{},{isDevelopmentMode:true}));mParticle.getEnvironment().should.equal('development');done();});it('should get app version from config',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.appName="testAppName";mParticle.init(apiKey,window.mParticle.config);var appName=mParticle.getAppName();appName.should.equal('testAppName');done();});it('should send new appName via event payload',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.appName='newAppName';mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.application_info.should.have.property('application_name','newAppName');done();});it('should allow app name to be changed via setAppName',function(done){mParticle._resetForTests(MPConfig);var newConfig=_objectSpread(_objectSpread({},window.mParticle.config),{},{appName:'OverrideTestName'});mParticle.init(apiKey,newConfig);var appName=mParticle.getAppName();appName.should.equal('OverrideTestName');done();});it('should set Package Name on Batch Payload',function(done){mParticle.config["package"]='my-web-package';mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.should.have.property('application_info');batch.application_info.should.have.property('package','my-web-package');done();});it('should sanitize event attributes',function(done){mParticle.logEvent('sanitized event',1,{key1:'value1',mydate:new Date(),ishouldberemoved:{test:'test'},ishouldalsoberemoved:['test'],removeme:new Error()});var sanitizedEvent=findEventFromRequest$7(client._calls,'sanitized event');sanitizedEvent.data.custom_attributes.should.have.property('key1','value1');sanitizedEvent.data.custom_attributes.should.have.property('mydate');sanitizedEvent.data.custom_attributes.should.not.have.property('ishouldberemoved');sanitizedEvent.data.custom_attributes.should.not.have.property('ishouldalsoberemoved');sanitizedEvent.data.custom_attributes.should.not.have.property('removeme');done();});it('sanitizes attributes when attrs are provided',function(done){var attrs={valid:'123',invalid:['123','345']};var product=mParticle.eCommerce.createProduct('name','sku',100,1,'variant','category','brand','position','coupon',attrs);product.Attributes.should.not.have.property('invalid');product.Attributes.should.have.property('valid');mParticle.eCommerce.logCheckout(1,'visa',attrs);var checkoutEvent=findEventFromRequest$7(client._calls,'checkout');checkoutEvent.data.custom_attributes.should.not.have.property('invalid');checkoutEvent.data.custom_attributes.should.have.property('valid');mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart,product,attrs);var addToCartEvent=findEventFromRequest$7(client._calls,'add_to_cart');addToCartEvent.data.custom_attributes.should.not.have.property('invalid');addToCartEvent.data.custom_attributes.should.have.property('valid');var transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mockServer$d.requests=[];mParticle.eCommerce.logPurchase(transactionAttributes,product,false,attrs);var purchaseEvent=findEventFromRequest$7(client._calls,'purchase');purchaseEvent.data.custom_attributes.should.not.have.property('invalid');purchaseEvent.data.custom_attributes.should.have.property('valid');var promotion=mParticle.eCommerce.createPromotion('id','creative','name','position');mockServer$d.requests=[];mParticle.eCommerce.logPromotion(1,promotion,attrs);var promotionViewEvent=findEventFromRequest$7(client._calls,'view');promotionViewEvent.data.custom_attributes.should.not.have.property('invalid');promotionViewEvent.data.custom_attributes.should.have.property('valid');mockServer$d.requests=[];mParticle.eCommerce.logRefund(transactionAttributes,product,false,attrs);var refundEvent=findEventFromRequest$7(client._calls,'refund');refundEvent.data.custom_attributes.should.not.have.property('invalid');refundEvent.data.custom_attributes.should.have.property('valid');done();});it('should not generate a new device ID if a deviceId exists in localStorage',function(done){mParticle._resetForTests(MPConfig);setLocalStorage$4();mParticle.init(apiKey,window.mParticle.config);var deviceId=mParticle.getDeviceId();deviceId.should.equal(das);done();});it('should return the deviceId when requested',function(done){var deviceId=mParticle.getDeviceId();Should(deviceId).be.ok();deviceId.length.should.equal(36);done();});it('will create a cgid when no previous cgid exists after initializing storage, and no sid',function(done){mParticle._resetForTests(MPConfig);mParticle.getInstance()._Store.storageName=TestsCore.workspaceCookieName;mParticle.getInstance()._Persistence.initializeStorage();mParticle.getInstance()._Persistence.update();var cookieData=mParticle.getInstance()._Persistence.getLocalStorage();cookieData.gs.should.have.properties(['cgid']);cookieData.gs.should.not.have.property('sid');done();});it('creates a new session when elapsed time between actions is greater than session timeout',function(done){mParticle._resetForTests(MPConfig);var clock=sinon$2.useFakeTimers();mParticle.config.sessionTimeout=1;mParticle.init(apiKey,window.mParticle.config);clock.tick(100);mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');clock.tick(70000);mParticle.logEvent('Test Event2');var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');testEvent.data.session_uuid.should.not.equal(testEvent2.data.session_uuid);mParticle.getInstance()._SessionManager.clearSessionTimeout();clock.restore();done();});it('should end session when last event sent is outside of sessionTimeout',function(done){mParticle._resetForTests(MPConfig);var clock=sinon$2.useFakeTimers();mParticle.config.sessionTimeout=1;mParticle.init(apiKey,window.mParticle.config);clock.tick(100);mParticle.logEvent('Test Event');clock.tick(10000);mParticle.logEvent('Test Event2');clock.tick(120000);mParticle.logEvent('Test Event3');clock.tick(150000);var testEvent=findEventFromRequest$7(client._calls,'Test Event');var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');var testEvent3=findEventFromRequest$7(client._calls,'Test Event3');testEvent2.data.session_uuid.should.equal(testEvent.data.session_uuid);testEvent3.data.session_uuid.should.not.equal(testEvent.data.session_uuid);clock.restore();done();});it('should not end session when end session is called within sessionTimeout timeframe',function(done){// This test mimics if another tab is open and events are sent, but previous tab's sessionTimeout is still ongoing + mParticle._resetForTests(MPConfig);var clock=sinon$2.useFakeTimers();mParticle.config.sessionTimeout=1;mParticle.init(apiKey,window.mParticle.config);mockServer$d.requests=[];clock.tick(100);mParticle.logEvent('Test Event');// This clock tick initiates a session end event that is successful + clock.tick(70000);var sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');Should(sessionEndEvent).be.ok();client._calls=[];clock.tick(100);mParticle.logEvent('Test Event2');var sid=mParticle.getInstance()._Persistence.getLocalStorage().gs.sid;var new_Persistence={gs:{sid:sid,ie:1,les:120000}};setLocalStorage$4(workspaceCookieName,new_Persistence);// // This clock tick initiates a session end event that is not successful + clock.tick(70000);sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');Should(sessionEndEvent).not.be.ok();var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');mParticle.logEvent('Test Event3');var testEvent3=findEventFromRequest$7(client._calls,'Test Event3');testEvent3.data.session_uuid.should.equal(testEvent2.data.session_uuid);clock.restore();done();});it('should get sessionId',function(done){mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');var sessionId=mParticle.getInstance()._SessionManager.getSession();testEvent.data.session_uuid.should.equal(sessionId);done();});it('should set session start date in dto',function(done){mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');testEvent.data.session_start_unixtime_ms.should.be.above(0);done();});it('should update session start date when manually ending session then starting a new one',function(done){mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');var testEventSessionStartTime=testEvent.data.session_start_unixtime_ms;mParticle.endSession();var sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');var sessionEndEventSessionStartDate=sessionEndEvent.data.session_start_unixtime_ms;sessionEndEventSessionStartDate.should.equal(testEventSessionStartTime);mParticle.logEvent('Test Event2');var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');var testEvent2SessionStartDate=testEvent2.data.session_start_unixtime_ms;testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate);done();});it('should update session start date when session times out,then starting a new one',function(done){mParticle._resetForTests(MPConfig);mParticle.config.sessionTimeout=1;var clock=sinon$2.useFakeTimers();mParticle.init(apiKey,mParticle.config);clock.tick(10);mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');var testEventSessionStartDate=testEvent.data.session_start_unixtime_ms;// trigger session timeout which ends session automatically + clock.tick(60000);// note to self - session end event not being triggered, could be the same bug + var sessionEndEvent=findEventFromRequest$7(client._calls,'session_end');var sessionEndEventSessionStartDate=sessionEndEvent.data.session_start_unixtime_ms;sessionEndEventSessionStartDate.should.equal(testEventSessionStartDate);clock.tick(100);mParticle.logEvent('Test Event2');var testEvent2=findEventFromRequest$7(client._calls,'Test Event2');var testEvent2SessionStartDate=testEvent2.data.session_start_unixtime_ms;testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate);clock.restore();done();});it('should load SDK with the included api on init and not send events to previous apikey in persistence',function(done){mParticle.logEvent('Test Event1');var testEvent1URL=findRequest(client._calls,'Test Event1')[0];testEvent1URL.should.equal(urls.events);client.post('https://jssdks.mparticle.com/v3/JS/new-api-key/events',200);mParticle.init('new-api-key',window.mParticle.config);mParticle.logEvent('Test Event2');var testEvent2URL=findRequestURL(client._calls,'Test Event2');testEvent2URL.should.equal('https://jssdks.mparticle.com/v3/JS/new-api-key/events');done();});it('should have default options as well as configured options on configuration object, overwriting when appropriate',function(done){var defaults=new Store({},mParticle.getInstance());// all items here should be the default values + for(var key in DefaultConfig){defaults.SDKConfig.should.have.property(key,DefaultConfig[key]);}var config={useCookieStorage:true,logLevel:'abc',useNativeSdk:true,isIOS:true,maxProducts:10,maxCookieSize:2000,appName:'testApp',integrationDelayTimeout:100,identifyRequest:{userIdentities:{customerid:'test'}},identityCallback:function identityCallback(){return 'identityCallback';},appVersion:'v2.0.0',sessionTimeout:3000,forceHttps:false,customFlags:{flag1:'attr1'},workspaceToken:'abcdef',requiredWebviewBridgeName:'exampleWebviewBridgeName',minWebviewBridgeVersion:2,aliasMaxWindow:3};var mp=new Store(config,mParticle.getInstance());mp.isEnabled.should.equal(true);Object.keys(mp.sessionAttributes).length.should.equal(0);Object.keys(mp.serverSettings).length.should.equal(0);Object.keys(mp.nonCurrentUserMPIDs).length.should.equal(0);Object.keys(mp.integrationAttributes).length.should.equal(0);Object.keys(mp.cookieSyncDates).length.should.equal(0);mp.currentSessionMPIDs.length.should.equal(0);mp.isTracking.should.equal(false);mp.cartProducts.length.should.equal(0);mp.eventQueue.length.should.equal(0);mp.identityCallInFlight.should.equal(false);mp.identifyCalled.should.equal(false);mp.isLoggedIn.should.equal(false);mp.requireDelay.should.equal(true);mp.activeForwarders.length.should.equal(0);(mp.consentState===null).should.equal(true);(mp.context===null).should.equal(true);(mp.sessionId===null).should.equal(true);(mp.isFirstRun===null).should.equal(true);(mp.clientId===null).should.equal(true);(mp.deviceId===null).should.equal(true);(mp.devToken===null).should.equal(true);(mp.dateLastEventSent===null).should.equal(true);(mp.sessionStartDate===null).should.equal(true);(mp.currentPosition===null).should.equal(true);(mp.watchPositionId===null).should.equal(true);(mp.currencyCode===null).should.equal(true);(mp.globalTimer===null).should.equal(true);(mp.isLocalStorageAvailable===null).should.equal(true);// all items here should be the overwritten values + mp.SDKConfig.useCookieStorage.should.equal(config.useCookieStorage);mp.SDKConfig.useNativeSdk.should.equal(config.useNativeSdk);mp.SDKConfig.isIOS.should.equal(config.isIOS);mp.SDKConfig.maxProducts.should.equal(config.maxProducts);mp.SDKConfig.maxCookieSize.should.equal(config.maxCookieSize);mp.SDKConfig.appName.should.equal(config.appName);mp.SDKConfig.integrationDelayTimeout.should.equal(config.integrationDelayTimeout);JSON.stringify(mp.SDKConfig.identifyRequest).should.equal(JSON.stringify(config.identifyRequest));mp.SDKConfig.identityCallback().should.equal(config.identityCallback());mp.SDKConfig.appVersion.should.equal(config.appVersion);mp.SDKConfig.sessionTimeout.should.equal(3000);mp.SDKConfig.forceHttps.should.equal(config.forceHttps);mp.SDKConfig.customFlags.should.equal(config.customFlags);mp.SDKConfig.workspaceToken.should.equal(config.workspaceToken);mp.SDKConfig.requiredWebviewBridgeName.should.equal(config.requiredWebviewBridgeName);mp.SDKConfig.minWebviewBridgeVersion.should.equal(config.minWebviewBridgeVersion);mp.SDKConfig.aliasMaxWindow.should.equal(config.aliasMaxWindow);mParticle._resetForTests(MPConfig);done();});it('should use custom loggers when provided',function(done){mParticle.config.logLevel='verbose';var errorMessage;var warnMessage;var infoMessage;mParticle.config.logger={error:function error(msg){errorMessage=msg;},warning:function warning(msg){warnMessage=msg;},verbose:function verbose(msg){infoMessage=msg;}};mParticle.init(apiKey,window.mParticle.config);infoMessage.should.equal('Batch count: 1');mParticle.eCommerce.createProduct();errorMessage.should.equal('Name is required when creating a product');mParticle.startTrackingLocation();warnMessage.should.equal('Warning: Location tracking is triggered, but not including a callback into the `startTrackingLocation` may result in events logged too quickly and not being associated with a location.');done();});it('should be able to change logLevel on the fly, postuse custom loggers when provided',function(done){var infoMessages=[];mParticle.config.logger={verbose:function verbose(msg){infoMessages.push(msg);}};mParticle.init(apiKey,window.mParticle.config);infoMessages.length.should.equal(0);mParticle.setLogLevel('verbose');mParticle.logEvent('hi');infoMessages[0].should.equal('Starting to log event: hi');done();});it("should not log anything to console when logLevel = 'none'",function(done){var infoMessages=[];var warnMessages=[];var errorMessages=[];mParticle.config.logger={error:function error(msg){errorMessages.push(msg);},warning:function warning(msg){warnMessages.push(msg);},verbose:function verbose(msg){infoMessages.push(msg);}};mParticle.init(apiKey,window.mParticle.config);infoMessages.length.should.equal(0);warnMessages.length.should.equal(0);errorMessages.length.should.equal(0);mParticle.setLogLevel('none');mParticle.logEvent('Test Event');infoMessages.length.should.equal(0);warnMessages.length.should.equal(0);errorMessages.length.should.equal(0);var testEvent=findEventFromRequest$7(client._calls,'Test Event');Should(testEvent).be.ok();done();});it('should not error when logger custom loggers when provided',function(done){/* Previously the Store was initialized before Logger, and since Store contains Logger, and it would throw. + This no longer throws because Store takes the Logger as an argument, which is now initialized first. + */mParticle.config.logLevel='verbose';delete mParticle.config.workspaceToken;// no workspace token would previously make the Store fail to Log this fact + var warnMessage;mParticle.config.logger={warning:function warning(msg){warnMessage=msg;}};mParticle.init(apiKey,window.mParticle.config);warnMessage.should.equal('You should have a workspaceToken on your config object for security purposes.');done();});it('should use default urls if no custom urls are set in config object',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.SDKConfig.v1SecureServiceUrl.should.equal(Constants.DefaultUrls.v1SecureServiceUrl);mParticle.getInstance()._Store.SDKConfig.v2SecureServiceUrl.should.equal(Constants.DefaultUrls.v2SecureServiceUrl);mParticle.getInstance()._Store.SDKConfig.v3SecureServiceUrl.should.equal(Constants.DefaultUrls.v3SecureServiceUrl);mParticle.getInstance()._Store.SDKConfig.configUrl.should.equal(Constants.DefaultUrls.configUrl);mParticle.getInstance()._Store.SDKConfig.identityUrl.should.equal(Constants.DefaultUrls.identityUrl);mParticle.getInstance()._Store.SDKConfig.aliasUrl.should.equal(Constants.DefaultUrls.aliasUrl);done();});it('should have default urls if no custom urls are set in config object, but use custom urls when they are set',function(done){window.mParticle.config.v3SecureServiceUrl='testtesttest-custom-v3secureserviceurl/v3/JS/';window.mParticle.config.configUrl='foo-custom-configUrl/v2/JS/';window.mParticle.config.identityUrl='custom-identityUrl/';window.mParticle.config.aliasUrl='custom-aliasUrl/';mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.SDKConfig.v3SecureServiceUrl.should.equal(window.mParticle.config.v3SecureServiceUrl);mParticle.getInstance()._Store.SDKConfig.configUrl.should.equal(window.mParticle.config.configUrl);mParticle.getInstance()._Store.SDKConfig.identityUrl.should.equal(window.mParticle.config.identityUrl);mParticle.getInstance()._Store.SDKConfig.aliasUrl.should.equal(window.mParticle.config.aliasUrl);// test events endpoint + mParticle.logEvent('Test Event');var testEventURL=findRequestURL(client._calls,'Test Event');testEventURL.should.equal('https://'+window.mParticle.config.v3SecureServiceUrl+'test_key/events');// test Identity endpoint + mockServer$d.requests=[];mParticle.Identity.login({userIdentities:{customerid:'test1'}});mockServer$d.requests[0].url.should.equal('https://'+window.mParticle.config.identityUrl+'login');// test alias endpoint + mockServer$d.requests=[];mParticle.Identity.aliasUsers({destinationMpid:1,sourceMpid:2,startTime:3,endTime:4});mockServer$d.requests[0].url.should.equal('https://'+window.mParticle.config.aliasUrl+'test_key/Alias');done();});it('should use configUrl when specified on config object',function(done){mParticle.config.configUrl='testConfigUrl/';mParticle.config.requestConfig=true;mockServer$d.requests=[];mParticle.init(apiKey,window.mParticle.config);mockServer$d.requests[0].url.should.equal('https://testConfigUrl/test_key/config?env=0');done();});it('should use custom v3 endpoint when specified on config object',function(done){mParticle.config.v3SecureServiceUrl='def-v3SecureServiceUrl/v3/JS/';mParticle.config.flags={eventBatchingIntervalMillis:0};client.post('https://def-v3SecureServiceUrl/v3/JS/test_key/events',200);mParticle.init(apiKey,mParticle.config);mockServer$d.requests=[];mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');client.lastOptions().body.should.be.ok();done();});it('should add onCreateBatch to _Store.SDKConfig if onCreateBatch is provide on mParticle.config object',function(done){window.mParticle._resetForTests();mParticle.config.onCreateBatch=function(batch){return batch;};mParticle.init(apiKey,mParticle.config);_typeof(mParticle.getInstance()._Store.SDKConfig.onCreateBatch).should.equal('function');done();});it('should not add onCreateBatch to _Store.SDKConfig if it is not a function',function(done){window.mParticle._resetForTests();mParticle.config.onCreateBatch='not a function';mParticle.init(apiKey,mParticle.config);_typeof(mParticle.getInstance()._Store.SDKConfig.onCreateBatch).should.equal('undefined');done();});it('should hit url with query parameter of env=1 for debug mode for forwarders',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=true;mParticle.config.requestConfig=true;mockServer$d.requests=[];mParticle.init(apiKey,window.mParticle.config);(mockServer$d.requests[0].url.indexOf('?env=1')>0).should.equal(true);mockServer$d.requests=[];mParticle.config.requestConfig=true;mParticle.config.isDevelopmentMode=false;mParticle.init(apiKey,window.mParticle.config);(mockServer$d.requests[0].url.indexOf('?env=0')>0).should.equal(true);done();});// TODO - there are no actual tests here....what's going on? + it('should fetch from /config and keep everything properly on the store',function(done){mParticle._resetForTests(MPConfig);var config={appName:'appNameTest',minWebviewBridgeVersion:1,workspaceToken:'token1'};mockServer$d.respondWith(urls.config,[200,{},JSON.stringify(config)]);window.mParticle.config.requestConfig=true;mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.SDKConfig.appName=config.appName;mParticle.getInstance()._Store.SDKConfig.minWebviewBridgeVersion=config.minWebviewBridgeVersion;mParticle.getInstance()._Store.SDKConfig.workspaceToken=config.workspaceToken;localStorage.removeItem(config.workspaceToken);done();});it('should initialize and log events even with a failed /config fetch and empty config',function(done){// this instance occurs when self hosting and the user only passes an object into init + mParticle._resetForTests(MPConfig);mockServer$d.respondWith(urls.identify,[400,{},JSON.stringify('')]);// force config to be only requestConfig = true; + delete window.mParticle.config.kitConfigs;delete window.mParticle.config.isDevelopmentMode;delete window.mParticle.config.logLevel;delete window.mParticle.config.workspaceToken;delete window.mParticle.config.requestConfig;mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.isInitialized.should.equal(true);// have to manually call identify although it was called as part of init because we can only mock the server response once + mockServer$d.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'MPID1'})]);mParticle.Identity.identify({userIdentities:{customerid:'test'}});mParticle.logEvent('Test Event');var testEvent=findEventFromRequest$7(client._calls,'Test Event');testEvent.should.be.ok();done();});it('should initialize without a config object passed to init',function(done){// this instance occurs when self hosting and the user only passes an object into init + mParticle._resetForTests(MPConfig);mParticle.init(apiKey);mParticle.getInstance()._Store.isInitialized.should.equal(true);done();});it('should generate hash both on the mparticle instance and the mparticle instance manager',function(done){var hashValue=-1146196832;var hash1=mParticle.generateHash('TestHash');var hash2=mParticle.getInstance().generateHash('TestHash');hash1.should.equal(hashValue);hash2.should.equal(hashValue);done();});it('should remove localstorage when calling reset',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.workspaceToken='defghi';mParticle.init(apiKey,window.mParticle.config);var ls=localStorage.getItem('mprtcl-v4_defghi');ls.should.be.ok();mParticle.reset();ls=localStorage.getItem('mprtcl-v4_defghi');(ls===null).should.equal(true);done();});it('should remove cookies when calling reset',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.useCookieStorage=true;window.mParticle.config.workspaceToken='defghi';mParticle.init(apiKey,window.mParticle.config);var cookie=document.cookie;cookie.includes('mprtcl-v4_defghi').should.equal(true);mParticle.reset();cookie=document.cookie;cookie.includes('mprtcl-v4_defghi').should.equal(false);window.mParticle.config.useCookieStorage=false;done();});it('should queue setCurrencyCode successfully when SDK is not yet initialized, and then later initialized',function(done){mParticle._resetForTests(MPConfig);// mock a non-initialized state + mParticle.getInstance()._Store.isInitialized=false;// when SDK is not yet initialized, this will add to the ready queue + mParticle.eCommerce.setCurrencyCode('USD');// initializing SDK will flush the ready queue and setCurrencyCode should not throw an error + mParticle.init(apiKey,window.mParticle.config);done();});it('should set a device id when calling setDeviceId',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);// this das should be the SDK auto generated one, which is 36 characters long + mParticle.getDeviceId().length.should.equal(36);mParticle.setDeviceId('foo-guid');mParticle.getDeviceId().should.equal('foo-guid');done();});it('should set a device id when set on mParticle.config',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.deviceId='foo-guid';mParticle.init(apiKey,window.mParticle.config);mParticle.getDeviceId().should.equal('foo-guid');done();});it('should not set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called if init not called',function(done){mParticle._resetForTests(MPConfig);mParticle._setWrapperSDKInfo('flutter','1.0.3');mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none');(mParticle.getInstance()._Store.wrapperSDKInfo.version===null).should.equal(true);mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(false);done();});it('should have the correct wrapper sdk info default values when init is called',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none');(mParticle.getInstance()._Store.wrapperSDKInfo.version===null).should.equal(true);mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(false);done();});it('should set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called after init is called',function(done){mParticle._resetForTests(MPConfig);mParticle._setWrapperSDKInfo('flutter','1.0.3');mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('flutter');mParticle.getInstance()._Store.wrapperSDKInfo.version.should.equal('1.0.3');mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(true);done();});it('should not set the wrapper sdk info in Store after it has previously been set',function(done){mParticle._resetForTests(MPConfig);mParticle._setWrapperSDKInfo('flutter','1.0.3');mParticle.init(apiKey,window.mParticle.config);mParticle._setWrapperSDKInfo('none','2.0.5');mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('flutter');mParticle.getInstance()._Store.wrapperSDKInfo.version.should.equal('1.0.3');mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(true);done();});});/****************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */var _extendStatics=function extendStatics(d,b){_extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b;}||function(d,b){for(var p in b)if(Object.prototype.hasOwnProperty.call(b,p))d[p]=b[p];};return _extendStatics(d,b);};function __extends(d,b){if(typeof b!=="function"&&b!==null)throw new TypeError("Class extends value "+String(b)+" is not a constructor or null");_extendStatics(d,b);function __(){this.constructor=d;}d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __());}var _assign=function __assign(){_assign=Object.assign||function __assign(t){for(var s,i=1,n=arguments.length;i0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue;}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]=0){return args[callArgAt];}var argumentList;if(callArgAt===useLeftMostCallback){argumentList=args;}if(callArgAt===useRightMostCallback){argumentList=reverse(slice(args));}var callArgProp=behavior.callArgProp;for(var i=0,l=argumentList.length;i0){msg+=" Received [".concat(join(args,", "),"]");}return msg;}return "argument at index ".concat(behavior.callArgAt," is not a function: ").concat(func);}function ensureArgs(name,behavior,args){// map function name to internal property + // callsArg => callArgAt + var property=name.replace(/sArg/,"ArgAt");var index=behavior[property];if(index>=args.length){throw new TypeError("".concat(name," failed: ").concat(index+1," arguments required but only ").concat(args.length," present"));}}function callCallback(behavior,args){if(typeof behavior.callArgAt==="number"){ensureArgs("callsArg",behavior,args);var func=getCallback(behavior,args);if(typeof func!=="function"){throw new TypeError(getCallbackError(behavior,func,args));}if(behavior.callbackAsync){nextTick(function(){func.apply(behavior.callbackContext,behavior.callbackArguments);});}else {return func.apply(behavior.callbackContext,behavior.callbackArguments);}}return undefined;}var proto={create:function create(stub){var behavior=extend({},proto);delete behavior.create;delete behavior.addBehavior;delete behavior.createBehavior;behavior.stub=stub;if(stub.defaultBehavior&&stub.defaultBehavior.promiseLibrary){behavior.promiseLibrary=stub.defaultBehavior.promiseLibrary;}return behavior;},isPresent:function isPresent(){return typeof this.callArgAt==="number"||this.exception||this.exceptionCreator||typeof this.returnArgAt==="number"||this.returnThis||typeof this.resolveArgAt==="number"||this.resolveThis||typeof this.throwArgAt==="number"||this.fakeFn||this.returnValueDefined;},/*eslint complexity: ["error", 20]*/invoke:function invoke(context,args){/* + * callCallback (conditionally) calls ensureArgs + * + * Note: callCallback intentionally happens before + * everything else and cannot be moved lower + */var returnValue=callCallback(this,args);if(this.exception){throw this.exception;}else if(this.exceptionCreator){this.exception=this.exceptionCreator();this.exceptionCreator=undefined;throw this.exception;}else if(typeof this.returnArgAt==="number"){ensureArgs("returnsArg",this,args);return args[this.returnArgAt];}else if(this.returnThis){return context;}else if(typeof this.throwArgAt==="number"){ensureArgs("throwsArg",this,args);throw args[this.throwArgAt];}else if(this.fakeFn){return this.fakeFn.apply(context,args);}else if(typeof this.resolveArgAt==="number"){ensureArgs("resolvesArg",this,args);return (this.promiseLibrary||Promise).resolve(args[this.resolveArgAt]);}else if(this.resolveThis){return (this.promiseLibrary||Promise).resolve(context);}else if(this.resolve){return (this.promiseLibrary||Promise).resolve(this.returnValue);}else if(this.reject){return (this.promiseLibrary||Promise).reject(this.returnValue);}else if(this.callsThrough){var wrappedMethod=this.effectiveWrappedMethod();return wrappedMethod.apply(context,args);}else if(this.callsThroughWithNew){// Get the original method (assumed to be a constructor in this case) + var WrappedClass=this.effectiveWrappedMethod();// Turn the arguments object into a normal array + var argsArray=slice(args);// Call the constructor + var F=WrappedClass.bind.apply(WrappedClass,concat([null],argsArray));return new F();}else if(typeof this.returnValue!=="undefined"){return this.returnValue;}else if(typeof this.callArgAt==="number"){return returnValue;}return this.returnValue;},effectiveWrappedMethod:function effectiveWrappedMethod(){for(var stubb=this.stub;stubb;stubb=stubb.parent){if(stubb.wrappedMethod){return stubb.wrappedMethod;}}throw new Error("Unable to find wrapped method");},onCall:function onCall(index){return this.stub.onCall(index);},onFirstCall:function onFirstCall(){return this.stub.onFirstCall();},onSecondCall:function onSecondCall(){return this.stub.onSecondCall();},onThirdCall:function onThirdCall(){return this.stub.onThirdCall();},withArgs:function withArgs(/* arguments */){throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" '+'is not supported. Use "stub.withArgs(...).onCall(...)" '+"to define sequential behavior for calls with certain arguments.");}};function createBehavior(behaviorMethod){return function(){this.defaultBehavior=this.defaultBehavior||proto.create(this);this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior,arguments);return this;};}function addBehavior(stub,name,fn){proto[name]=function(){fn.apply(this,concat([this],slice(arguments)));return this.stub||this;};stub[name]=createBehavior(name);}proto.addBehavior=addBehavior;proto.createBehavior=createBehavior;var asyncBehaviors=exportAsyncBehaviors(proto);module.exports=extend.nonEnum({},proto,asyncBehaviors);},{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/next-tick":34,"@sinonjs/commons":48}],5:[function(require,module,exports){var walk=require("./util/core/walk");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var push=require("@sinonjs/commons").prototypes.array.push;function collectMethod(methods,object,prop,propOwner){if(typeof getPropertyDescriptor(propOwner,prop).value==="function"&&hasOwnProperty(object,prop)){push(methods,object[prop]);}}// This function returns an array of all the own methods on the passed object + function collectOwnMethods(object){var methods=[];walk(object,collectMethod.bind(null,methods,object));return methods;}module.exports=collectOwnMethods;},{"./util/core/get-property-descriptor":29,"./util/core/walk":39,"@sinonjs/commons":48}],6:[function(require,module,exports){var supportsColor=require("supports-color");function colorize(str,color){if(supportsColor.stdout===false){return str;}return "\x1B[".concat(color,"m").concat(str,"\x1B[0m");}exports.red=function(str){return colorize(str,31);};exports.green=function(str){return colorize(str,32);};exports.cyan=function(str){return colorize(str,96);};exports.white=function(str){return colorize(str,39);};exports.bold=function(str){return colorize(str,1);};},{"supports-color":150}],7:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var Sandbox=require("./sandbox");var forEach=arrayProto.forEach;var push=arrayProto.push;function prepareSandboxFromConfig(config){var sandbox=new Sandbox();if(config.useFakeServer){if(_typeof$1(config.useFakeServer)==="object"){sandbox.serverPrototype=config.useFakeServer;}sandbox.useFakeServer();}if(config.useFakeTimers){if(_typeof$1(config.useFakeTimers)==="object"){sandbox.useFakeTimers(config.useFakeTimers);}else {sandbox.useFakeTimers();}}return sandbox;}function exposeValue(sandbox,config,key,value){if(!value){return;}if(config.injectInto&&!(key in config.injectInto)){config.injectInto[key]=value;push(sandbox.injectedKeys,key);}else {push(sandbox.args,value);}}function createSandbox(config){if(!config){return new Sandbox();}var configuredSandbox=prepareSandboxFromConfig(config);configuredSandbox.args=configuredSandbox.args||[];configuredSandbox.injectedKeys=[];configuredSandbox.injectInto=config.injectInto;var exposed=configuredSandbox.inject({});if(config.properties){forEach(config.properties,function(prop){var value=exposed[prop]||prop==="sandbox"&&configuredSandbox;exposeValue(configuredSandbox,config,prop,value);});}else {exposeValue(configuredSandbox,config,"sandbox");}return configuredSandbox;}module.exports=createSandbox;},{"./sandbox":19,"@sinonjs/commons":48}],8:[function(require,module,exports){var stub=require("./stub");var sinonType=require("./util/core/sinon-type");var forEach=require("@sinonjs/commons").prototypes.array.forEach;function isStub(value){return sinonType.get(value)==="stub";}module.exports=function createStubInstance(constructor,overrides){if(typeof constructor!=="function"){throw new TypeError("The constructor should be a function.");}var stubInstance=Object.create(constructor.prototype);sinonType.set(stubInstance,"stub-instance");var stubbedObject=stub(stubInstance);forEach(Object.keys(overrides||{}),function(propertyName){if(propertyName in stubbedObject){var value=overrides[propertyName];if(isStub(value)){stubbedObject[propertyName]=value;}else {stubbedObject[propertyName].returns(value);}}else {throw new Error("Cannot stub ".concat(propertyName,". Property does not exist!"));}});return stubbedObject;};},{"./stub":22,"./util/core/sinon-type":35,"@sinonjs/commons":48}],9:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var isPropertyConfigurable=require("./util/core/is-property-configurable");var exportAsyncBehaviors=require("./util/core/export-async-behaviors");var extend=require("./util/core/extend");var slice=arrayProto.slice;var useLeftMostCallback=-1;var useRightMostCallback=-2;function throwsException(fake,error,message){if(typeof error==="function"){fake.exceptionCreator=error;}else if(typeof error==="string"){fake.exceptionCreator=function(){var newException=new Error(message||"Sinon-provided ".concat(error));newException.name=error;return newException;};}else if(!error){fake.exceptionCreator=function(){return new Error("Error");};}else {fake.exception=error;}}var defaultBehaviors={callsFake:function callsFake(fake,fn){fake.fakeFn=fn;fake.exception=undefined;fake.exceptionCreator=undefined;},callsArg:function callsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOn:function callsArgOn(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=[];fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgWith:function callsArgWith(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;},callsArgOnWith:function callsArgWith(fake,index,context){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.callArgAt=index;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;},usingPromise:function usingPromise(fake,promiseLibrary){fake.promiseLibrary=promiseLibrary;},yields:function yields(fake){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsRight:function yieldsRight(fake){fake.callArgAt=useRightMostCallback;fake.callbackArguments=slice(arguments,1);fake.callbackContext=undefined;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsOn:function yieldsOn(fake,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=context;fake.callArgProp=undefined;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsTo:function yieldsTo(fake,prop){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,2);fake.callbackContext=undefined;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},yieldsToOn:function yieldsToOn(fake,prop,context){fake.callArgAt=useLeftMostCallback;fake.callbackArguments=slice(arguments,3);fake.callbackContext=context;fake.callArgProp=prop;fake.callbackAsync=false;fake.fakeFn=undefined;},"throws":throwsException,throwsException:throwsException,returns:function returns(fake,value){fake.returnValue=value;fake.resolve=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},returnsArg:function returnsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.returnArgAt=index;},throwsArg:function throwsArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.throwArgAt=index;},returnsThis:function returnsThis(fake){fake.returnThis=true;},resolves:function resolves(fake,value){fake.returnValue=value;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},resolvesArg:function resolvesArg(fake,index){if(typeof index!=="number"){throw new TypeError("argument index is not number");}fake.resolveArgAt=index;fake.returnValue=undefined;fake.resolve=true;fake.resolveThis=false;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},rejects:function rejects(fake,error,message){var reason;if(typeof error==="string"){reason=new Error(message||"");reason.name=error;}else if(!error){reason=new Error("Error");}else {reason=error;}fake.returnValue=reason;fake.resolve=false;fake.resolveThis=false;fake.reject=true;fake.returnValueDefined=true;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;return fake;},resolvesThis:function resolvesThis(fake){fake.returnValue=undefined;fake.resolve=false;fake.resolveThis=true;fake.reject=false;fake.returnValueDefined=false;fake.exception=undefined;fake.exceptionCreator=undefined;fake.fakeFn=undefined;},callThrough:function callThrough(fake){fake.callsThrough=true;},callThroughWithNew:function callThroughWithNew(fake){fake.callsThroughWithNew=true;},get:function get(fake,getterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{get:getterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},set:function set(fake,setterFunction){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,// eslint-disable-next-line accessor-pairs + {set:setterFunction,configurable:isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;},value:function value(fake,newVal){var rootStub=fake.stub||fake;Object.defineProperty(rootStub.rootObj,rootStub.propName,{value:newVal,enumerable:true,writable:true,configurable:rootStub.shadowsPropOnPrototype||isPropertyConfigurable(rootStub.rootObj,rootStub.propName)});return fake;}};var asyncBehaviors=exportAsyncBehaviors(defaultBehaviors);module.exports=extend({},defaultBehaviors,asyncBehaviors);},{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/is-property-configurable":32,"@sinonjs/commons":48}],10:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var createProxy=require("./proxy");var nextTick=require("./util/core/next-tick");var slice=arrayProto.slice;var promiseLib=Promise;module.exports=fake;/** + * Returns a `fake` that records all calls, arguments and return values. + * + * When an `f` argument is supplied, this implementation will be used. + * + * @example + * // create an empty fake + * var f1 = sinon.fake(); + * + * f1(); + * + * f1.calledOnce() + * // true + * + * @example + * function greet(greeting) { + * console.log(`Hello ${greeting}`); + * } + * + * // create a fake with implementation + * var f2 = sinon.fake(greet); + * + * // Hello world + * f2("world"); + * + * f2.calledWith("world"); + * // true + * + * @param {Function|undefined} f + * @returns {Function} + * @namespace + */function fake(f){if(arguments.length>0&&typeof f!=="function"){throw new TypeError("Expected f argument to be a Function");}return wrapFunc(f);}/** + * Creates a `fake` that returns the provided `value`, as well as recording all + * calls, arguments and return values. + * + * @example + * var f1 = sinon.fake.returns(42); + * + * f1(); + * // 42 + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.returns=function returns(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return value;}return wrapFunc(f);};/** + * Creates a `fake` that throws an Error. + * If the `value` argument does not have Error in its prototype chain, it will + * be used for creating a new error. + * + * @example + * var f1 = sinon.fake.throws("hello"); + * + * f1(); + * // Uncaught Error: hello + * + * @example + * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); + * + * f2(); + * // Uncaught TypeError: Invalid argument + * + * @memberof fake + * @param {*|Error} value + * @returns {Function} + */fake["throws"]=function _throws2(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){throw getError(value);}return wrapFunc(f);};/** + * Creates a `fake` that returns a promise that resolves to the passed `value` + * argument. + * + * @example + * var f1 = sinon.fake.resolves("apple pie"); + * + * await f1(); + * // "apple pie" + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.resolves=function resolves(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return promiseLib.resolve(value);}return wrapFunc(f);};/** + * Creates a `fake` that returns a promise that rejects to the passed `value` + * argument. When `value` does not have Error in its prototype chain, it will be + * wrapped in an Error. + * + * @example + * var f1 = sinon.fake.rejects(":("); + * + * try { + * await ft(); + * } catch (error) { + * console.log(error); + * // ":(" + * } + * + * @memberof fake + * @param {*} value + * @returns {Function} + */fake.rejects=function rejects(value){// eslint-disable-next-line jsdoc/require-jsdoc + function f(){return promiseLib.reject(getError(value));}return wrapFunc(f);};/** + * Causes `fake` to use a custom Promise implementation, instead of the native + * Promise implementation. + * + * @example + * const bluebird = require("bluebird"); + * sinon.fake.usingPromise(bluebird); + * + * @memberof fake + * @param {*} promiseLibrary + * @returns {Function} + */fake.usingPromise=function usingPromise(promiseLibrary){promiseLib=promiseLibrary;return fake;};/** + * Returns a `fake` that calls the callback with the defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * // "apple*pie" + * + * @memberof fake + * @returns {Function} + */fake.yields=function yields(){var values=slice(arguments);// eslint-disable-next-line jsdoc/require-jsdoc + function f(){var callback=arguments[arguments.length-1];if(typeof callback!=="function"){throw new TypeError("Expected last argument to be a function");}callback.apply(null,values);}return wrapFunc(f);};/** + * Returns a `fake` that calls the callback **asynchronously** with the + * defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * * setTimeout(() => { * // "apple*pie" * }); @@ -325,7 +16228,7 @@ * @param args */function throwYieldError(proxy,text,args){var msg=functionName(proxy)+text;if(args.length){msg+=" Received [".concat(join(slice(args),", "),"]");}throw new Error(msg);}var callProto={calledOn:function calledOn(thisValue){if(match.isMatcher(thisValue)){return thisValue.test(this.thisValue);}return this.thisValue===thisValue;},calledWith:function calledWith(){var self=this;var calledWithArgs=slice(arguments);if(calledWithArgs.length>self.args.length){return false;}return reduce(calledWithArgs,function(prev,arg,i){return prev&&deepEqual(self.args[i],arg);},true);},calledWithMatch:function calledWithMatch(){var self=this;var calledWithMatchArgs=slice(arguments);if(calledWithMatchArgs.length>self.args.length){return false;}return reduce(calledWithMatchArgs,function(prev,expectation,i){var actual=self.args[i];return prev&&match(expectation).test(actual);},true);},calledWithExactly:function calledWithExactly(){return arguments.length===this.args.length&&this.calledWith.apply(this,arguments);},notCalledWith:function notCalledWith(){return !this.calledWith.apply(this,arguments);},notCalledWithMatch:function notCalledWithMatch(){return !this.calledWithMatch.apply(this,arguments);},returned:function returned(value){return deepEqual(this.returnValue,value);},threw:function threw(error){if(typeof error==="undefined"||!this.exception){return Boolean(this.exception);}return this.exception===error||this.exception.name===error;},calledWithNew:function calledWithNew(){return this.proxy.prototype&&this.thisValue instanceof this.proxy;},calledBefore:function calledBefore(other){return this.callIdother.callId;},calledImmediatelyBefore:function calledImmediatelyBefore(other){return this.callId===other.callId-1;},calledImmediatelyAfter:function calledImmediatelyAfter(other){return this.callId===other.callId+1;},callArg:function callArg(pos){this.ensureArgIsAFunction(pos);return this.args[pos]();},callArgOn:function callArgOn(pos,thisValue){this.ensureArgIsAFunction(pos);return this.args[pos].apply(thisValue);},callArgWith:function callArgWith(pos){return this.callArgOnWith.apply(this,concat([pos,null],slice(arguments,1)));},callArgOnWith:function callArgOnWith(pos,thisValue){this.ensureArgIsAFunction(pos);var args=slice(arguments,2);return this.args[pos].apply(thisValue,args);},throwArg:function throwArg(pos){if(pos>this.args.length){throw new TypeError("Not enough arguments: ".concat(pos," required but only ").concat(this.args.length," present"));}throw this.args[pos];},"yield":function _yield(){return this.yieldOn.apply(this,concat([null],slice(arguments,0)));},yieldOn:function yieldOn(thisValue){var args=slice(this.args);var yieldFn=filter(args,function(arg){return typeof arg==="function";})[0];if(!yieldFn){throwYieldError(this.proxy," cannot yield since no callback was passed.",args);}return yieldFn.apply(thisValue,slice(arguments,1));},yieldTo:function yieldTo(prop){return this.yieldToOn.apply(this,concat([prop,null],slice(arguments,1)));},yieldToOn:function yieldToOn(prop,thisValue){var args=slice(this.args);var yieldArg=filter(args,function(arg){return arg&&typeof arg[prop]==="function";})[0];var yieldFn=yieldArg&&yieldArg[prop];if(!yieldFn){throwYieldError(this.proxy," cannot yield to '".concat(valueToString(prop),"' since no callback was passed."),args);}return yieldFn.apply(thisValue,slice(arguments,2));},toString:function toString(){if(!this.args){return ":(";}var callStr=this.proxy?"".concat(String(this.proxy),"("):"";var formattedArgs=map(this.args,function(arg){return inspect(arg);});callStr="".concat(callStr+join(formattedArgs,", "),")");if(typeof this.returnValue!=="undefined"){callStr+=" => ".concat(inspect(this.returnValue));}if(this.exception){callStr+=" !".concat(this.exception.name);if(this.exception.message){callStr+="(".concat(this.exception.message,")");}}if(this.stack){// If we have a stack, add the first frame that's in end-user code // Skip the first two frames because they will refer to Sinon code - callStr+=(this.stack.split("\n")[3]||"unknown").replace(/^\s*(?:at\s+|@)?/," at ");}return callStr;},ensureArgIsAFunction:function ensureArgIsAFunction(pos){if(typeof this.args[pos]!=="function"){throw new TypeError("Expected argument at position ".concat(pos," to be a Function, but was ").concat(_typeof(this.args[pos])));}}};Object.defineProperty(callProto,"stack",{enumerable:true,configurable:true,get:function get(){return this.errorWithCallStack&&this.errorWithCallStack.stack||"";}});callProto.invokeCallback=callProto["yield"];/** + callStr+=(this.stack.split("\n")[3]||"unknown").replace(/^\s*(?:at\s+|@)?/," at ");}return callStr;},ensureArgIsAFunction:function ensureArgIsAFunction(pos){if(typeof this.args[pos]!=="function"){throw new TypeError("Expected argument at position ".concat(pos," to be a Function, but was ").concat(_typeof$1(this.args[pos])));}}};Object.defineProperty(callProto,"stack",{enumerable:true,configurable:true,get:function get(){return this.errorWithCallStack&&this.errorWithCallStack.stack||"";}});callProto.invokeCallback=callProto["yield"];/** * @param proxy * @param thisValue * @param args @@ -336,7 +16239,7 @@ */function createProxyCall(proxy,thisValue,args,returnValue,exception,id,errorWithCallStack){if(typeof id!=="number"){throw new TypeError("Call id is not a number");}var firstArg,lastArg;if(args.length>0){firstArg=args[0];lastArg=args[args.length-1];}var proxyCall=Object.create(callProto);var callback=lastArg&&typeof lastArg==="function"?lastArg:undefined;proxyCall.proxy=proxy;proxyCall.thisValue=thisValue;proxyCall.args=args;proxyCall.firstArg=firstArg;proxyCall.lastArg=lastArg;proxyCall.callback=callback;proxyCall.returnValue=returnValue;proxyCall.exception=exception;proxyCall.callId=id;proxyCall.errorWithCallStack=errorWithCallStack;return proxyCall;}createProxyCall.toString=callProto.toString;// used by mocks module.exports=createProxyCall;},{"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],16:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var proxyCallUtil=require("./proxy-call-util");var push=arrayProto.push;var forEach=arrayProto.forEach;var concat=arrayProto.concat;var ErrorConstructor=Error.prototype.constructor;var bind=Function.prototype.bind;var callId=0;module.exports=function invoke(func,thisValue,args){var matchings=this.matchingFakes(args);var currentCallId=callId++;var exception,returnValue;proxyCallUtil.incrementCallCount(this);push(this.thisValues,thisValue);push(this.args,args);push(this.callIds,currentCallId);forEach(matchings,function(matching){proxyCallUtil.incrementCallCount(matching);push(matching.thisValues,thisValue);push(matching.args,args);push(matching.callIds,currentCallId);});// Make call properties available from within the spied function: proxyCallUtil.createCallProperties(this);forEach(matchings,proxyCallUtil.createCallProperties);try{this.invoking=true;var thisCall=this.getCall(this.callCount-1);if(thisCall.calledWithNew()){// Call through with `new` - returnValue=new(bind.apply(this.func||func,concat([thisValue],args)))();if(_typeof(returnValue)!=="object"&&typeof returnValue!=="function"){returnValue=thisValue;}}else {returnValue=(this.func||func).apply(thisValue,args);}}catch(e){exception=e;}finally{delete this.invoking;}push(this.exceptions,exception);push(this.returnValues,returnValue);forEach(matchings,function(matching){push(matching.exceptions,exception);push(matching.returnValues,returnValue);});var err=new ErrorConstructor();// 1. Please do not get stack at this point. It may be so very slow, and not actually used + returnValue=new(bind.apply(this.func||func,concat([thisValue],args)))();if(_typeof$1(returnValue)!=="object"&&typeof returnValue!=="function"){returnValue=thisValue;}}else {returnValue=(this.func||func).apply(thisValue,args);}}catch(e){exception=e;}finally{delete this.invoking;}push(this.exceptions,exception);push(this.returnValues,returnValue);forEach(matchings,function(matching){push(matching.exceptions,exception);push(matching.returnValues,returnValue);});var err=new ErrorConstructor();// 1. Please do not get stack at this point. It may be so very slow, and not actually used // 2. PhantomJS does not serialize the stack trace until the error has been thrown: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack try{throw err;}catch(e){/* empty */}push(this.errorsWithCallStack,err);forEach(matchings,function(matching){push(matching.errorsWithCallStack,err);});// Make return value and exception available in the calls: @@ -352,7 +16255,7 @@ // ref: https://github.com/sinonjs/sinon/issues/710 switch(arity){/*eslint-disable no-unused-vars, max-len*/case 0:p=function proxy(){return p.invoke(func,this,slice(arguments));};break;case 1:p=function proxy(a){return p.invoke(func,this,slice(arguments));};break;case 2:p=function proxy(a,b){return p.invoke(func,this,slice(arguments));};break;case 3:p=function proxy(a,b,c){return p.invoke(func,this,slice(arguments));};break;case 4:p=function proxy(a,b,c,d){return p.invoke(func,this,slice(arguments));};break;case 5:p=function proxy(a,b,c,d,e){return p.invoke(func,this,slice(arguments));};break;case 6:p=function proxy(a,b,c,d,e,f){return p.invoke(func,this,slice(arguments));};break;case 7:p=function proxy(a,b,c,d,e,f,g){return p.invoke(func,this,slice(arguments));};break;case 8:p=function proxy(a,b,c,d,e,f,g,h){return p.invoke(func,this,slice(arguments));};break;case 9:p=function proxy(a,b,c,d,e,f,g,h,i){return p.invoke(func,this,slice(arguments));};break;case 10:p=function proxy(a,b,c,d,e,f,g,h,i,j){return p.invoke(func,this,slice(arguments));};break;case 11:p=function proxy(a,b,c,d,e,f,g,h,i,j,k){return p.invoke(func,this,slice(arguments));};break;case 12:p=function proxy(a,b,c,d,e,f,g,h,i,j,k,l){return p.invoke(func,this,slice(arguments));};break;default:p=function proxy(){return p.invoke(func,this,slice(arguments));};break;/*eslint-enable*/}var nameDescriptor=Object.getOwnPropertyDescriptor(originalFunc,"name");if(nameDescriptor&&nameDescriptor.configurable){// IE 11 functions don't have a name. // Safari 9 has names that are not configurable. - Object.defineProperty(p,"name",nameDescriptor);}extend.nonEnum(p,{isSinonProxy:true,called:false,notCalled:true,calledOnce:false,calledTwice:false,calledThrice:false,callCount:0,firstCall:null,firstArg:null,secondCall:null,thirdCall:null,lastCall:null,lastArg:null,args:[],returnValues:[],thisValues:[],exceptions:[],callIds:[],errorsWithCallStack:[]});return p;}module.exports=createProxy;},{"./proxy-call":15,"./proxy-call-util":14,"./proxy-invoke":16,"./spy-formatters":20,"./util/core/extend":26,"./util/core/function-to-string":27,"@sinonjs/commons":48,"util":113}],18:[function(require,module,exports){var walkObject=require("./util/core/walk-object");function filter(object,property){return object[property].restore&&object[property].restore.sinon;}function restore(object,property){object[property].restore();}function restoreObject(object){return walkObject(restore,object,filter);}module.exports=restoreObject;},{"./util/core/walk-object":38}],19:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var logger=require("@sinonjs/commons").deprecated;var collectOwnMethods=require("./collect-own-methods");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var isPropertyConfigurable=require("./util/core/is-property-configurable");var match=require("@sinonjs/samsam").createMatcher;var sinonAssert=require("./assert");var sinonClock=require("./util/fake-timers");var sinonMock=require("./mock");var sinonSpy=require("./spy");var sinonStub=require("./stub");var sinonCreateStubInstance=require("./create-stub-instance");var sinonFake=require("./fake");var valueToString=require("@sinonjs/commons").valueToString;var fakeServer=require("nise").fakeServer;var fakeXhr=require("nise").fakeXhr;var usePromiseLibrary=require("./util/core/use-promise-library");var DEFAULT_LEAK_THRESHOLD=10000;var filter=arrayProto.filter;var forEach=arrayProto.forEach;var push=arrayProto.push;var reverse=arrayProto.reverse;function applyOnEach(fakes,method){var matchingFakes=filter(fakes,function(fake){return typeof fake[method]==="function";});forEach(matchingFakes,function(fake){fake[method]();});}function throwOnAccessors(descriptor){if(typeof descriptor.get==="function"){throw new Error("Use sandbox.replaceGetter for replacing getters");}if(typeof descriptor.set==="function"){throw new Error("Use sandbox.replaceSetter for replacing setters");}}function verifySameType(object,property,replacement){if(_typeof(object[property])!==_typeof(replacement)){throw new TypeError("Cannot replace ".concat(_typeof(object[property])," with ").concat(_typeof(replacement)));}}function checkForValidArguments(descriptor,property,replacement){if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property),". Perhaps you meant sandbox.define()?"));}if(typeof replacement==="undefined"){throw new TypeError("Expected replacement argument to be defined");}}function Sandbox(){var sandbox=this;var fakeRestorers=[];var promiseLib;var collection=[];var loggedLeakWarning=false;sandbox.leakThreshold=DEFAULT_LEAK_THRESHOLD;function addToCollection(object){if(push(collection,object)>sandbox.leakThreshold&&!loggedLeakWarning){// eslint-disable-next-line no-console + Object.defineProperty(p,"name",nameDescriptor);}extend.nonEnum(p,{isSinonProxy:true,called:false,notCalled:true,calledOnce:false,calledTwice:false,calledThrice:false,callCount:0,firstCall:null,firstArg:null,secondCall:null,thirdCall:null,lastCall:null,lastArg:null,args:[],returnValues:[],thisValues:[],exceptions:[],callIds:[],errorsWithCallStack:[]});return p;}module.exports=createProxy;},{"./proxy-call":15,"./proxy-call-util":14,"./proxy-invoke":16,"./spy-formatters":20,"./util/core/extend":26,"./util/core/function-to-string":27,"@sinonjs/commons":48,"util":113}],18:[function(require,module,exports){var walkObject=require("./util/core/walk-object");function filter(object,property){return object[property].restore&&object[property].restore.sinon;}function restore(object,property){object[property].restore();}function restoreObject(object){return walkObject(restore,object,filter);}module.exports=restoreObject;},{"./util/core/walk-object":38}],19:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var logger=require("@sinonjs/commons").deprecated;var collectOwnMethods=require("./collect-own-methods");var getPropertyDescriptor=require("./util/core/get-property-descriptor");var isPropertyConfigurable=require("./util/core/is-property-configurable");var match=require("@sinonjs/samsam").createMatcher;var sinonAssert=require("./assert");var sinonClock=require("./util/fake-timers");var sinonMock=require("./mock");var sinonSpy=require("./spy");var sinonStub=require("./stub");var sinonCreateStubInstance=require("./create-stub-instance");var sinonFake=require("./fake");var valueToString=require("@sinonjs/commons").valueToString;var fakeServer=require("nise").fakeServer;var fakeXhr=require("nise").fakeXhr;var usePromiseLibrary=require("./util/core/use-promise-library");var DEFAULT_LEAK_THRESHOLD=10000;var filter=arrayProto.filter;var forEach=arrayProto.forEach;var push=arrayProto.push;var reverse=arrayProto.reverse;function applyOnEach(fakes,method){var matchingFakes=filter(fakes,function(fake){return typeof fake[method]==="function";});forEach(matchingFakes,function(fake){fake[method]();});}function throwOnAccessors(descriptor){if(typeof descriptor.get==="function"){throw new Error("Use sandbox.replaceGetter for replacing getters");}if(typeof descriptor.set==="function"){throw new Error("Use sandbox.replaceSetter for replacing setters");}}function verifySameType(object,property,replacement){if(_typeof$1(object[property])!==_typeof$1(replacement)){throw new TypeError("Cannot replace ".concat(_typeof$1(object[property])," with ").concat(_typeof$1(replacement)));}}function checkForValidArguments(descriptor,property,replacement){if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property),". Perhaps you meant sandbox.define()?"));}if(typeof replacement==="undefined"){throw new TypeError("Expected replacement argument to be defined");}}function Sandbox(){var sandbox=this;var fakeRestorers=[];var promiseLib;var collection=[];var loggedLeakWarning=false;sandbox.leakThreshold=DEFAULT_LEAK_THRESHOLD;function addToCollection(object){if(push(collection,object)>sandbox.leakThreshold&&!loggedLeakWarning){// eslint-disable-next-line no-console logger.printWarning("Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox.");loggedLeakWarning=true;}}sandbox.assert=sinonAssert.createAssertObject();sandbox.serverPrototype=fakeServer;// this is for testing only sandbox.getFakes=function getFakes(){return collection;};sandbox.createStubInstance=function createStubInstance(){var stubbed=sinonCreateStubInstance.apply(null,arguments);var ownMethods=collectOwnMethods(stubbed);forEach(ownMethods,function(method){addToCollection(method);});usePromiseLibrary(promiseLib,ownMethods);return stubbed;};sandbox.inject=function inject(obj){obj.spy=function(){return sandbox.spy.apply(null,arguments);};obj.stub=function(){return sandbox.stub.apply(null,arguments);};obj.mock=function(){return sandbox.mock.apply(null,arguments);};obj.createStubInstance=function(){return sandbox.createStubInstance.apply(sandbox,arguments);};obj.fake=function(){return sandbox.fake.apply(null,arguments);};obj.define=function(){return sandbox.define.apply(null,arguments);};obj.replace=function(){return sandbox.replace.apply(null,arguments);};obj.replaceSetter=function(){return sandbox.replaceSetter.apply(null,arguments);};obj.replaceGetter=function(){return sandbox.replaceGetter.apply(null,arguments);};if(sandbox.clock){obj.clock=sandbox.clock;}if(sandbox.server){obj.server=sandbox.server;obj.requests=sandbox.server.requests;}obj.match=match;return obj;};sandbox.mock=function mock(){var m=sinonMock.apply(null,arguments);addToCollection(m);usePromiseLibrary(promiseLib,m);return m;};sandbox.reset=function reset(){applyOnEach(collection,"reset");applyOnEach(collection,"resetHistory");};sandbox.resetBehavior=function resetBehavior(){applyOnEach(collection,"resetBehavior");};sandbox.resetHistory=function resetHistory(){function privateResetHistory(f){var method=f.resetHistory||f.reset;if(method){method.call(f);}}forEach(collection,privateResetHistory);};sandbox.restore=function restore(){if(arguments.length){throw new Error("sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()");}reverse(collection);applyOnEach(collection,"restore");collection=[];forEach(fakeRestorers,function(restorer){restorer();});fakeRestorers=[];sandbox.restoreContext();};sandbox.restoreContext=function restoreContext(){if(!sandbox.injectedKeys){return;}forEach(sandbox.injectedKeys,function(injectedKey){delete sandbox.injectInto[injectedKey];});sandbox.injectedKeys.length=0;};/** * Creates a restorer function for the property @@ -374,7 +16277,7 @@ push(fakeRestorers,getFakeRestorer(object,property));object[property]=value;return value;};sandbox.replaceGetter=function replaceGetter(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property)));}if(typeof replacement!=="function"){throw new TypeError("Expected replacement argument to be a function");}if(typeof descriptor.get!=="function"){throw new Error("`object.property` is not a getter");}verifyNotReplaced(object,property);// store a function for restoring the replaced property push(fakeRestorers,getFakeRestorer(object,property));Object.defineProperty(object,property,{get:replacement,configurable:isPropertyConfigurable(object,property)});return replacement;};sandbox.replaceSetter=function replaceSetter(object,property,replacement){var descriptor=getPropertyDescriptor(object,property);if(typeof descriptor==="undefined"){throw new TypeError("Cannot replace non-existent property ".concat(valueToString(property)));}if(typeof replacement!=="function"){throw new TypeError("Expected replacement argument to be a function");}if(typeof descriptor.set!=="function"){throw new Error("`object.property` is not a setter");}verifyNotReplaced(object,property);// store a function for restoring the replaced property push(fakeRestorers,getFakeRestorer(object,property));// eslint-disable-next-line accessor-pairs - Object.defineProperty(object,property,{set:replacement,configurable:isPropertyConfigurable(object,property)});return replacement;};function commonPostInitSetup(args,spy){var _args2=_slicedToArray(args,3),object=_args2[0],property=_args2[1],types=_args2[2];var isSpyingOnEntireObject=typeof property==="undefined"&&_typeof(object)==="object";if(isSpyingOnEntireObject){var ownMethods=collectOwnMethods(spy);forEach(ownMethods,function(method){addToCollection(method);});usePromiseLibrary(promiseLib,ownMethods);}else if(Array.isArray(types)){var _iterator=_createForOfIteratorHelper(types),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var accessorType=_step.value;addToCollection(spy[accessorType]);usePromiseLibrary(promiseLib,spy[accessorType]);}}catch(err){_iterator.e(err);}finally{_iterator.f();}}else {addToCollection(spy);usePromiseLibrary(promiseLib,spy);}return spy;}sandbox.spy=function spy(){var createdSpy=sinonSpy.apply(sinonSpy,arguments);return commonPostInitSetup(arguments,createdSpy);};sandbox.stub=function stub(){var createdStub=sinonStub.apply(sinonStub,arguments);return commonPostInitSetup(arguments,createdStub);};// eslint-disable-next-line no-unused-vars + Object.defineProperty(object,property,{set:replacement,configurable:isPropertyConfigurable(object,property)});return replacement;};function commonPostInitSetup(args,spy){var _args9=_slicedToArray(args,3),object=_args9[0],property=_args9[1],types=_args9[2];var isSpyingOnEntireObject=typeof property==="undefined"&&_typeof$1(object)==="object";if(isSpyingOnEntireObject){var ownMethods=collectOwnMethods(spy);forEach(ownMethods,function(method){addToCollection(method);});usePromiseLibrary(promiseLib,ownMethods);}else if(Array.isArray(types)){var _iterator3=_createForOfIteratorHelper2(types),_step3;try{for(_iterator3.s();!(_step3=_iterator3.n()).done;){var accessorType=_step3.value;addToCollection(spy[accessorType]);usePromiseLibrary(promiseLib,spy[accessorType]);}}catch(err){_iterator3.e(err);}finally{_iterator3.f();}}else {addToCollection(spy);usePromiseLibrary(promiseLib,spy);}return spy;}sandbox.spy=function spy(){var createdSpy=sinonSpy.apply(sinonSpy,arguments);return commonPostInitSetup(arguments,createdSpy);};sandbox.stub=function stub(){var createdStub=sinonStub.apply(sinonStub,arguments);return commonPostInitSetup(arguments,createdStub);};// eslint-disable-next-line no-unused-vars sandbox.fake=function fake(f){var s=sinonFake.apply(sinonFake,arguments);addToCollection(s);return s;};forEach(Object.keys(sinonFake),function(key){var fakeBehavior=sinonFake[key];if(typeof fakeBehavior==="function"){sandbox.fake[key]=function(){var s=fakeBehavior.apply(fakeBehavior,arguments);addToCollection(s);return s;};}});sandbox.useFakeTimers=function useFakeTimers(args){var clock=sinonClock.useFakeTimers.call(null,args);sandbox.clock=clock;addToCollection(clock);return clock;};sandbox.verify=function verify(){applyOnEach(collection,"verify");};sandbox.verifyAndRestore=function verifyAndRestore(){var exception;try{sandbox.verify();}catch(e){exception=e;}sandbox.restore();if(exception){throw exception;}};sandbox.useFakeServer=function useFakeServer(){var proto=sandbox.serverPrototype||fakeServer;if(!proto||!proto.create){return null;}sandbox.server=proto.create();addToCollection(sandbox.server);return sandbox.server;};sandbox.useFakeXMLHttpRequest=function useFakeXMLHttpRequest(){var xhr=fakeXhr.useFakeXMLHttpRequest();addToCollection(xhr);return xhr;};sandbox.usingPromise=function usingPromise(promiseLibrary){promiseLib=promiseLibrary;collection.promiseLibrary=promiseLibrary;return sandbox;};}Sandbox.prototype.match=match;module.exports=Sandbox;},{"./assert":3,"./collect-own-methods":5,"./create-stub-instance":8,"./fake":10,"./mock":12,"./spy":21,"./stub":22,"./util/core/get-property-descriptor":29,"./util/core/is-property-configurable":32,"./util/core/use-promise-library":37,"./util/fake-timers":41,"@sinonjs/commons":48,"@sinonjs/samsam":88,"nise":128}],20:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var color=require("./color");var match=require("@sinonjs/samsam").createMatcher;var timesInWords=require("./util/core/times-in-words");var inspect=require("util").inspect;var jsDiff=require("diff");var join=arrayProto.join;var map=arrayProto.map;var push=arrayProto.push;var slice=arrayProto.slice;function colorSinonMatchText(matcher,calledArg,calledArgMessage){var calledArgumentMessage=calledArgMessage;var matcherMessage=matcher.message;if(!matcher.test(calledArg)){matcherMessage=color.red(matcher.message);if(calledArgumentMessage){calledArgumentMessage=color.green(calledArgumentMessage);}}return "".concat(calledArgumentMessage," ").concat(matcherMessage);}function colorDiffText(diff){var objects=map(diff,function(part){var text=part.value;if(part.added){text=color.green(text);}else if(part.removed){text=color.red(text);}if(diff.length===2){text+=" ";// format simple diffs }return text;});return join(objects,"");}function quoteStringValue(value){if(typeof value==="string"){return JSON.stringify(value);}return value;}module.exports={c:function c(spyInstance){return timesInWords(spyInstance.callCount);},n:function n(spyInstance){// eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods return spyInstance.toString();},D:function D(spyInstance,args){var message="";for(var i=0,l=spyInstance.callCount;i2){throw new TypeError("stub(obj, 'meth', fn) has been removed, see documentation");}if(isEsModule(object)){throw new TypeError("ES Modules cannot be stubbed");}throwOnFalsyObject.apply(null,arguments);if(isNonExistentProperty(object,property)){throw new TypeError("Cannot stub non-existent property ".concat(valueToString(property)));}var actualDescriptor=getPropertyDescriptor(object,property);assertValidPropertyDescriptor(actualDescriptor,property);var isObjectOrFunction=_typeof(object)==="object"||typeof object==="function";var isStubbingEntireObject=typeof property==="undefined"&&isObjectOrFunction;var isCreatingNewStub=!object&&typeof property==="undefined";var isStubbingNonFuncProperty=isObjectOrFunction&&typeof property!=="undefined"&&(typeof actualDescriptor==="undefined"||typeof actualDescriptor.value!=="function");if(isStubbingEntireObject){return walkObject(stub,object);}if(isCreatingNewStub){return createStub();}var func=typeof actualDescriptor.value==="function"?actualDescriptor.value:null;var s=createStub(func);extend.nonEnum(s,{rootObj:object,propName:property,shadowsPropOnPrototype:!actualDescriptor.isOwn,restore:function restore(){if(actualDescriptor!==undefined&&actualDescriptor.isOwn){Object.defineProperty(object,property,actualDescriptor);return;}delete object[property];}});return isStubbingNonFuncProperty?s:wrapMethod(object,property,s);}function assertValidPropertyDescriptor(descriptor,property){if(!descriptor||!property){return;}if(descriptor.isOwn&&!descriptor.configurable&&!descriptor.writable){throw new TypeError("Descriptor for property ".concat(property," is non-configurable and non-writable"));}if((descriptor.get||descriptor.set)&&!descriptor.configurable){throw new TypeError("Descriptor for accessor property ".concat(property," is non-configurable"));}if(isDataDescriptor(descriptor)&&!descriptor.writable){throw new TypeError("Descriptor for data property ".concat(property," is non-writable"));}}function isDataDescriptor(descriptor){return !descriptor.value&&!descriptor.writable&&!descriptor.set&&!descriptor.get;}/*eslint-disable no-use-before-define*/function getParentBehaviour(stubInstance){return stubInstance.parent&&getCurrentBehavior(stubInstance.parent);}function getDefaultBehavior(stubInstance){return stubInstance.defaultBehavior||getParentBehaviour(stubInstance)||behavior.create(stubInstance);}function getCurrentBehavior(stubInstance){var currentBehavior=stubInstance.behaviors[stubInstance.callCount-1];return currentBehavior&¤tBehavior.isPresent()?currentBehavior:getDefaultBehavior(stubInstance);}/*eslint-enable no-use-before-define*/var proto={resetBehavior:function resetBehavior(){this.defaultBehavior=null;this.behaviors=[];delete this.returnValue;delete this.returnArgAt;delete this.throwArgAt;delete this.resolveArgAt;delete this.fakeFn;this.returnThis=false;this.resolveThis=false;forEach(this.fakes,function(fake){fake.resetBehavior();});},reset:function reset(){this.resetHistory();this.resetBehavior();},onCall:function onCall(index){if(!this.behaviors[index]){this.behaviors[index]=behavior.create(this);}return this.behaviors[index];},onFirstCall:function onFirstCall(){return this.onCall(0);},onSecondCall:function onSecondCall(){return this.onCall(1);},onThirdCall:function onThirdCall(){return this.onCall(2);},withArgs:function withArgs(){var fake=spy.withArgs.apply(this,arguments);if(this.defaultBehavior&&this.defaultBehavior.promiseLibrary){fake.defaultBehavior=fake.defaultBehavior||behavior.create(fake);fake.defaultBehavior.promiseLibrary=this.defaultBehavior.promiseLibrary;}return fake;}};forEach(Object.keys(behavior),function(method){if(hasOwnProperty(behavior,method)&&!hasOwnProperty(proto,method)&&method!=="create"&&method!=="invoke"){proto[method]=behavior.createBehavior(method);}});forEach(Object.keys(behaviors),function(method){if(hasOwnProperty(behaviors,method)&&!hasOwnProperty(proto,method)){behavior.addBehavior(stub,method,behaviors[method]);}});extend(stub,proto);module.exports=stub;},{"./behavior":4,"./default-behaviors":9,"./proxy":17,"./spy":21,"./throw-on-falsy-object":23,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/is-non-existent-property":31,"./util/core/sinon-type":35,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48}],23:[function(require,module,exports){var valueToString=require("@sinonjs/commons").valueToString;function throwOnFalsyObject(object,property){if(property&&!object){var type=object===null?"null":"undefined";throw new Error("Trying to stub property '".concat(valueToString(property),"' of ").concat(type));}}module.exports=throwOnFalsyObject;},{"@sinonjs/commons":48}],24:[function(require,module,exports){module.exports={injectInto:null,properties:["spy","stub","mock","clock","server","requests","fake","define","replace","replaceSetter","replaceGetter","createStubInstance"],useFakeTimers:true,useFakeServer:true};},{}],25:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var reduce=arrayProto.reduce;module.exports=function exportAsyncBehaviors(behaviorMethods){return reduce(Object.keys(behaviorMethods),function(acc,method){// need to avoid creating another async versions of the newly added async methods + extend.nonEnum(proxy,stub);var name=originalFunc?functionName(originalFunc):null;extend.nonEnum(proxy,{fakes:[],instantiateFake:createStub,displayName:name||"stub",defaultBehavior:null,behaviors:[],id:"stub#".concat(uuid++)});sinonType.set(proxy,"stub");return proxy;}function stub(object,property){if(arguments.length>2){throw new TypeError("stub(obj, 'meth', fn) has been removed, see documentation");}if(isEsModule(object)){throw new TypeError("ES Modules cannot be stubbed");}throwOnFalsyObject.apply(null,arguments);if(isNonExistentProperty(object,property)){throw new TypeError("Cannot stub non-existent property ".concat(valueToString(property)));}var actualDescriptor=getPropertyDescriptor(object,property);assertValidPropertyDescriptor(actualDescriptor,property);var isObjectOrFunction=_typeof$1(object)==="object"||typeof object==="function";var isStubbingEntireObject=typeof property==="undefined"&&isObjectOrFunction;var isCreatingNewStub=!object&&typeof property==="undefined";var isStubbingNonFuncProperty=isObjectOrFunction&&typeof property!=="undefined"&&(typeof actualDescriptor==="undefined"||typeof actualDescriptor.value!=="function");if(isStubbingEntireObject){return walkObject(stub,object);}if(isCreatingNewStub){return createStub();}var func=typeof actualDescriptor.value==="function"?actualDescriptor.value:null;var s=createStub(func);extend.nonEnum(s,{rootObj:object,propName:property,shadowsPropOnPrototype:!actualDescriptor.isOwn,restore:function restore(){if(actualDescriptor!==undefined&&actualDescriptor.isOwn){Object.defineProperty(object,property,actualDescriptor);return;}delete object[property];}});return isStubbingNonFuncProperty?s:wrapMethod(object,property,s);}function assertValidPropertyDescriptor(descriptor,property){if(!descriptor||!property){return;}if(descriptor.isOwn&&!descriptor.configurable&&!descriptor.writable){throw new TypeError("Descriptor for property ".concat(property," is non-configurable and non-writable"));}if((descriptor.get||descriptor.set)&&!descriptor.configurable){throw new TypeError("Descriptor for accessor property ".concat(property," is non-configurable"));}if(isDataDescriptor(descriptor)&&!descriptor.writable){throw new TypeError("Descriptor for data property ".concat(property," is non-writable"));}}function isDataDescriptor(descriptor){return !descriptor.value&&!descriptor.writable&&!descriptor.set&&!descriptor.get;}/*eslint-disable no-use-before-define*/function getParentBehaviour(stubInstance){return stubInstance.parent&&getCurrentBehavior(stubInstance.parent);}function getDefaultBehavior(stubInstance){return stubInstance.defaultBehavior||getParentBehaviour(stubInstance)||behavior.create(stubInstance);}function getCurrentBehavior(stubInstance){var currentBehavior=stubInstance.behaviors[stubInstance.callCount-1];return currentBehavior&¤tBehavior.isPresent()?currentBehavior:getDefaultBehavior(stubInstance);}/*eslint-enable no-use-before-define*/var proto={resetBehavior:function resetBehavior(){this.defaultBehavior=null;this.behaviors=[];delete this.returnValue;delete this.returnArgAt;delete this.throwArgAt;delete this.resolveArgAt;delete this.fakeFn;this.returnThis=false;this.resolveThis=false;forEach(this.fakes,function(fake){fake.resetBehavior();});},reset:function reset(){this.resetHistory();this.resetBehavior();},onCall:function onCall(index){if(!this.behaviors[index]){this.behaviors[index]=behavior.create(this);}return this.behaviors[index];},onFirstCall:function onFirstCall(){return this.onCall(0);},onSecondCall:function onSecondCall(){return this.onCall(1);},onThirdCall:function onThirdCall(){return this.onCall(2);},withArgs:function withArgs(){var fake=spy.withArgs.apply(this,arguments);if(this.defaultBehavior&&this.defaultBehavior.promiseLibrary){fake.defaultBehavior=fake.defaultBehavior||behavior.create(fake);fake.defaultBehavior.promiseLibrary=this.defaultBehavior.promiseLibrary;}return fake;}};forEach(Object.keys(behavior),function(method){if(hasOwnProperty(behavior,method)&&!hasOwnProperty(proto,method)&&method!=="create"&&method!=="invoke"){proto[method]=behavior.createBehavior(method);}});forEach(Object.keys(behaviors),function(method){if(hasOwnProperty(behaviors,method)&&!hasOwnProperty(proto,method)){behavior.addBehavior(stub,method,behaviors[method]);}});extend(stub,proto);module.exports=stub;},{"./behavior":4,"./default-behaviors":9,"./proxy":17,"./spy":21,"./throw-on-falsy-object":23,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/is-non-existent-property":31,"./util/core/sinon-type":35,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48}],23:[function(require,module,exports){var valueToString=require("@sinonjs/commons").valueToString;function throwOnFalsyObject(object,property){if(property&&!object){var _type2=object===null?"null":"undefined";throw new Error("Trying to stub property '".concat(valueToString(property),"' of ").concat(_type2));}}module.exports=throwOnFalsyObject;},{"@sinonjs/commons":48}],24:[function(require,module,exports){module.exports={injectInto:null,properties:["spy","stub","mock","clock","server","requests","fake","define","replace","replaceSetter","replaceGetter","createStubInstance"],useFakeTimers:true,useFakeServer:true};},{}],25:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var reduce=arrayProto.reduce;module.exports=function exportAsyncBehaviors(behaviorMethods){return reduce(Object.keys(behaviorMethods),function(acc,method){// need to avoid creating another async versions of the newly added async methods if(method.match(/^(callsArg|yields)/)&&!method.match(/Async/)){acc["".concat(method,"Async")]=function(){var result=behaviorMethods[method].apply(this,arguments);this.callbackAsync=true;return result;};}return acc;},{});};},{"@sinonjs/commons":48}],26:[function(require,module,exports){var arrayProto=require("@sinonjs/commons").prototypes.array;var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var join=arrayProto.join;var push=arrayProto.push;// Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug var hasDontEnumBug=function(){var obj={constructor:function constructor(){return "0";},toString:function toString(){return "1";},valueOf:function valueOf(){return "2";},toLocaleString:function toLocaleString(){return "3";},prototype:function prototype(){return "4";},isPrototypeOf:function isPrototypeOf(){return "5";},propertyIsEnumerable:function propertyIsEnumerable(){return "6";},hasOwnProperty:function hasOwnProperty(){return "7";},length:function length(){return "8";},unique:function unique(){return "9";}};var result=[];for(var prop in obj){if(hasOwnProperty(obj,prop)){push(result,obj[prop]());}}return join(result,"")!=="0123456789";}();/** * @@ -403,7 +16306,7 @@ * @param {object} target - The Object to extend * @param {object[]} sources - Objects to copy properties from. * @returns {object} the extended target - */module.exports=function extend(target){for(var _len=arguments.length,sources=new Array(_len>1?_len-1:0),_key2=1;_key2<_len;_key2++){sources[_key2-1]=arguments[_key2];}return extendCommon(target,sources,function copyValue(dest,source,prop){var destOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(dest,prop);var sourceOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(source,prop);if(prop==="name"&&!destOwnPropertyDescriptor.writable){return;}var descriptors={configurable:sourceOwnPropertyDescriptor.configurable,enumerable:sourceOwnPropertyDescriptor.enumerable};/* + */module.exports=function extend(target){for(var _len7=arguments.length,sources=new Array(_len7>1?_len7-1:0),_key8=1;_key8<_len7;_key8++){sources[_key8-1]=arguments[_key8];}return extendCommon(target,sources,function copyValue(dest,source,prop){var destOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(dest,prop);var sourceOwnPropertyDescriptor=Object.getOwnPropertyDescriptor(source,prop);if(prop==="name"&&!destOwnPropertyDescriptor.writable){return;}var descriptors={configurable:sourceOwnPropertyDescriptor.configurable,enumerable:sourceOwnPropertyDescriptor.enumerable};/* if the sorce has an Accessor property copy over the accessor functions (get and set) data properties has writable attribute where as accessor property don't REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties @@ -414,9 +16317,9 @@ * @param {object} target - The Object to extend * @param {object[]} sources - Objects to copy properties from. * @returns {object} the extended target - */module.exports.nonEnum=function extendNonEnum(target){for(var _len2=arguments.length,sources=new Array(_len2>1?_len2-1:0),_key3=1;_key3<_len2;_key3++){sources[_key3-1]=arguments[_key3];}return extendCommon(target,sources,function copyProperty(dest,source,prop){Object.defineProperty(dest,prop,{value:source[prop],enumerable:false,configurable:true,writable:true});});};},{"@sinonjs/commons":48}],27:[function(require,module,exports){module.exports=function toString(){var i,prop,thisValue;if(this.getCall&&this.callCount){i=this.callCount;while(i--){thisValue=this.getCall(i).thisValue;// eslint-disable-next-line guard-for-in + */module.exports.nonEnum=function extendNonEnum(target){for(var _len8=arguments.length,sources=new Array(_len8>1?_len8-1:0),_key9=1;_key9<_len8;_key9++){sources[_key9-1]=arguments[_key9];}return extendCommon(target,sources,function copyProperty(dest,source,prop){Object.defineProperty(dest,prop,{value:source[prop],enumerable:false,configurable:true,writable:true});});};},{"@sinonjs/commons":48}],27:[function(require,module,exports){module.exports=function toString(){var i,prop,thisValue;if(this.getCall&&this.callCount){i=this.callCount;while(i--){thisValue=this.getCall(i).thisValue;// eslint-disable-next-line guard-for-in for(prop in thisValue){try{if(thisValue[prop]===this){return prop;}}catch(e){// no-op - accessing props can throw an error, nothing to do here - }}}}return this.displayName||"sinon fake";};},{}],28:[function(require,module,exports){/* istanbul ignore next : not testing that setTimeout works */function nextTick(callback){setTimeout(callback,0);}module.exports=function getNextTick(process,setImmediate){if(_typeof(process)==="object"&&typeof process.nextTick==="function"){return process.nextTick;}if(typeof setImmediate==="function"){return setImmediate;}return nextTick;};},{}],29:[function(require,module,exports){/* eslint-disable jsdoc/valid-types */ /* + }}}}return this.displayName||"sinon fake";};},{}],28:[function(require,module,exports){/* istanbul ignore next : not testing that setTimeout works */function nextTick(callback){setTimeout(callback,0);}module.exports=function getNextTick(process,setImmediate){if(_typeof$1(process)==="object"&&typeof process.nextTick==="function"){return process.nextTick;}if(typeof setImmediate==="function"){return setImmediate;}return nextTick;};},{}],29:[function(require,module,exports){/* eslint-disable jsdoc/valid-types */ /* * The following type def is strictly an illegal JSDoc, but the expression forms a * legal Typescript union type and is understood by Visual Studio and the IntelliJ * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these @@ -471,9 +16374,9 @@ * context - (Optional) When given, the iterator will be called with this object as the receiver. */module.exports=function walk(obj,iterator,context){return walkInternal(obj,iterator,context,obj,{});};},{"@sinonjs/commons":48}],40:[function(require,module,exports){// eslint-disable-next-line no-empty-function var noop=function noop(){};var getPropertyDescriptor=require("./get-property-descriptor");var extend=require("./extend");var sinonType=require("./sinon-type");var hasOwnProperty=require("@sinonjs/commons").prototypes.object.hasOwnProperty;var valueToString=require("@sinonjs/commons").valueToString;var push=require("@sinonjs/commons").prototypes.array.push;function isFunction(obj){return typeof obj==="function"||Boolean(obj&&obj.constructor&&obj.call&&obj.apply);}function mirrorProperties(target,source){for(var prop in source){if(!hasOwnProperty(target,prop)){target[prop]=source[prop];}}}function getAccessor(object,property,method){var accessors=["get","set"];var descriptor=getPropertyDescriptor(object,property);for(var i=0;i-1;var maxTimeout=Math.pow(2,31)-1;//see https://heycam.github.io/webidl/#abstract-opdef-converttoint var idCounterStart=1e12;// arbitrarily large number to avoid collisions with native timer IDs - var NOOP=function NOOP(){return undefined;};var NOOP_ARRAY=function NOOP_ARRAY(){return [];};var timeoutResult=_global.setTimeout(NOOP,0);var addTimerReturnsObject=_typeof(timeoutResult)==="object";var hrtimePresent=_global.process&&typeof _global.process.hrtime==="function";var hrtimeBigintPresent=hrtimePresent&&typeof _global.process.hrtime.bigint==="function";var nextTickPresent=_global.process&&typeof _global.process.nextTick==="function";var utilPromisify=_global.process&&require("util").promisify;var performancePresent=_global.performance&&typeof _global.performance.now==="function";var hasPerformancePrototype=_global.Performance&&_typeof(_global.Performance).match(/^(function|object)$/);var hasPerformanceConstructorPrototype=_global.performance&&_global.performance.constructor&&_global.performance.constructor.prototype;var queueMicrotaskPresent=_global.hasOwnProperty("queueMicrotask");var requestAnimationFramePresent=_global.requestAnimationFrame&&typeof _global.requestAnimationFrame==="function";var cancelAnimationFramePresent=_global.cancelAnimationFrame&&typeof _global.cancelAnimationFrame==="function";var requestIdleCallbackPresent=_global.requestIdleCallback&&typeof _global.requestIdleCallback==="function";var cancelIdleCallbackPresent=_global.cancelIdleCallback&&typeof _global.cancelIdleCallback==="function";var setImmediatePresent=_global.setImmediate&&typeof _global.setImmediate==="function";// Make properties writable in IE, as per + var NOOP=function NOOP(){return undefined;};var NOOP_ARRAY=function NOOP_ARRAY(){return [];};var timeoutResult=_global.setTimeout(NOOP,0);var addTimerReturnsObject=_typeof$1(timeoutResult)==="object";var hrtimePresent=_global.process&&typeof _global.process.hrtime==="function";var hrtimeBigintPresent=hrtimePresent&&typeof _global.process.hrtime.bigint==="function";var nextTickPresent=_global.process&&typeof _global.process.nextTick==="function";var utilPromisify=_global.process&&require("util").promisify;var performancePresent=_global.performance&&typeof _global.performance.now==="function";var hasPerformancePrototype=_global.Performance&&_typeof$1(_global.Performance).match(/^(function|object)$/);var hasPerformanceConstructorPrototype=_global.performance&&_global.performance.constructor&&_global.performance.constructor.prototype;var queueMicrotaskPresent=_global.hasOwnProperty("queueMicrotask");var requestAnimationFramePresent=_global.requestAnimationFrame&&typeof _global.requestAnimationFrame==="function";var cancelAnimationFramePresent=_global.cancelAnimationFrame&&typeof _global.cancelAnimationFrame==="function";var requestIdleCallbackPresent=_global.requestIdleCallback&&typeof _global.requestIdleCallback==="function";var cancelIdleCallbackPresent=_global.cancelIdleCallback&&typeof _global.cancelIdleCallback==="function";var setImmediatePresent=_global.setImmediate&&typeof _global.setImmediate==="function";// Make properties writable in IE, as per // https://www.adequatelygood.com/Replacing-setTimeout-Globally.html /* eslint-disable no-self-assign */if(isRunningInIE){_global.setTimeout=_global.setTimeout;_global.clearTimeout=_global.clearTimeout;_global.setInterval=_global.setInterval;_global.clearInterval=_global.clearInterval;_global.Date=_global.Date;}// setImmediate is not a standard function // avoid adding the prop to the window object if not present @@ -803,7 +16706,7 @@ * @param {Timer} timer * @returns {number} id of the created timer */function addTimer(clock,timer){if(timer.func===undefined){throw new Error("Callback must be provided to timer calls");}if(addTimerReturnsObject){// Node.js environment - if(typeof timer.func!=="function"){throw new TypeError("[ERR_INVALID_CALLBACK]: Callback must be a function. Received ".concat(timer.func," of type ").concat(_typeof(timer.func)));}}if(isNearInfiniteLimit){timer.error=new Error();}timer.type=timer.immediate?"Immediate":"Timeout";if(timer.hasOwnProperty("delay")){if(typeof timer.delay!=="number"){timer.delay=parseInt(timer.delay,10);}if(!isNumberFinite(timer.delay)){timer.delay=0;}timer.delay=timer.delay>maxTimeout?1:timer.delay;timer.delay=Math.max(0,timer.delay);}if(timer.hasOwnProperty("interval")){timer.type="Interval";timer.interval=timer.interval>maxTimeout?1:timer.interval;}if(timer.hasOwnProperty("animation")){timer.type="AnimationFrame";timer.animation=true;}if(timer.hasOwnProperty("idleCallback")){timer.type="IdleCallback";timer.idleCallback=true;}if(!clock.timers){clock.timers={};}timer.id=uniqueTimerId++;timer.createdAt=clock.now;timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));clock.timers[timer.id]=timer;if(addTimerReturnsObject){var res=_defineProperty({refed:true,ref:function ref(){this.refed=true;return res;},unref:function unref(){this.refed=false;return res;},hasRef:function hasRef(){return this.refed;},refresh:function refresh(){timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));// it _might_ have been removed, but if not the assignment is perfectly fine + if(typeof timer.func!=="function"){throw new TypeError("[ERR_INVALID_CALLBACK]: Callback must be a function. Received ".concat(timer.func," of type ").concat(_typeof$1(timer.func)));}}if(isNearInfiniteLimit){timer.error=new Error();}timer.type=timer.immediate?"Immediate":"Timeout";if(timer.hasOwnProperty("delay")){if(typeof timer.delay!=="number"){timer.delay=parseInt(timer.delay,10);}if(!isNumberFinite(timer.delay)){timer.delay=0;}timer.delay=timer.delay>maxTimeout?1:timer.delay;timer.delay=Math.max(0,timer.delay);}if(timer.hasOwnProperty("interval")){timer.type="Interval";timer.interval=timer.interval>maxTimeout?1:timer.interval;}if(timer.hasOwnProperty("animation")){timer.type="AnimationFrame";timer.animation=true;}if(timer.hasOwnProperty("idleCallback")){timer.type="IdleCallback";timer.idleCallback=true;}if(!clock.timers){clock.timers={};}timer.id=uniqueTimerId++;timer.createdAt=clock.now;timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));clock.timers[timer.id]=timer;if(addTimerReturnsObject){var res=_defineProperty({refed:true,ref:function ref(){this.refed=true;return res;},unref:function unref(){this.refed=false;return res;},hasRef:function hasRef(){return this.refed;},refresh:function refresh(){timer.callAt=clock.now+(parseInt(timer.delay)||(clock.duringTick?1:0));// it _might_ have been removed, but if not the assignment is perfectly fine clock.timers[timer.id]=timer;return res;}},Symbol.toPrimitive,function(){return timer.id;});return res;}return timer.id;}/* eslint consistent-return: "off" */ /** * Timer comparitor * @@ -930,7 +16833,7 @@ for(id in clock.timers){if(clock.timers.hasOwnProperty(id)){timer=clock.timers[id];timer.createdAt+=difference;timer.callAt+=difference;}}};/** * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" * @returns {number} will return the new `now` value - */clock.jump=function jump(tickValue){var msFloat=typeof tickValue==="number"?tickValue:parseTime(tickValue);var ms=Math.floor(msFloat);for(var _i2=0,_Object$values=Object.values(clock.timers);_i2<_Object$values.length;_i2++){var timer=_Object$values[_i2];if(clock.now+ms>timer.callAt){timer.callAt=clock.now+ms;}}clock.tick(ms);};if(performancePresent){clock.performance=Object.create(null);clock.performance.now=fakePerformanceNow;}if(hrtimePresent){clock.hrtime=hrtime;}return clock;}/* eslint-disable complexity */ /** + */clock.jump=function jump(tickValue){var msFloat=typeof tickValue==="number"?tickValue:parseTime(tickValue);var ms=Math.floor(msFloat);for(var _i3=0,_Object$values2=Object.values(clock.timers);_i3<_Object$values2.length;_i3++){var timer=_Object$values2[_i3];if(clock.now+ms>timer.callAt){timer.callAt=clock.now+ms;}}clock.tick(ms);};if(performancePresent){clock.performance=Object.create(null);clock.performance.now=fakePerformanceNow;}if(hrtimePresent){clock.hrtime=hrtime;}return clock;}/* eslint-disable complexity */ /** * @param {Config=} [config] Optional config * @returns {Clock} */function install(config){if(arguments.length>1||config instanceof Date||Array.isArray(config)||typeof config==="number"){throw new TypeError("FakeTimers.install called with ".concat(String(config)," install requires an object parameter"));}if(_global.Date.isFake===true){// Timers are already faked; this is a problem. @@ -961,7 +16864,7 @@ * @param {Function} propertyTest A function to test the property against a value * @param {string} messagePrefix A prefix to use for messages generated by the matcher * @returns {object} A matcher - */function createPropertyMatcher(propertyTest,messagePrefix){return function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="".concat(messagePrefix,"(\"").concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||!propertyTest(actual,property)){return false;}return onlyProperty||deepEqual(actual[property],value);},message);};}createMatcher.has=createPropertyMatcher(function(actual,property){if(_typeof(actual)==="object"){return property in actual;}return actual[property]!==undefined;},"has");createMatcher.hasOwn=createPropertyMatcher(function(actual,property){return hasOwnProperty(actual,property);},"hasOwn");createMatcher.hasNested=function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="hasNested(\"".concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||get(actual,property)===undefined){return false;}return onlyProperty||deepEqual(get(actual,property),value);},message);};var jsonParseResultTypes={"null":true,"boolean":true,number:true,string:true,object:true,array:true};createMatcher.json=function(value){if(!jsonParseResultTypes[typeOf(value)]){throw new TypeError("Value cannot be the result of JSON.parse");}var message="json(".concat(JSON.stringify(value,null," "),")");return createMatcher(function(actual){var parsed;try{parsed=JSON.parse(actual);}catch(e){return false;}return deepEqual(parsed,value);},message);};createMatcher.every=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return every(Object.keys(actual),function(key){return predicate.test(actual[key]);});}return isIterable(actual)&&every(actual,function(element){return predicate.test(element);});},"every(".concat(predicate.message,")"));};createMatcher.some=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return !every(Object.keys(actual),function(key){return !predicate.test(actual[key]);});}return isIterable(actual)&&!every(actual,function(element){return !predicate.test(element);});},"some(".concat(predicate.message,")"));};createMatcher.array=createMatcher.typeOf("array");createMatcher.array.deepEquals=function(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item + */function createPropertyMatcher(propertyTest,messagePrefix){return function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="".concat(messagePrefix,"(\"").concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||!propertyTest(actual,property)){return false;}return onlyProperty||deepEqual(actual[property],value);},message);};}createMatcher.has=createPropertyMatcher(function(actual,property){if(_typeof$1(actual)==="object"){return property in actual;}return actual[property]!==undefined;},"has");createMatcher.hasOwn=createPropertyMatcher(function(actual,property){return hasOwnProperty(actual,property);},"hasOwn");createMatcher.hasNested=function(property,value){assertType(property,"string","property");var onlyProperty=arguments.length===1;var message="hasNested(\"".concat(property,"\"");if(!onlyProperty){message+=", ".concat(valueToString(value));}message+=")";return createMatcher(function(actual){if(actual===undefined||actual===null||get(actual,property)===undefined){return false;}return onlyProperty||deepEqual(get(actual,property),value);},message);};var jsonParseResultTypes={"null":true,"boolean":true,number:true,string:true,object:true,array:true};createMatcher.json=function(value){if(!jsonParseResultTypes[typeOf(value)]){throw new TypeError("Value cannot be the result of JSON.parse");}var message="json(".concat(JSON.stringify(value,null," "),")");return createMatcher(function(actual){var parsed;try{parsed=JSON.parse(actual);}catch(e){return false;}return deepEqual(parsed,value);},message);};createMatcher.every=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return every(Object.keys(actual),function(key){return predicate.test(actual[key]);});}return isIterable(actual)&&every(actual,function(element){return predicate.test(element);});},"every(".concat(predicate.message,")"));};createMatcher.some=function(predicate){assertMatcher(predicate);return createMatcher(function(actual){if(typeOf(actual)==="object"){return !every(Object.keys(actual),function(key){return !predicate.test(actual[key]);});}return isIterable(actual)&&!every(actual,function(element){return !predicate.test(element);});},"some(".concat(predicate.message,")"));};createMatcher.array=createMatcher.typeOf("array");createMatcher.array.deepEquals=function(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item var sameLength=actual.length===expectation.length;return typeOf(actual)==="array"&&sameLength&&every(actual,function(element,index){var expected=expectation[index];return typeOf(expected)==="array"&&typeOf(element)==="array"?createMatcher.array.deepEquals(expected).test(element):deepEqual(expected,element);});},"deepEquals([".concat(iterableToString(expectation),"])"));};createMatcher.array.startsWith=function(expectation){return createMatcher(function(actual){return typeOf(actual)==="array"&&every(expectation,function(expectedElement,index){return actual[index]===expectedElement;});},"startsWith([".concat(iterableToString(expectation),"])"));};createMatcher.array.endsWith=function(expectation){return createMatcher(function(actual){// This indicates the index in which we should start matching var offset=actual.length-expectation.length;return typeOf(actual)==="array"&&every(expectation,function(expectedElement,index){return actual[offset+index]===expectedElement;});},"endsWith([".concat(iterableToString(expectation),"])"));};createMatcher.array.contains=function(expectation){return createMatcher(function(actual){return typeOf(actual)==="array"&&every(expectation,function(expectedElement){return arrayIndexOf(actual,expectedElement)!==-1;});},"contains([".concat(iterableToString(expectation),"])"));};createMatcher.map=createMatcher.typeOf("map");createMatcher.map.deepEquals=function mapDeepEquals(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item var sameLength=actual.size===expectation.size;return typeOf(actual)==="map"&&sameLength&&every(actual,function(element,key){return expectation.has(key)&&expectation.get(key)===element;});},"deepEquals(Map[".concat(iterableToString(expectation),"])"));};createMatcher.map.contains=function mapContains(expectation){return createMatcher(function(actual){return typeOf(actual)==="map"&&every(expectation,function(element,key){return actual.has(key)&&actual.get(key)===element;});},"contains(Map[".concat(iterableToString(expectation),"])"));};createMatcher.set=createMatcher.typeOf("set");createMatcher.set.deepEquals=function setDeepEquals(expectation){return createMatcher(function(actual){// Comparing lengths is the fastest way to spot a difference before iterating through every item @@ -1038,7 +16941,7 @@ return function deepEqual(actualObj,expectationObj,actualPath,expectationPath){// If both are matchers they must be the same instance in order to be // considered equal If we didn't do that we would end up running one // matcher against the other - if(match&&match.isMatcher(expectationObj)){if(match.isMatcher(actualObj)){return actualObj===expectationObj;}return expectationObj.test(actualObj);}var actualType=_typeof(actualObj);var expectationType=_typeof(expectationObj);if(actualObj===expectationObj||isNaN(actualObj)||isNaN(expectationObj)||actualObj===null||expectationObj===null||actualObj===undefined||expectationObj===undefined||actualType!=="object"||expectationType!=="object"){return identical(actualObj,expectationObj);}// Elements are only equal if identical(expected, actual) + if(match&&match.isMatcher(expectationObj)){if(match.isMatcher(actualObj)){return actualObj===expectationObj;}return expectationObj.test(actualObj);}var actualType=_typeof$1(actualObj);var expectationType=_typeof$1(expectationObj);if(actualObj===expectationObj||isNaN(actualObj)||isNaN(expectationObj)||actualObj===null||expectationObj===null||actualObj===undefined||expectationObj===undefined||actualType!=="object"||expectationType!=="object"){return identical(actualObj,expectationObj);}// Elements are only equal if identical(expected, actual) if(isElement(actualObj)||isElement(expectationObj)){return false;}var isActualDate=isDate(actualObj);var isExpectationDate=isDate(expectationObj);if(isActualDate||isExpectationDate){if(!isActualDate||!isExpectationDate||getTime.call(actualObj)!==getTime.call(expectationObj)){return false;}}if(actualObj instanceof RegExp&&expectationObj instanceof RegExp){if(valueToString(actualObj)!==valueToString(expectationObj)){return false;}}if(actualObj instanceof Promise&&expectationObj instanceof Promise){return actualObj===expectationObj;}if(actualObj instanceof Error&&expectationObj instanceof Error){return actualObj===expectationObj;}var actualClass=getClass(actualObj);var expectationClass=getClass(expectationObj);var actualKeys=keys(actualObj);var expectationKeys=keys(expectationObj);var actualName=className(actualObj);var expectationName=className(expectationObj);var expectationSymbols=typeOf(getOwnPropertySymbols)==="function"?getOwnPropertySymbols(expectationObj):/* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */[];var expectationKeysAndSymbols=concat(expectationKeys,expectationSymbols);if(isArguments(actualObj)||isArguments(expectationObj)){if(actualObj.length!==expectationObj.length){return false;}}else {if(actualType!==expectationType||actualClass!==expectationClass||actualKeys.length!==expectationKeys.length||actualName&&expectationName&&actualName!==expectationName){return false;}}if(isSet(actualObj)||isSet(expectationObj)){if(!isSet(actualObj)||!isSet(expectationObj)||actualObj.size!==expectationObj.size){return false;}return isSubset(actualObj,expectationObj,deepEqual);}if(isMap(actualObj)||isMap(expectationObj)){if(!isMap(actualObj)||!isMap(expectationObj)||actualObj.size!==expectationObj.size){return false;}var mapsDeeplyEqual=true;mapForEach(actualObj,function(value,key){mapsDeeplyEqual=mapsDeeplyEqual&&deepEqualCyclic(value,expectationObj.get(key));});return mapsDeeplyEqual;}// jQuery objects have iteration protocols // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols // But, they don't work well with the implementation concerning iterables below, @@ -1115,7 +17018,7 @@ * @param {*} val - A value to examine * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise */function isIterable(val){// checks for null and undefined - if(_typeof(val)!=="object"){return false;}return typeof val[Symbol.iterator]==="function";}module.exports=isIterable;},{}],80:[function(require,module,exports){/** + if(_typeof$1(val)!=="object"){return false;}return typeof val[Symbol.iterator]==="function";}module.exports=isIterable;},{}],80:[function(require,module,exports){/** * Returns `true` when `value` is a Map * * @param {*} value A value to examine @@ -1150,7 +17053,7 @@ * @private * @param {object} value The object to examine * @returns {boolean} `true` when the object is a non-specialised object - */function isObject(value){return _typeof(value)==="object"&&value!==null&&// none of these are collection objects, so we can return false + */function isObject(value){return _typeof$1(value)==="object"&&value!==null&&// none of these are collection objects, so we can return false !(value instanceof Boolean)&&!(value instanceof Date)&&!(value instanceof Error)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String);}module.exports=isObject;},{}],84:[function(require,module,exports){/** * Returns `true` when the argument is an instance of Set, `false` otherwise * @@ -1209,7 +17112,7 @@ * @param {object} object The object candidate to match * @param {object} matcherOrValue A matcher or value to match against * @returns {boolean} true when `object` matches `matcherOrValue` - */function match(object,matcherOrValue){if(matcherOrValue&&typeof matcherOrValue.test==="function"){return matcherOrValue.test(object);}switch(type(matcherOrValue)){case"bigint":case"boolean":case"number":case"symbol":return matcherOrValue===object;case"function":return matcherOrValue(object)===true;case"string":var notNull=typeof object==="string"||Boolean(object);return notNull&&indexOf(valueToString(object).toLowerCase(),matcherOrValue.toLowerCase())>=0;case"null":return object===null;case"undefined":return typeof object==="undefined";case"Date":/* istanbul ignore else */if(type(object)==="Date"){return object.getTime()===matcherOrValue.getTime();}/* istanbul ignore next: this is basically the rest of the function, which is covered */break;case"Array":case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":return isArrayType(matcherOrValue)&&arrayContains(object,matcherOrValue,match);case"Map":/* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/if(!engineCanCompareMaps){throw new Error("The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances");}return type(object)==="Map"&&arrayContains(Array.from(object),Array.from(matcherOrValue),match);}switch(type(object)){case"null":return false;case"Set":return isSubset(matcherOrValue,object,match);}/* istanbul ignore else */if(matcherOrValue&&_typeof(matcherOrValue)==="object"){if(matcherOrValue===object){return true;}if(_typeof(object)!=="object"){return false;}var prop;// eslint-disable-next-line guard-for-in + */function match(object,matcherOrValue){if(matcherOrValue&&typeof matcherOrValue.test==="function"){return matcherOrValue.test(object);}switch(type(matcherOrValue)){case"bigint":case"boolean":case"number":case"symbol":return matcherOrValue===object;case"function":return matcherOrValue(object)===true;case"string":var notNull=typeof object==="string"||Boolean(object);return notNull&&indexOf(valueToString(object).toLowerCase(),matcherOrValue.toLowerCase())>=0;case"null":return object===null;case"undefined":return typeof object==="undefined";case"Date":/* istanbul ignore else */if(type(object)==="Date"){return object.getTime()===matcherOrValue.getTime();}/* istanbul ignore next: this is basically the rest of the function, which is covered */break;case"Array":case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":return isArrayType(matcherOrValue)&&arrayContains(object,matcherOrValue,match);case"Map":/* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/if(!engineCanCompareMaps){throw new Error("The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances");}return type(object)==="Map"&&arrayContains(Array.from(object),Array.from(matcherOrValue),match);}switch(type(object)){case"null":return false;case"Set":return isSubset(matcherOrValue,object,match);}/* istanbul ignore else */if(matcherOrValue&&_typeof$1(matcherOrValue)==="object"){if(matcherOrValue===object){return true;}if(_typeof$1(object)!=="object"){return false;}var prop;// eslint-disable-next-line guard-for-in for(prop in matcherOrValue){var value=object[prop];if(typeof value==="undefined"&&typeof object.getAttribute==="function"){value=object.getAttribute(prop);}if(matcherOrValue[prop]===null||typeof matcherOrValue[prop]==="undefined"){if(value!==matcherOrValue[prop]){return false;}}else if(typeof value==="undefined"||!deepEqual(value,matcherOrValue[prop])){return false;}}return true;}/* istanbul ignore next */throw new Error("Matcher was an unknown or unsupported type");}/* eslint-enable complexity */forEach(Object.keys(createMatcher),function(key){match[key]=createMatcher[key];});module.exports=match;},{"./create-matcher":63,"./deep-equal":72,"./is-array-type":76,"./is-subset":85,"@sinonjs/commons":95,"type-detect":151}],88:[function(require,module,exports){/** * @module samsam */var identical=require("./identical");var isArguments=require("./is-arguments");var isElement=require("./is-element");var isNegZero=require("./is-neg-zero");var isSet=require("./is-set");var isMap=require("./is-map");var match=require("./match");var deepEqualCyclic=require("./deep-equal").use(match);var createMatcher=require("./create-matcher");module.exports={createMatcher:createMatcher,deepEqual:deepEqualCyclic,identical:identical,isArguments:isArguments,isElement:isElement,isMap:isMap,isNegZero:isNegZero,isSet:isSet,match:match};},{"./create-matcher":63,"./deep-equal":72,"./identical":74,"./is-arguments":75,"./is-element":78,"./is-map":80,"./is-neg-zero":82,"./is-set":84,"./match":87}],89:[function(require,module,exports){arguments[4][42][0].apply(exports,arguments);},{"./prototypes/array":97,"dup":42}],90:[function(require,module,exports){arguments[4][43][0].apply(exports,arguments);},{"./function-name":93,"dup":43}],91:[function(require,module,exports){arguments[4][44][0].apply(exports,arguments);},{"dup":44}],92:[function(require,module,exports){arguments[4][45][0].apply(exports,arguments);},{"dup":45}],93:[function(require,module,exports){arguments[4][46][0].apply(exports,arguments);},{"dup":46}],94:[function(require,module,exports){arguments[4][47][0].apply(exports,arguments);},{"dup":47}],95:[function(require,module,exports){arguments[4][48][0].apply(exports,arguments);},{"./called-in-order":89,"./class-name":90,"./deprecated":91,"./every":92,"./function-name":93,"./global":94,"./order-by-first-call":96,"./prototypes":100,"./type-of":106,"./value-to-string":107,"dup":48}],96:[function(require,module,exports){arguments[4][49][0].apply(exports,arguments);},{"./prototypes/array":97,"dup":49}],97:[function(require,module,exports){arguments[4][50][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":50}],98:[function(require,module,exports){arguments[4][51][0].apply(exports,arguments);},{"./throws-on-proto":105,"dup":51}],99:[function(require,module,exports){arguments[4][52][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":52}],100:[function(require,module,exports){arguments[4][53][0].apply(exports,arguments);},{"./array":97,"./function":99,"./map":101,"./object":102,"./set":103,"./string":104,"dup":53}],101:[function(require,module,exports){arguments[4][54][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":54}],102:[function(require,module,exports){arguments[4][55][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":55}],103:[function(require,module,exports){arguments[4][56][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":56}],104:[function(require,module,exports){arguments[4][57][0].apply(exports,arguments);},{"./copy-prototype-methods":98,"dup":57}],105:[function(require,module,exports){arguments[4][58][0].apply(exports,arguments);},{"dup":58}],106:[function(require,module,exports){arguments[4][59][0].apply(exports,arguments);},{"dup":59,"type-detect":151}],107:[function(require,module,exports){arguments[4][60][0].apply(exports,arguments);},{"dup":60}],108:[function(require,module,exports){// This is free and unencumbered software released into the public domain. @@ -1438,7 +17341,7 @@ * @param {BufferSource=} input The buffer of bytes to decode. * @param {Object=} options * @return {string} The decoded string. - */TextDecoder.prototype.decode=function decode(input,options){var bytes;if(_typeof(input)==='object'&&input instanceof ArrayBuffer){bytes=new Uint8Array(input);}else if(_typeof(input)==='object'&&'buffer'in input&&input.buffer instanceof ArrayBuffer){bytes=new Uint8Array(input.buffer,input.byteOffset,input.byteLength);}else {bytes=new Uint8Array(0);}options=ToDictionary(options);// 1. If the do not flush flag is unset, set decoder to a new + */TextDecoder.prototype.decode=function decode(input,options){var bytes;if(_typeof$1(input)==='object'&&input instanceof ArrayBuffer){bytes=new Uint8Array(input);}else if(_typeof$1(input)==='object'&&'buffer'in input&&input.buffer instanceof ArrayBuffer){bytes=new Uint8Array(input.buffer,input.byteOffset,input.byteLength);}else {bytes=new Uint8Array(0);}options=ToDictionary(options);// 1. If the do not flush flag is unset, set decoder to a new // encoding's decoder, set stream to a new stream, and unset the // BOM seen flag. if(!this._do_not_flush){this._decoder=decoders[this._encoding.name]({fatal:this._error_mode==='fatal'});this._BOMseen=false;}// 2. If options's stream is true, set the do not flush flag, and @@ -2271,7 +18174,7 @@ // is `undefined`, take a pure object instead })(this||{});},{"./encoding-indexes.js":109}],111:[function(require,module,exports){if(typeof Object.create==='function'){// implementation from standard node.js 'util' module module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:false,writable:true,configurable:true}});};}else {// old school shim for old browsers - module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function TempCtor(){};TempCtor.prototype=superCtor.prototype;ctor.prototype=new TempCtor();ctor.prototype.constructor=ctor;};}},{}],112:[function(require,module,exports){module.exports=function isBuffer(arg){return arg&&_typeof(arg)==='object'&&typeof arg.copy==='function'&&typeof arg.fill==='function'&&typeof arg.readUInt8==='function';};},{}],113:[function(require,module,exports){// Copyright Joyent, Inc. and other Node contributors. + module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function TempCtor(){};TempCtor.prototype=superCtor.prototype;ctor.prototype=new TempCtor();ctor.prototype.constructor=ctor;};}},{}],112:[function(require,module,exports){module.exports=function isBuffer(arg){return arg&&_typeof$1(arg)==='object'&&typeof arg.copy==='function'&&typeof arg.fill==='function'&&typeof arg.readUInt8==='function';};},{}],113:[function(require,module,exports){// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the @@ -2299,1138 +18202,7867 @@ * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ /* legacy: obj, showHidden, depth, colors*/function inspect(obj,opts){// default options - var ctx={seen:[],stylize:stylizeNoColor};// legacy... - if(arguments.length>=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){// legacy... - ctx.showHidden=opts;}else if(opts){// got an "options" object - exports._extend(ctx,opts);}// set default options - if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth);}exports.inspect=inspect;// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics - inspect.colors={'bold':[1,22],'italic':[3,23],'underline':[4,24],'inverse':[7,27],'white':[37,39],'grey':[90,39],'black':[30,39],'blue':[34,39],'cyan':[36,39],'green':[32,39],'magenta':[35,39],'red':[31,39],'yellow':[33,39]};// Don't use 'blue' not visible on cmd.exe - inspect.styles={'special':'cyan','number':'yellow','boolean':'yellow','undefined':'grey','null':'bold','string':'green','date':'magenta',// "name": intentionally not styling - 'regexp':'red'};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return "\x1B["+inspect.colors[style][0]+'m'+str+"\x1B["+inspect.colors[style][1]+'m';}else {return str;}}function stylizeNoColor(str,styleType){return str;}function arrayToHash(array){var hash={};array.forEach(function(val,idx){hash[val]=true;});return hash;}function formatValue(ctx,value,recurseTimes){// Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if(ctx.customInspect&&value&&isFunction(value.inspect)&&// Filter out the util module, it's inspect function is special - value.inspect!==exports.inspect&&// Also filter out any prototype objects using the circular check. - !(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes);}return ret;}// Primitive types cannot have properties - var primitive=formatPrimitive(ctx,value);if(primitive){return primitive;}// Look up the keys of the object. - var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value);}// IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if(isError(value)&&(keys.indexOf('message')>=0||keys.indexOf('description')>=0)){return formatError(value);}// Some type of object without properties can be shortcutted. - if(keys.length===0){if(isFunction(value)){var name=value.name?': '+value.name:'';return ctx.stylize('[Function'+name+']','special');}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),'date');}if(isError(value)){return formatError(value);}}var base='',array=false,braces=['{','}'];// Make Array say that they are Array - if(isArray(value)){array=true;braces=['[',']'];}// Make functions say that they are functions - if(isFunction(value)){var n=value.name?': '+value.name:'';base=' [Function'+n+']';}// Make RegExps say that they are RegExps - if(isRegExp(value)){base=' '+RegExp.prototype.toString.call(value);}// Make dates with properties first say the date - if(isDate(value)){base=' '+Date.prototype.toUTCString.call(value);}// Make error with message first say the error - if(isError(value)){base=' '+formatError(value);}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1];}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}else {return ctx.stylize('[Object]','special');}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys);}else {output=keys.map(function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array);});}ctx.seen.pop();return reduceToSingleString(output,base,braces);}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize('undefined','undefined');if(isString(value)){var simple='\''+JSON.stringify(value).replace(/^"|"$/g,'').replace(/'/g,"\\'").replace(/\\"/g,'"')+'\'';return ctx.stylize(simple,'string');}if(isNumber(value))return ctx.stylize(''+value,'number');if(isBoolean(value))return ctx.stylize(''+value,'boolean');// For some reason typeof null is "object", so special case here. - if(isNull(value))return ctx.stylize('null','null');}function formatError(value){return '['+Error.prototype.toString.call(value)+']';}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i-1){if(array){str=str.split('\n').map(function(line){return ' '+line;}).join('\n').substr(2);}else {str='\n'+str.split('\n').map(function(line){return ' '+line;}).join('\n');}}}else {str=ctx.stylize('[Circular]','special');}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str;}name=JSON.stringify(''+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,'name');}else {name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,'string');}}return name+': '+str;}function reduceToSingleString(output,base,braces){var length=output.reduce(function(prev,cur){if(cur.indexOf('\n')>=0);return prev+cur.replace(/\u001b\[\d\d?m/g,'').length+1;},0);if(length>60){return braces[0]+(base===''?'':base+'\n ')+' '+output.join(',\n ')+' '+braces[1];}return braces[0]+base+' '+output.join(', ')+' '+braces[1];}// NOTE: These type checking functions intentionally don't use `instanceof` - // because it is fragile and can be easily faked with `Object.create()`. - function isArray(ar){return Array.isArray(ar);}exports.isArray=isArray;function isBoolean(arg){return typeof arg==='boolean';}exports.isBoolean=isBoolean;function isNull(arg){return arg===null;}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null;}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==='number';}exports.isNumber=isNumber;function isString(arg){return typeof arg==='string';}exports.isString=isString;function isSymbol(arg){return _typeof(arg)==='symbol';}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0;}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==='[object RegExp]';}exports.isRegExp=isRegExp;function isObject(arg){return _typeof(arg)==='object'&&arg!==null;}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==='[object Date]';}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==='[object Error]'||e instanceof Error);}exports.isError=isError;function isFunction(arg){return typeof arg==='function';}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==='boolean'||typeof arg==='number'||typeof arg==='string'||_typeof(arg)==='symbol'||// ES6 symbol - typeof arg==='undefined';}exports.isPrimitive=isPrimitive;exports.isBuffer=require('./support/isBuffer');function objectToString(o){return Object.prototype.toString.call(o);}function pad(n){return n<10?'0'+n.toString(10):n.toString(10);}var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];// 26 Feb 16:19:34 - function timestamp(){var d=new Date();var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(':');return [d.getDate(),months[d.getMonth()],time].join(' ');}// log is just a thin wrapper to console.log that prepends a timestamp - exports.log=function(){console.log('%s - %s',timestamp(),exports.format.apply(exports,arguments));};/** - * Inherit the prototype methods from one constructor into another. + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ /* legacy: obj, showHidden, depth, colors*/function inspect(obj,opts){// default options + var ctx={seen:[],stylize:stylizeNoColor};// legacy... + if(arguments.length>=3)ctx.depth=arguments[2];if(arguments.length>=4)ctx.colors=arguments[3];if(isBoolean(opts)){// legacy... + ctx.showHidden=opts;}else if(opts){// got an "options" object + exports._extend(ctx,opts);}// set default options + if(isUndefined(ctx.showHidden))ctx.showHidden=false;if(isUndefined(ctx.depth))ctx.depth=2;if(isUndefined(ctx.colors))ctx.colors=false;if(isUndefined(ctx.customInspect))ctx.customInspect=true;if(ctx.colors)ctx.stylize=stylizeWithColor;return formatValue(ctx,obj,ctx.depth);}exports.inspect=inspect;// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors={'bold':[1,22],'italic':[3,23],'underline':[4,24],'inverse':[7,27],'white':[37,39],'grey':[90,39],'black':[30,39],'blue':[34,39],'cyan':[36,39],'green':[32,39],'magenta':[35,39],'red':[31,39],'yellow':[33,39]};// Don't use 'blue' not visible on cmd.exe + inspect.styles={'special':'cyan','number':'yellow','boolean':'yellow','undefined':'grey','null':'bold','string':'green','date':'magenta',// "name": intentionally not styling + 'regexp':'red'};function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];if(style){return "\x1B["+inspect.colors[style][0]+'m'+str+"\x1B["+inspect.colors[style][1]+'m';}else {return str;}}function stylizeNoColor(str,styleType){return str;}function arrayToHash(array){var hash={};array.forEach(function(val,idx){hash[val]=true;});return hash;}function formatValue(ctx,value,recurseTimes){// Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if(ctx.customInspect&&value&&isFunction(value.inspect)&&// Filter out the util module, it's inspect function is special + value.inspect!==exports.inspect&&// Also filter out any prototype objects using the circular check. + !(value.constructor&&value.constructor.prototype===value)){var ret=value.inspect(recurseTimes,ctx);if(!isString(ret)){ret=formatValue(ctx,ret,recurseTimes);}return ret;}// Primitive types cannot have properties + var primitive=formatPrimitive(ctx,value);if(primitive){return primitive;}// Look up the keys of the object. + var keys=Object.keys(value);var visibleKeys=arrayToHash(keys);if(ctx.showHidden){keys=Object.getOwnPropertyNames(value);}// IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if(isError(value)&&(keys.indexOf('message')>=0||keys.indexOf('description')>=0)){return formatError(value);}// Some type of object without properties can be shortcutted. + if(keys.length===0){if(isFunction(value)){var name=value.name?': '+value.name:'';return ctx.stylize('[Function'+name+']','special');}if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}if(isDate(value)){return ctx.stylize(Date.prototype.toString.call(value),'date');}if(isError(value)){return formatError(value);}}var base='',array=false,braces=['{','}'];// Make Array say that they are Array + if(isArray(value)){array=true;braces=['[',']'];}// Make functions say that they are functions + if(isFunction(value)){var n=value.name?': '+value.name:'';base=' [Function'+n+']';}// Make RegExps say that they are RegExps + if(isRegExp(value)){base=' '+RegExp.prototype.toString.call(value);}// Make dates with properties first say the date + if(isDate(value)){base=' '+Date.prototype.toUTCString.call(value);}// Make error with message first say the error + if(isError(value)){base=' '+formatError(value);}if(keys.length===0&&(!array||value.length==0)){return braces[0]+base+braces[1];}if(recurseTimes<0){if(isRegExp(value)){return ctx.stylize(RegExp.prototype.toString.call(value),'regexp');}else {return ctx.stylize('[Object]','special');}}ctx.seen.push(value);var output;if(array){output=formatArray(ctx,value,recurseTimes,visibleKeys,keys);}else {output=keys.map(function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array);});}ctx.seen.pop();return reduceToSingleString(output,base,braces);}function formatPrimitive(ctx,value){if(isUndefined(value))return ctx.stylize('undefined','undefined');if(isString(value)){var simple='\''+JSON.stringify(value).replace(/^"|"$/g,'').replace(/'/g,"\\'").replace(/\\"/g,'"')+'\'';return ctx.stylize(simple,'string');}if(isNumber(value))return ctx.stylize(''+value,'number');if(isBoolean(value))return ctx.stylize(''+value,'boolean');// For some reason typeof null is "object", so special case here. + if(isNull(value))return ctx.stylize('null','null');}function formatError(value){return '['+Error.prototype.toString.call(value)+']';}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){var output=[];for(var i=0,l=value.length;i-1){if(array){str=str.split('\n').map(function(line){return ' '+line;}).join('\n').substr(2);}else {str='\n'+str.split('\n').map(function(line){return ' '+line;}).join('\n');}}}else {str=ctx.stylize('[Circular]','special');}}if(isUndefined(name)){if(array&&key.match(/^\d+$/)){return str;}name=JSON.stringify(''+key);if(name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)){name=name.substr(1,name.length-2);name=ctx.stylize(name,'name');}else {name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");name=ctx.stylize(name,'string');}}return name+': '+str;}function reduceToSingleString(output,base,braces){var length=output.reduce(function(prev,cur){if(cur.indexOf('\n')>=0);return prev+cur.replace(/\u001b\[\d\d?m/g,'').length+1;},0);if(length>60){return braces[0]+(base===''?'':base+'\n ')+' '+output.join(',\n ')+' '+braces[1];}return braces[0]+base+' '+output.join(', ')+' '+braces[1];}// NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar){return Array.isArray(ar);}exports.isArray=isArray;function isBoolean(arg){return typeof arg==='boolean';}exports.isBoolean=isBoolean;function isNull(arg){return arg===null;}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null;}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg==='number';}exports.isNumber=isNumber;function isString(arg){return typeof arg==='string';}exports.isString=isString;function isSymbol(arg){return _typeof$1(arg)==='symbol';}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0;}exports.isUndefined=isUndefined;function isRegExp(re){return isObject(re)&&objectToString(re)==='[object RegExp]';}exports.isRegExp=isRegExp;function isObject(arg){return _typeof$1(arg)==='object'&&arg!==null;}exports.isObject=isObject;function isDate(d){return isObject(d)&&objectToString(d)==='[object Date]';}exports.isDate=isDate;function isError(e){return isObject(e)&&(objectToString(e)==='[object Error]'||e instanceof Error);}exports.isError=isError;function isFunction(arg){return typeof arg==='function';}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg==='boolean'||typeof arg==='number'||typeof arg==='string'||_typeof$1(arg)==='symbol'||// ES6 symbol + typeof arg==='undefined';}exports.isPrimitive=isPrimitive;exports.isBuffer=require('./support/isBuffer');function objectToString(o){return Object.prototype.toString.call(o);}function pad(n){return n<10?'0'+n.toString(10):n.toString(10);}var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];// 26 Feb 16:19:34 + function timestamp(){var d=new Date();var time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(':');return [d.getDate(),months[d.getMonth()],time].join(' ');}// log is just a thin wrapper to console.log that prepends a timestamp + exports.log=function(){console.log('%s - %s',timestamp(),exports.format.apply(exports,arguments));};/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */exports.inherits=require('inherits');exports._extend=function(origin,add){// Don't do anything if add isn't an object + if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]];}return origin;};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);}},{"./support/isBuffer":112,"inherits":111}],114:[function(require,module,exports){/*! + + diff v5.1.0 + + Software License Agreement (BSD License) + + Copyright (c) 2009-2015, Kevin Decker + + All rights reserved. + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + @license + */(function(global,factory){_typeof$1(exports)==='object'&&typeof module!=='undefined'?factory(exports):(global=global||self,factory(global.Diff={}));})(this,function(exports){function Diff(){}Diff.prototype={diff:function diff(oldString,newString){var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var callback=options.callback;if(typeof options==='function'){callback=options;options={};}this.options=options;var self=this;function done(value){if(callback){setTimeout(function(){callback(undefined,value);},0);return true;}else {return value;}}// Allow subclasses to massage the input prior to running + oldString=this.castInput(oldString);newString=this.castInput(newString);oldString=this.removeEmpty(this.tokenize(oldString));newString=this.removeEmpty(this.tokenize(newString));var newLen=newString.length,oldLen=oldString.length;var editLength=1;var maxEditLength=newLen+oldLen;if(options.maxEditLength){maxEditLength=Math.min(maxEditLength,options.maxEditLength);}var bestPath=[{newPos:-1,components:[]}];// Seed editLength = 0, i.e. the content starts with the same values + var oldPos=this.extractCommon(bestPath[0],newString,oldString,0);if(bestPath[0].newPos+1>=newLen&&oldPos+1>=oldLen){// Identity per the equality and tokenizer + return done([{value:this.join(newString),count:newString.length}]);}// Main worker method. checks all permutations of a given edit length for acceptance. + function execEditLength(){for(var diagonalPath=-1*editLength;diagonalPath<=editLength;diagonalPath+=2){var basePath=void 0;var addPath=bestPath[diagonalPath-1],removePath=bestPath[diagonalPath+1],_oldPos=(removePath?removePath.newPos:0)-diagonalPath;if(addPath){// No one else is going to attempt to use this value, clear it + bestPath[diagonalPath-1]=undefined;}var canAdd=addPath&&addPath.newPos+1=newLen&&_oldPos+1>=oldLen){return done(buildValues(self,basePath.components,newString,oldString,self.useLongestToken));}else {// Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath]=basePath;}}editLength++;}// Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced, or until the edit length exceeds options.maxEditLength (if given), + // in which case it will return undefined. + if(callback){(function exec(){setTimeout(function(){if(editLength>maxEditLength){return callback();}if(!execEditLength()){exec();}},0);})();}else {while(editLength<=maxEditLength){var ret=execEditLength();if(ret){return ret;}}}},pushComponent:function pushComponent(components,added,removed){var last=components[components.length-1];if(last&&last.added===added&&last.removed===removed){// We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length-1]={count:last.count+1,added:added,removed:removed};}else {components.push({count:1,added:added,removed:removed});}},extractCommon:function extractCommon(basePath,newString,oldString,diagonalPath){var newLen=newString.length,oldLen=oldString.length,newPos=basePath.newPos,oldPos=newPos-diagonalPath,commonCount=0;while(newPos+1value.length?oldValue:value;});component.value=diff.join(value);}else {component.value=diff.join(newString.slice(newPos,newPos+component.count));}newPos+=component.count;// Common case + if(!component.added){oldPos+=component.count;}}else {component.value=diff.join(oldString.slice(oldPos,oldPos+component.count));oldPos+=component.count;// Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + if(componentPos&&components[componentPos-1].added){var tmp=components[componentPos-1];components[componentPos-1]=components[componentPos];components[componentPos]=tmp;}}}// Special case handle for when one terminal is ignored (i.e. whitespace). + // For this case we merge the terminal into the prior string and drop the change. + // This is only available for string mode. + var lastComponent=components[componentLen-1];if(componentLen>1&&typeof lastComponent.value==='string'&&(lastComponent.added||lastComponent.removed)&&diff.equals('',lastComponent.value)){components[componentLen-2].value+=lastComponent.value;components.pop();}return components;}function clonePath(path){return {newPos:path.newPos,components:path.components.slice(0)};}var characterDiff=new Diff();function diffChars(oldStr,newStr,options){return characterDiff.diff(oldStr,newStr,options);}function generateOptions(options,defaults){if(typeof options==='function'){defaults.callback=options;}else if(options){for(var name in options){/* istanbul ignore else */if(options.hasOwnProperty(name)){defaults[name]=options[name];}}}return defaults;}// + // Ranges and exceptions: + // Latin-1 Supplement, 0080–00FF + // - U+00D7 × Multiplication sign + // - U+00F7 ÷ Division sign + // Latin Extended-A, 0100–017F + // Latin Extended-B, 0180–024F + // IPA Extensions, 0250–02AF + // Spacing Modifier Letters, 02B0–02FF + // - U+02C7 ˇ ˇ Caron + // - U+02D8 ˘ ˘ Breve + // - U+02D9 ˙ ˙ Dot Above + // - U+02DA ˚ ˚ Ring Above + // - U+02DB ˛ ˛ Ogonek + // - U+02DC ˜ ˜ Small Tilde + // - U+02DD ˝ ˝ Double Acute Accent + // Latin Extended Additional, 1E00–1EFF + var extendedWordChars=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;var reWhitespace=/\S/;var wordDiff=new Diff();wordDiff.equals=function(left,right){if(this.options.ignoreCase){left=left.toLowerCase();right=right.toLowerCase();}return left===right||this.options.ignoreWhitespace&&!reWhitespace.test(left)&&!reWhitespace.test(right);};wordDiff.tokenize=function(value){// All whitespace symbols except newline group into one token, each newline - in separate token + var tokens=value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);// Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + for(var i=0;iarr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:{};var diffstr=uniDiff.split(/\r\n|[\n\v\f\r\x85]/),delimiters=uniDiff.match(/\r\n|[\n\v\f\r\x85]/g)||[],list=[],i=0;function parseIndex(){var index={};list.push(index);// Parse diff metadata + while(i2&&arguments[2]!==undefined?arguments[2]:{};if(typeof uniDiff==='string'){uniDiff=parsePatch(uniDiff);}if(Array.isArray(uniDiff)){if(uniDiff.length>1){throw new Error('applyPatch only works with a single input.');}uniDiff=uniDiff[0];}// Apply the diff to the input + var lines=source.split(/\r\n|[\n\v\f\r\x85]/),delimiters=source.match(/\r\n|[\n\v\f\r\x85]/g)||[],hunks=uniDiff.hunks,compareLine=options.compareLine||function(lineNumber,line,operation,patchContent){return line===patchContent;},errorCount=0,fuzzFactor=options.fuzzFactor||0,minLine=0,offset=0,removeEOFNL,addEOFNL;/** + * Checks if the hunk exactly fits on the provided location + */function hunkFits(hunk,toPos){for(var j=0;j0?line[0]:' ',content=line.length>0?line.substr(1):line;if(operation===' '||operation==='-'){// Context sanity check + if(!compareLine(toPos+1,lines[toPos],operation,content)){errorCount++;if(errorCount>fuzzFactor){return false;}}toPos++;}}return true;}// Search best fit offsets for each hunk based on the previous ones + for(var i=0;i0?line[0]:' ',content=line.length>0?line.substr(1):line,delimiter=_hunk.linedelimiters[j];if(operation===' '){_toPos++;}else if(operation==='-'){lines.splice(_toPos,1);delimiters.splice(_toPos,1);/* istanbul ignore else */}else if(operation==='+'){lines.splice(_toPos,0,content);delimiters.splice(_toPos,0,delimiter);_toPos++;}else if(operation==='\\'){var previousOperation=_hunk.lines[j-1]?_hunk.lines[j-1][0]:null;if(previousOperation==='+'){removeEOFNL=true;}else if(previousOperation==='-'){addEOFNL=true;}}}}// Handle EOFNL insertion/removal + if(removeEOFNL){while(!lines[lines.length-1]){lines.pop();delimiters.pop();}}else if(addEOFNL){lines.push('');delimiters.push('\n');}for(var _k=0;_k0?contextLines(prev.lines.slice(-options.context)):[];oldRangeStart-=curRange.length;newRangeStart-=curRange.length;}}// Output our changes + (_curRange=curRange).push.apply(_curRange,_toConsumableArray(lines.map(function(entry){return (current.added?'+':'-')+entry;})));// Track the updated file position + if(current.added){newLine+=lines.length;}else {oldLine+=lines.length;}}else {// Identical context lines. Track line changes + if(oldRangeStart){// Close out any changes that have been output (or join overlapping) + if(lines.length<=options.context*2&&i=diff.length-2&&lines.length<=options.context){// EOF is inside this hunk + var oldEOFNewline=/\n$/.test(oldStr);var newEOFNewline=/\n$/.test(newStr);var noNlBeforeAdds=lines.length==0&&curRange.length>hunk.oldLines;if(!oldEOFNewline&&noNlBeforeAdds&&oldStr.length>0){// special case: old has no eol and no trailing context; no-nl can end up before adds + // however, if the old file is empty, do not output the no-nl line + curRange.splice(hunk.oldLines,0,'\\ No newline at end of file');}if(!oldEOFNewline&&!noNlBeforeAdds||!newEOFNewline){curRange.push('\\ No newline at end of file');}}hunks.push(hunk);oldRangeStart=0;newRangeStart=0;curRange=[];}}oldLine+=lines.length;newLine+=lines.length;}};for(var i=0;iarray.length){return false;}for(var i=0;i');}else if(change.removed){ret.push('');}ret.push(escapeHTML(change.value));if(change.added){ret.push('');}else if(change.removed){ret.push('');}}return ret.join('');}function escapeHTML(s){var n=s;n=n.replace(/&/g,'&');n=n.replace(//g,'>');n=n.replace(/"/g,'"');return n;}exports.Diff=Diff;exports.applyPatch=applyPatch;exports.applyPatches=applyPatches;exports.canonicalize=canonicalize;exports.convertChangesToDMP=convertChangesToDMP;exports.convertChangesToXML=convertChangesToXML;exports.createPatch=createPatch;exports.createTwoFilesPatch=createTwoFilesPatch;exports.diffArrays=diffArrays;exports.diffChars=diffChars;exports.diffCss=diffCss;exports.diffJson=diffJson;exports.diffLines=diffLines;exports.diffSentences=diffSentences;exports.diffTrimmedLines=diffTrimmedLines;exports.diffWords=diffWords;exports.diffWordsWithSpace=diffWordsWithSpace;exports.merge=merge;exports.parsePatch=parsePatch;exports.structuredPatch=structuredPatch;Object.defineProperty(exports,'__esModule',{value:true});});},{}],115:[function(require,module,exports){module.exports=extend;/* + var obj = {a: 3, b: 5}; + extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 4, b: 5, c: 8} + + var obj = {a: 3, b: 5}; + extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 3, b: 5} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3]} + + extend({a: 4, b: 5}); // {a: 4, b: 5} + extend({a: 4, b: 5}, 3); {a: 4, b: 5} + extend({a: 4, b: 5}, true); {a: 4, b: 5} + extend('hello', {a: 4, b: 5}); // throws + extend(3, {a: 4, b: 5}); // throws + */function extend(/* [deep], obj1, obj2, [objn] */){var args=[].slice.call(arguments);var deep=false;if(typeof args[0]=='boolean'){deep=args.shift();}var result=args[0];if(isUnextendable(result)){throw new Error('extendee must be an object');}var extenders=args.slice(1);var len=extenders.length;for(var i=0;i + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ /** Used as the `TypeError` message for "Functions" methods. */var FUNC_ERROR_TEXT='Expected a function';/** Used to stand-in for `undefined` hash values. */var HASH_UNDEFINED='__lodash_hash_undefined__';/** Used as references for various `Number` constants. */var INFINITY=1/0;/** `Object#toString` result references. */var funcTag='[object Function]',genTag='[object GeneratorFunction]',symbolTag='[object Symbol]';/** Used to match property names within property paths. */var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,reLeadingDot=/^\./,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */var reRegExpChar=/[\\^$.*+?()[\]{}|]/g;/** Used to match backslashes in property paths. */var reEscapeChar=/\\(\\)?/g;/** Used to detect host constructors (Safari). */var reIsHostCtor=/^\[object .+?Constructor\]$/;/** Detect free variable `global` from Node.js. */var freeGlobal=_typeof$1(commonjsGlobal)=='object'&&commonjsGlobal&&commonjsGlobal.Object===Object&&commonjsGlobal;/** Detect free variable `self`. */var freeSelf=(typeof self==="undefined"?"undefined":_typeof$1(self))=='object'&&self&&self.Object===Object&&self;/** Used as a reference to the global object. */var root=freeGlobal||freeSelf||Function('return this')();/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */function getValue(object,key){return object==null?undefined:object[key];}/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */function isHostObject(value){// Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result=false;if(value!=null&&typeof value.toString!='function'){try{result=!!(value+'');}catch(e){}}return result;}/** Used for built-in method references. */var arrayProto=Array.prototype,funcProto=Function.prototype,objectProto=Object.prototype;/** Used to detect overreaching core-js shims. */var coreJsData=root['__core-js_shared__'];/** Used to detect methods masquerading as native. */var maskSrcKey=function(){var uid=/[^.]+$/.exec(coreJsData&&coreJsData.keys&&coreJsData.keys.IE_PROTO||'');return uid?'Symbol(src)_1.'+uid:'';}();/** Used to resolve the decompiled source of functions. */var funcToString=funcProto.toString;/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty;/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */var objectToString=objectProto.toString;/** Used to detect if a method is native. */var reIsNative=RegExp('^'+funcToString.call(hasOwnProperty).replace(reRegExpChar,'\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,'$1.*?')+'$');/** Built-in value references. */var _Symbol3=root.Symbol,splice=arrayProto.splice;/* Built-in method references that are verified to be native. */var Map=getNative(root,'Map'),nativeCreate=getNative(Object,'create');/** Used to convert symbols to primitives and strings. */var symbolProto=_Symbol3?_Symbol3.prototype:undefined,symbolToString=symbolProto?symbolProto.toString:undefined;/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */function Hash(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index-1;}/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */function listCacheSet(key,value){var data=this.__data__,index=assocIndexOf(data,key);if(index<0){data.push([key,value]);}else {data[index][1]=value;}return this;}// Add methods to `ListCache`. + ListCache.prototype.clear=listCacheClear;ListCache.prototype['delete']=listCacheDelete;ListCache.prototype.get=listCacheGet;ListCache.prototype.has=listCacheHas;ListCache.prototype.set=listCacheSet;/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */function MapCache(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */function memoize(func,resolver){if(typeof func!='function'||resolver&&typeof resolver!='function'){throw new TypeError(FUNC_ERROR_TEXT);}var memoized=function memoized(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key);}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result;};memoized.cache=new(memoize.Cache||MapCache)();return memoized;}// Assign cache to `_.memoize`. + memoize.Cache=MapCache;/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */function eq(value,other){return value===other||value!==value&&other!==other;}/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */var isArray=Array.isArray;/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */function isFunction(value){// The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag=isObject(value)?objectToString.call(value):'';return tag==funcTag||tag==genTag;}/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */function isObject(value){var type=_typeof$1(value);return !!value&&(type=='object'||type=='function');}/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */function isObjectLike(value){return !!value&&_typeof$1(value)=='object';}/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */function isSymbol(value){return _typeof$1(value)=='symbol'||isObjectLike(value)&&objectToString.call(value)==symbolTag;}/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */function toString(value){return value==null?'':baseToString(value);}/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). + * _.get(object, 'a[0].b.c'); + * // => 3 * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */exports.inherits=require('inherits');exports._extend=function(origin,add){// Don't do anything if add isn't an object - if(!add||!isObject(add))return origin;var keys=Object.keys(add);var i=keys.length;while(i--){origin[keys[i]]=add[keys[i]];}return origin;};function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);}},{"./support/isBuffer":112,"inherits":111}],114:[function(require,module,exports){/*! - - diff v5.1.0 - - Software License Agreement (BSD License) - - Copyright (c) 2009-2015, Kevin Decker - - All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - - * Neither the name of Kevin Decker nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - @license - */(function(global,factory){_typeof(exports)==='object'&&typeof module!=='undefined'?factory(exports):(global=global||self,factory(global.Diff={}));})(this,function(exports){function Diff(){}Diff.prototype={diff:function diff(oldString,newString){var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var callback=options.callback;if(typeof options==='function'){callback=options;options={};}this.options=options;var self=this;function done(value){if(callback){setTimeout(function(){callback(undefined,value);},0);return true;}else {return value;}}// Allow subclasses to massage the input prior to running - oldString=this.castInput(oldString);newString=this.castInput(newString);oldString=this.removeEmpty(this.tokenize(oldString));newString=this.removeEmpty(this.tokenize(newString));var newLen=newString.length,oldLen=oldString.length;var editLength=1;var maxEditLength=newLen+oldLen;if(options.maxEditLength){maxEditLength=Math.min(maxEditLength,options.maxEditLength);}var bestPath=[{newPos:-1,components:[]}];// Seed editLength = 0, i.e. the content starts with the same values - var oldPos=this.extractCommon(bestPath[0],newString,oldString,0);if(bestPath[0].newPos+1>=newLen&&oldPos+1>=oldLen){// Identity per the equality and tokenizer - return done([{value:this.join(newString),count:newString.length}]);}// Main worker method. checks all permutations of a given edit length for acceptance. - function execEditLength(){for(var diagonalPath=-1*editLength;diagonalPath<=editLength;diagonalPath+=2){var basePath=void 0;var addPath=bestPath[diagonalPath-1],removePath=bestPath[diagonalPath+1],_oldPos=(removePath?removePath.newPos:0)-diagonalPath;if(addPath){// No one else is going to attempt to use this value, clear it - bestPath[diagonalPath-1]=undefined;}var canAdd=addPath&&addPath.newPos+1=newLen&&_oldPos+1>=oldLen){return done(buildValues(self,basePath.components,newString,oldString,self.useLongestToken));}else {// Otherwise track this path as a potential candidate and continue. - bestPath[diagonalPath]=basePath;}}editLength++;}// Performs the length of edit iteration. Is a bit fugly as this has to support the - // sync and async mode which is never fun. Loops over execEditLength until a value - // is produced, or until the edit length exceeds options.maxEditLength (if given), - // in which case it will return undefined. - if(callback){(function exec(){setTimeout(function(){if(editLength>maxEditLength){return callback();}if(!execEditLength()){exec();}},0);})();}else {while(editLength<=maxEditLength){var ret=execEditLength();if(ret){return ret;}}}},pushComponent:function pushComponent(components,added,removed){var last=components[components.length-1];if(last&&last.added===added&&last.removed===removed){// We need to clone here as the component clone operation is just - // as shallow array clone - components[components.length-1]={count:last.count+1,added:added,removed:removed};}else {components.push({count:1,added:added,removed:removed});}},extractCommon:function extractCommon(basePath,newString,oldString,diagonalPath){var newLen=newString.length,oldLen=oldString.length,newPos=basePath.newPos,oldPos=newPos-diagonalPath,commonCount=0;while(newPos+1value.length?oldValue:value;});component.value=diff.join(value);}else {component.value=diff.join(newString.slice(newPos,newPos+component.count));}newPos+=component.count;// Common case - if(!component.added){oldPos+=component.count;}}else {component.value=diff.join(oldString.slice(oldPos,oldPos+component.count));oldPos+=component.count;// Reverse add and remove so removes are output first to match common convention - // The diffing algorithm is tied to add then remove output and this is the simplest - // route to get the desired output with minimal overhead. - if(componentPos&&components[componentPos-1].added){var tmp=components[componentPos-1];components[componentPos-1]=components[componentPos];components[componentPos]=tmp;}}}// Special case handle for when one terminal is ignored (i.e. whitespace). - // For this case we merge the terminal into the prior string and drop the change. - // This is only available for string mode. - var lastComponent=components[componentLen-1];if(componentLen>1&&typeof lastComponent.value==='string'&&(lastComponent.added||lastComponent.removed)&&diff.equals('',lastComponent.value)){components[componentLen-2].value+=lastComponent.value;components.pop();}return components;}function clonePath(path){return {newPos:path.newPos,components:path.components.slice(0)};}var characterDiff=new Diff();function diffChars(oldStr,newStr,options){return characterDiff.diff(oldStr,newStr,options);}function generateOptions(options,defaults){if(typeof options==='function'){defaults.callback=options;}else if(options){for(var name in options){/* istanbul ignore else */if(options.hasOwnProperty(name)){defaults[name]=options[name];}}}return defaults;}// - // Ranges and exceptions: - // Latin-1 Supplement, 0080–00FF - // - U+00D7 × Multiplication sign - // - U+00F7 ÷ Division sign - // Latin Extended-A, 0100–017F - // Latin Extended-B, 0180–024F - // IPA Extensions, 0250–02AF - // Spacing Modifier Letters, 02B0–02FF - // - U+02C7 ˇ ˇ Caron - // - U+02D8 ˘ ˘ Breve - // - U+02D9 ˙ ˙ Dot Above - // - U+02DA ˚ ˚ Ring Above - // - U+02DB ˛ ˛ Ogonek - // - U+02DC ˜ ˜ Small Tilde - // - U+02DD ˝ ˝ Double Acute Accent - // Latin Extended Additional, 1E00–1EFF - var extendedWordChars=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;var reWhitespace=/\S/;var wordDiff=new Diff();wordDiff.equals=function(left,right){if(this.options.ignoreCase){left=left.toLowerCase();right=right.toLowerCase();}return left===right||this.options.ignoreWhitespace&&!reWhitespace.test(left)&&!reWhitespace.test(right);};wordDiff.tokenize=function(value){// All whitespace symbols except newline group into one token, each newline - in separate token - var tokens=value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);// Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. - for(var i=0;iarr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:{};var diffstr=uniDiff.split(/\r\n|[\n\v\f\r\x85]/),delimiters=uniDiff.match(/\r\n|[\n\v\f\r\x85]/g)||[],list=[],i=0;function parseIndex(){var index={};list.push(index);// Parse diff metadata - while(i2&&arguments[2]!==undefined?arguments[2]:{};if(typeof uniDiff==='string'){uniDiff=parsePatch(uniDiff);}if(Array.isArray(uniDiff)){if(uniDiff.length>1){throw new Error('applyPatch only works with a single input.');}uniDiff=uniDiff[0];}// Apply the diff to the input - var lines=source.split(/\r\n|[\n\v\f\r\x85]/),delimiters=source.match(/\r\n|[\n\v\f\r\x85]/g)||[],hunks=uniDiff.hunks,compareLine=options.compareLine||function(lineNumber,line,operation,patchContent){return line===patchContent;},errorCount=0,fuzzFactor=options.fuzzFactor||0,minLine=0,offset=0,removeEOFNL,addEOFNL;/** - * Checks if the hunk exactly fits on the provided location - */function hunkFits(hunk,toPos){for(var j=0;j0?line[0]:' ',content=line.length>0?line.substr(1):line;if(operation===' '||operation==='-'){// Context sanity check - if(!compareLine(toPos+1,lines[toPos],operation,content)){errorCount++;if(errorCount>fuzzFactor){return false;}}toPos++;}}return true;}// Search best fit offsets for each hunk based on the previous ones - for(var i=0;i0?line[0]:' ',content=line.length>0?line.substr(1):line,delimiter=_hunk.linedelimiters[j];if(operation===' '){_toPos++;}else if(operation==='-'){lines.splice(_toPos,1);delimiters.splice(_toPos,1);/* istanbul ignore else */}else if(operation==='+'){lines.splice(_toPos,0,content);delimiters.splice(_toPos,0,delimiter);_toPos++;}else if(operation==='\\'){var previousOperation=_hunk.lines[j-1]?_hunk.lines[j-1][0]:null;if(previousOperation==='+'){removeEOFNL=true;}else if(previousOperation==='-'){addEOFNL=true;}}}}// Handle EOFNL insertion/removal - if(removeEOFNL){while(!lines[lines.length-1]){lines.pop();delimiters.pop();}}else if(addEOFNL){lines.push('');delimiters.push('\n');}for(var _k=0;_k0?contextLines(prev.lines.slice(-options.context)):[];oldRangeStart-=curRange.length;newRangeStart-=curRange.length;}}// Output our changes - (_curRange=curRange).push.apply(_curRange,_toConsumableArray(lines.map(function(entry){return (current.added?'+':'-')+entry;})));// Track the updated file position - if(current.added){newLine+=lines.length;}else {oldLine+=lines.length;}}else {// Identical context lines. Track line changes - if(oldRangeStart){// Close out any changes that have been output (or join overlapping) - if(lines.length<=options.context*2&&i=diff.length-2&&lines.length<=options.context){// EOF is inside this hunk - var oldEOFNewline=/\n$/.test(oldStr);var newEOFNewline=/\n$/.test(newStr);var noNlBeforeAdds=lines.length==0&&curRange.length>hunk.oldLines;if(!oldEOFNewline&&noNlBeforeAdds&&oldStr.length>0){// special case: old has no eol and no trailing context; no-nl can end up before adds - // however, if the old file is empty, do not output the no-nl line - curRange.splice(hunk.oldLines,0,'\\ No newline at end of file');}if(!oldEOFNewline&&!noNlBeforeAdds||!newEOFNewline){curRange.push('\\ No newline at end of file');}}hunks.push(hunk);oldRangeStart=0;newRangeStart=0;curRange=[];}}oldLine+=lines.length;newLine+=lines.length;}};for(var i=0;iarray.length){return false;}for(var i=0;i');}else if(change.removed){ret.push('');}ret.push(escapeHTML(change.value));if(change.added){ret.push('');}else if(change.removed){ret.push('');}}return ret.join('');}function escapeHTML(s){var n=s;n=n.replace(/&/g,'&');n=n.replace(//g,'>');n=n.replace(/"/g,'"');return n;}exports.Diff=Diff;exports.applyPatch=applyPatch;exports.applyPatches=applyPatches;exports.canonicalize=canonicalize;exports.convertChangesToDMP=convertChangesToDMP;exports.convertChangesToXML=convertChangesToXML;exports.createPatch=createPatch;exports.createTwoFilesPatch=createTwoFilesPatch;exports.diffArrays=diffArrays;exports.diffChars=diffChars;exports.diffCss=diffCss;exports.diffJson=diffJson;exports.diffLines=diffLines;exports.diffSentences=diffSentences;exports.diffTrimmedLines=diffTrimmedLines;exports.diffWords=diffWords;exports.diffWordsWithSpace=diffWordsWithSpace;exports.merge=merge;exports.parsePatch=parsePatch;exports.structuredPatch=structuredPatch;Object.defineProperty(exports,'__esModule',{value:true});});},{}],115:[function(require,module,exports){module.exports=extend;/* - var obj = {a: 3, b: 5}; - extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} - obj; // {a: 4, b: 5, c: 8} - - var obj = {a: 3, b: 5}; - extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} - obj; // {a: 3, b: 5} - - var arr = [1, 2, 3]; - var obj = {a: 3, b: 5}; - extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} - arr.push(4); - obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} - - var arr = [1, 2, 3]; - var obj = {a: 3, b: 5}; - extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} - arr.push(4); - obj; // {a: 3, b: 5, c: [1, 2, 3]} - - extend({a: 4, b: 5}); // {a: 4, b: 5} - extend({a: 4, b: 5}, 3); {a: 4, b: 5} - extend({a: 4, b: 5}, true); {a: 4, b: 5} - extend('hello', {a: 4, b: 5}); // throws - extend(3, {a: 4, b: 5}); // throws - */function extend(/* [deep], obj1, obj2, [objn] */){var args=[].slice.call(arguments);var deep=false;if(typeof args[0]=='boolean'){deep=args.shift();}var result=args[0];if(isUnextendable(result)){throw new Error('extendee must be an object');}var extenders=args.slice(1);var len=extenders.length;for(var i=0;i - * Build: `lodash modularize exports="npm" -o ./` - * Copyright jQuery Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ /** Used as the `TypeError` message for "Functions" methods. */var FUNC_ERROR_TEXT='Expected a function';/** Used to stand-in for `undefined` hash values. */var HASH_UNDEFINED='__lodash_hash_undefined__';/** Used as references for various `Number` constants. */var INFINITY=1/0;/** `Object#toString` result references. */var funcTag='[object Function]',genTag='[object GeneratorFunction]',symbolTag='[object Symbol]';/** Used to match property names within property paths. */var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,reLeadingDot=/^\./,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;/** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */var reRegExpChar=/[\\^$.*+?()[\]{}|]/g;/** Used to match backslashes in property paths. */var reEscapeChar=/\\(\\)?/g;/** Used to detect host constructors (Safari). */var reIsHostCtor=/^\[object .+?Constructor\]$/;/** Detect free variable `global` from Node.js. */var freeGlobal=_typeof(commonjsGlobal)=='object'&&commonjsGlobal&&commonjsGlobal.Object===Object&&commonjsGlobal;/** Detect free variable `self`. */var freeSelf=(typeof self==="undefined"?"undefined":_typeof(self))=='object'&&self&&self.Object===Object&&self;/** Used as a reference to the global object. */var root=freeGlobal||freeSelf||Function('return this')();/** - * Gets the value at `key` of `object`. + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */function get(object,path,defaultValue){var result=object==null?undefined:baseGet(object,path);return result===undefined?defaultValue:result;}module.exports=get;},{}],117:[function(require,module,exports){// cache a reference to setTimeout, so that our reference won't be stubbed out + // when using fake timers and errors will still get logged + // https://github.com/cjohansen/Sinon.JS/issues/381 + var realSetTimeout=setTimeout;function configureLogger(config){// eslint-disable-next-line no-param-reassign + config=config||{};// Function which prints errors. + if(!config.hasOwnProperty("logger")){// eslint-disable-next-line no-empty-function + config.logger=function(){};}// When set to true, any errors logged will be thrown immediately; + // If set to false, the errors will be thrown in separate execution frame. + if(!config.hasOwnProperty("useImmediateExceptions")){config.useImmediateExceptions=true;}// wrap realSetTimeout with something we can stub in tests + if(!config.hasOwnProperty("setTimeout")){config.setTimeout=realSetTimeout;}return function logError(label,e){var msg="".concat(label," threw exception: ");var err={name:e.name||label,message:e.message||e.toString(),stack:e.stack};function throwLoggedError(){err.message=msg+err.message;throw err;}config.logger("".concat(msg,"[").concat(err.name,"] ").concat(err.message));if(err.stack){config.logger(err.stack);}if(config.useImmediateExceptions){throwLoggedError();}else {config.setTimeout(throwLoggedError,0);}};}module.exports=configureLogger;},{}],118:[function(require,module,exports){var Event=require("./event");function CustomEvent(type,customData,target){this.initEvent(type,false,false,target);this.detail=customData.detail||null;}CustomEvent.prototype=new Event();CustomEvent.prototype.constructor=CustomEvent;module.exports=CustomEvent;},{"./event":120}],119:[function(require,module,exports){function flattenOptions(options){if(options!==Object(options)){return {capture:Boolean(options),once:false,passive:false};}return {capture:Boolean(options.capture),once:Boolean(options.once),passive:Boolean(options.passive)};}function not(fn){return function(){return !fn.apply(this,arguments);};}function hasListenerFilter(listener,capture){return function(listenerSpec){return listenerSpec.capture===capture&&listenerSpec.listener===listener;};}var EventTarget={// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener + addEventListener:function addEventListener(event,listener,providedOptions){// 3. Let capture, passive, and once be the result of flattening more options. + // Flatten property before executing step 2, + // feture detection is usually based on registering handler with options object, + // that has getter defined + // addEventListener("load", () => {}, { + // get once() { supportsOnce = true; } + // }); + var options=flattenOptions(providedOptions);// 2. If callback is null, then return. + if(listener===null||listener===undefined){return;}this.eventListeners=this.eventListeners||{};this.eventListeners[event]=this.eventListeners[event]||[];// 4. If context object’s associated list of event listener + // does not contain an event listener whose type is type, + // callback is callback, and capture is capture, then append + // a new event listener to it, whose type is type, callback is + // callback, capture is capture, passive is passive, and once is once. + if(!this.eventListeners[event].some(hasListenerFilter(listener,options.capture))){this.eventListeners[event].push({listener:listener,capture:options.capture,once:options.once});}},// https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener + removeEventListener:function removeEventListener(event,listener,providedOptions){if(!this.eventListeners||!this.eventListeners[event]){return;}// 2. Let capture be the result of flattening options. + var options=flattenOptions(providedOptions);// 3. If there is an event listener in the associated list of + // event listeners whose type is type, callback is callback, + // and capture is capture, then set that event listener’s + // removed to true and remove it from the associated list of event listeners. + this.eventListeners[event]=this.eventListeners[event].filter(not(hasListenerFilter(listener,options.capture)));},dispatchEvent:function dispatchEvent(event){if(!this.eventListeners||!this.eventListeners[event.type]){return Boolean(event.defaultPrevented);}var self=this;var type=event.type;var listeners=self.eventListeners[type];// Remove listeners, that should be dispatched once + // before running dispatch loop to avoid nested dispatch issues + self.eventListeners[type]=listeners.filter(function(listenerSpec){return !listenerSpec.once;});listeners.forEach(function(listenerSpec){var listener=listenerSpec.listener;if(typeof listener==="function"){listener.call(self,event);}else {listener.handleEvent(event);}});return Boolean(event.defaultPrevented);}};module.exports=EventTarget;},{}],120:[function(require,module,exports){function Event(type,bubbles,cancelable,target){this.initEvent(type,bubbles,cancelable,target);}Event.prototype={initEvent:function initEvent(type,bubbles,cancelable,target){this.type=type;this.bubbles=bubbles;this.cancelable=cancelable;this.target=target;this.currentTarget=target;},// eslint-disable-next-line no-empty-function + stopPropagation:function stopPropagation(){},preventDefault:function preventDefault(){this.defaultPrevented=true;}};module.exports=Event;},{}],121:[function(require,module,exports){module.exports={Event:require("./event"),ProgressEvent:require("./progress-event"),CustomEvent:require("./custom-event"),EventTarget:require("./event-target")};},{"./custom-event":118,"./event":120,"./event-target":119,"./progress-event":122}],122:[function(require,module,exports){var Event=require("./event");function ProgressEvent(type,progressEventRaw,target){this.initEvent(type,false,false,target);this.loaded=typeof progressEventRaw.loaded==="number"?progressEventRaw.loaded:null;this.total=typeof progressEventRaw.total==="number"?progressEventRaw.total:null;this.lengthComputable=Boolean(progressEventRaw.total);}ProgressEvent.prototype=new Event();ProgressEvent.prototype.constructor=ProgressEvent;module.exports=ProgressEvent;},{"./event":120}],123:[function(require,module,exports){var FakeTimers=require("@sinonjs/fake-timers");var fakeServer=require("./index");// eslint-disable-next-line no-empty-function + function Server(){}Server.prototype=fakeServer;var fakeServerWithClock=new Server();fakeServerWithClock.addRequest=function addRequest(xhr){if(xhr.async){if(_typeof$1(setTimeout.clock)==="object"){this.clock=setTimeout.clock;}else {this.clock=FakeTimers.install();this.resetClock=true;}if(!this.longestTimeout){var clockSetTimeout=this.clock.setTimeout;var clockSetInterval=this.clock.setInterval;var server=this;this.clock.setTimeout=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetTimeout.apply(this,arguments);};this.clock.setInterval=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetInterval.apply(this,arguments);};}}return fakeServer.addRequest.call(this,xhr);};fakeServerWithClock.respond=function respond(){var returnVal=fakeServer.respond.apply(this,arguments);if(this.clock){this.clock.tick(this.longestTimeout||0);this.longestTimeout=0;if(this.resetClock){this.clock.uninstall();this.resetClock=false;}}return returnVal;};fakeServerWithClock.restore=function restore(){if(this.clock){this.clock.uninstall();}return fakeServer.restore.apply(this,arguments);};module.exports=fakeServerWithClock;},{"./index":124,"@sinonjs/fake-timers":61}],124:[function(require,module,exports){var fakeXhr=require("../fake-xhr");var push=[].push;var log=require("./log");var configureLogError=require("../configure-logger");var pathToRegexp=require("path-to-regexp");var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";function responseArray(handler){var response=handler;if(Object.prototype.toString.call(handler)!=="[object Array]"){response=[200,{},handler];}if(typeof response[2]!=="string"){if(!supportsArrayBuffer){throw new TypeError("Fake server response body should be a string, but was ".concat(_typeof$1(response[2])));}else if(!(response[2]instanceof ArrayBuffer)){throw new TypeError("Fake server response body should be a string or ArrayBuffer, but was ".concat(_typeof$1(response[2])));}}return response;}function getDefaultWindowLocation(){var winloc={hostname:"localhost",port:process.env.PORT||80,protocol:"http:"};winloc.host=winloc.hostname+(String(winloc.port)==="80"?"":":".concat(winloc.port));return winloc;}function getWindowLocation(){if(typeof window==="undefined"){// Fallback + return getDefaultWindowLocation();}if(typeof window.location!=="undefined"){// Browsers place location on window + return window.location;}if(typeof window.window!=="undefined"&&typeof window.window.location!=="undefined"){// React Native on Android places location on window.window + return window.window.location;}return getDefaultWindowLocation();}function matchOne(response,reqMethod,reqUrl){var rmeth=response.method;var matchMethod=!rmeth||rmeth.toLowerCase()===reqMethod.toLowerCase();var url=response.url;var matchUrl=!url||url===reqUrl||typeof url.test==="function"&&url.test(reqUrl)||typeof url==="function"&&url(reqUrl)===true;return matchMethod&&matchUrl;}function match(response,request){var wloc=getWindowLocation();var rCurrLoc=new RegExp("^".concat(wloc.protocol,"//").concat(wloc.host,"/"));var requestUrl=request.url;if(!/^https?:\/\//.test(requestUrl)||rCurrLoc.test(requestUrl)){requestUrl=requestUrl.replace(rCurrLoc,"/");}if(matchOne(response,this.getHTTPMethod(request),requestUrl)){if(typeof response.response==="function"){var ru=response.url;var args=[request].concat(ru&&typeof ru.exec==="function"?ru.exec(requestUrl).slice(1):[]);return response.response.apply(response,args);}return true;}return false;}function incrementRequestCount(){var count=++this.requestCount;this.requested=true;this.requestedOnce=count===1;this.requestedTwice=count===2;this.requestedThrice=count===3;this.firstRequest=this.getRequest(0);this.secondRequest=this.getRequest(1);this.thirdRequest=this.getRequest(2);this.lastRequest=this.getRequest(count-1);}var fakeServer={create:function create(config){var server=Object.create(this);server.configure(config);this.xhr=fakeXhr.useFakeXMLHttpRequest();server.requests=[];server.requestCount=0;server.queue=[];server.responses=[];this.xhr.onCreate=function(xhrObj){xhrObj.unsafeHeadersEnabled=function(){return !(server.unsafeHeadersEnabled===false);};server.addRequest(xhrObj);};return server;},configure:function configure(config){var self=this;var allowlist={autoRespond:true,autoRespondAfter:true,respondImmediately:true,fakeHTTPMethods:true,logger:true,unsafeHeadersEnabled:true};// eslint-disable-next-line no-param-reassign + config=config||{};Object.keys(config).forEach(function(setting){if(setting in allowlist){self[setting]=config[setting];}});self.logError=configureLogError(config);},addRequest:function addRequest(xhrObj){var server=this;push.call(this.requests,xhrObj);incrementRequestCount.call(this);xhrObj.onSend=function(){server.handleRequest(this);if(server.respondImmediately){server.respond();}else if(server.autoRespond&&!server.responding){setTimeout(function(){server.responding=false;server.respond();},server.autoRespondAfter||10);server.responding=true;}};},getHTTPMethod:function getHTTPMethod(request){if(this.fakeHTTPMethods&&/post/i.test(request.method)){var matches=(request.requestBody||"").match(/_method=([^\b;]+)/);return matches?matches[1]:request.method;}return request.method;},handleRequest:function handleRequest(xhr){if(xhr.async){push.call(this.queue,xhr);}else {this.processRequest(xhr);}},logger:function logger(){// no-op; override via configure() + },logError:configureLogError({}),log:log,respondWith:function respondWith(method,url,body){if(arguments.length===1&&typeof method!=="function"){this.response=responseArray(method);return;}if(arguments.length===1){// eslint-disable-next-line no-param-reassign + body=method;// eslint-disable-next-line no-param-reassign + url=method=null;}if(arguments.length===2){// eslint-disable-next-line no-param-reassign + body=url;// eslint-disable-next-line no-param-reassign + url=method;// eslint-disable-next-line no-param-reassign + method=null;}// Escape port number to prevent "named" parameters in 'path-to-regexp' module + if(typeof url==="string"&&url!==""&&/:[0-9]+\//.test(url)){var m=url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/);// eslint-disable-next-line no-param-reassign + url="".concat(m[1],"\\:").concat(m[2]);}push.call(this.responses,{method:method,url:typeof url==="string"&&url!==""?pathToRegexp(url):url,response:typeof body==="function"?body:responseArray(body)});},respond:function respond(){if(arguments.length>0){this.respondWith.apply(this,arguments);}var queue=this.queue||[];var requests=queue.splice(0,queue.length);var self=this;requests.forEach(function(request){self.processRequest(request);});},respondAll:function respondAll(){if(this.respondImmediately){return;}this.queue=this.requests.slice(0);var request;while(request=this.queue.shift()){this.processRequest(request);}},processRequest:function processRequest(request){try{if(request.aborted){return;}var response=this.response||[404,{},""];if(this.responses){for(var l=this.responses.length,i=l-1;i>=0;i--){if(match.call(this,this.responses[i],request)){response=this.responses[i].response;break;}}}if(request.readyState!==4){this.log(response,request);request.respond(response[0],response[1],response[2]);}}catch(e){this.logError("Fake server request processing",e);}},restore:function restore(){return this.xhr.restore&&this.xhr.restore.apply(this.xhr,arguments);},getRequest:function getRequest(index){return this.requests[index]||null;},reset:function reset(){this.resetBehavior();this.resetHistory();},resetBehavior:function resetBehavior(){this.responses.length=this.queue.length=0;},resetHistory:function resetHistory(){this.requests.length=this.requestCount=0;this.requestedOnce=this.requestedTwice=this.requestedThrice=this.requested=false;this.firstRequest=this.secondRequest=this.thirdRequest=this.lastRequest=null;}};module.exports=fakeServer;},{"../configure-logger":117,"../fake-xhr":127,"./log":125,"path-to-regexp":148}],125:[function(require,module,exports){var inspect=require("util").inspect;function log(response,request){var str;str="Request:\n".concat(inspect(request),"\n\n");str+="Response:\n".concat(inspect(response),"\n\n");/* istanbul ignore else: when this.logger is not a function, it can't be called */if(typeof this.logger==="function"){this.logger(str);}}module.exports=log;},{"util":113}],126:[function(require,module,exports){exports.isSupported=function(){try{return Boolean(new Blob());}catch(e){return false;}}();},{}],127:[function(require,module,exports){var GlobalTextEncoder=typeof TextEncoder!=="undefined"?TextEncoder:require("@sinonjs/text-encoding").TextEncoder;var globalObject=require("@sinonjs/commons").global;var configureLogError=require("../configure-logger");var sinonEvent=require("../event");var extend=require("just-extend");var supportsProgress=typeof ProgressEvent!=="undefined";var supportsCustomEvent=typeof CustomEvent!=="undefined";var supportsFormData=typeof FormData!=="undefined";var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";var supportsBlob=require("./blob").isSupported;function getWorkingXHR(globalScope){var supportsXHR=typeof globalScope.XMLHttpRequest!=="undefined";if(supportsXHR){return globalScope.XMLHttpRequest;}var supportsActiveX=typeof globalScope.ActiveXObject!=="undefined";if(supportsActiveX){return function(){return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");};}return false;}// Ref: https://fetch.spec.whatwg.org/#forbidden-header-name + var unsafeHeaders={"Accept-Charset":true,"Access-Control-Request-Headers":true,"Access-Control-Request-Method":true,"Accept-Encoding":true,Connection:true,"Content-Length":true,Cookie:true,Cookie2:true,"Content-Transfer-Encoding":true,Date:true,DNT:true,Expect:true,Host:true,"Keep-Alive":true,Origin:true,Referer:true,TE:true,Trailer:true,"Transfer-Encoding":true,Upgrade:true,"User-Agent":true,Via:true};function EventTargetHandler(){var self=this;var events=["loadstart","progress","abort","error","load","timeout","loadend"];function addEventListener(eventName){self.addEventListener(eventName,function(event){var listener=self["on".concat(eventName)];if(listener&&typeof listener==="function"){listener.call(this,event);}});}events.forEach(addEventListener);}EventTargetHandler.prototype=sinonEvent.EventTarget;function normalizeHeaderValue(value){// Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes + /*eslint no-control-regex: "off"*/return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g,"");}function getHeader(headers,header){var foundHeader=Object.keys(headers).filter(function(h){return h.toLowerCase()===header.toLowerCase();});return foundHeader[0]||null;}function excludeSetCookie2Header(header){return !/^Set-Cookie2?$/i.test(header);}function verifyResponseBodyType(body,responseType){var error=null;var isString=typeof body==="string";if(responseType==="arraybuffer"){if(!isString&&!(body instanceof ArrayBuffer)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string or ArrayBuffer."));error.name="InvalidBodyException";}}else if(responseType==="blob"){if(!isString&&!(body instanceof ArrayBuffer)&&supportsBlob&&!(body instanceof Blob)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string, ArrayBuffer, or Blob."));error.name="InvalidBodyException";}}else if(!isString){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string."));error.name="InvalidBodyException";}if(error){throw error;}}function convertToArrayBuffer(body,encoding){if(body instanceof ArrayBuffer){return body;}return new GlobalTextEncoder(encoding||"utf-8").encode(body).buffer;}function isXmlContentType(contentType){return !contentType||/(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);}function clearResponse(xhr){if(xhr.responseType===""||xhr.responseType==="text"){xhr.response=xhr.responseText="";}else {xhr.response=xhr.responseText=null;}xhr.responseXML=null;}function fakeXMLHttpRequestFor(globalScope){var isReactNative=globalScope.navigator&&globalScope.navigator.product==="ReactNative";var sinonXhr={XMLHttpRequest:globalScope.XMLHttpRequest};sinonXhr.GlobalXMLHttpRequest=globalScope.XMLHttpRequest;sinonXhr.GlobalActiveXObject=globalScope.ActiveXObject;sinonXhr.supportsActiveX=typeof sinonXhr.GlobalActiveXObject!=="undefined";sinonXhr.supportsXHR=typeof sinonXhr.GlobalXMLHttpRequest!=="undefined";sinonXhr.workingXHR=getWorkingXHR(globalScope);sinonXhr.supportsTimeout=sinonXhr.supportsXHR&&"timeout"in new sinonXhr.GlobalXMLHttpRequest();sinonXhr.supportsCORS=isReactNative||sinonXhr.supportsXHR&&"withCredentials"in new sinonXhr.GlobalXMLHttpRequest();// Note that for FakeXMLHttpRequest to work pre ES5 + // we lose some of the alignment with the spec. + // To ensure as close a match as possible, + // set responseType before calling open, send or respond; + function FakeXMLHttpRequest(config){EventTargetHandler.call(this);this.readyState=FakeXMLHttpRequest.UNSENT;this.requestHeaders={};this.requestBody=null;this.status=0;this.statusText="";this.upload=new EventTargetHandler();this.responseType="";this.response="";this.logError=configureLogError(config);if(sinonXhr.supportsTimeout){this.timeout=0;}if(sinonXhr.supportsCORS){this.withCredentials=false;}if(typeof FakeXMLHttpRequest.onCreate==="function"){FakeXMLHttpRequest.onCreate(this);}}function verifyState(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){throw new Error("INVALID_STATE_ERR");}if(xhr.sendFlag){throw new Error("INVALID_STATE_ERR");}}// largest arity in XHR is 5 - XHR#open + var apply=function apply(obj,method,args){switch(args.length){case 0:return obj[method]();case 1:return obj[method](args[0]);case 2:return obj[method](args[0],args[1]);case 3:return obj[method](args[0],args[1],args[2]);case 4:return obj[method](args[0],args[1],args[2],args[3]);case 5:return obj[method](args[0],args[1],args[2],args[3],args[4]);default:throw new Error("Unhandled case");}};FakeXMLHttpRequest.filters=[];FakeXMLHttpRequest.addFilter=function addFilter(fn){this.filters.push(fn);};FakeXMLHttpRequest.defake=function defake(fakeXhr,xhrArgs){var xhr=new sinonXhr.workingXHR();// eslint-disable-line new-cap + ["open","setRequestHeader","abort","getResponseHeader","getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"].forEach(function(method){fakeXhr[method]=function(){return apply(xhr,method,arguments);};});fakeXhr.send=function(){// Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute + if(xhr.responseType!==fakeXhr.responseType){xhr.responseType=fakeXhr.responseType;}return apply(xhr,"send",arguments);};var copyAttrs=function copyAttrs(args){args.forEach(function(attr){fakeXhr[attr]=xhr[attr];});};var stateChangeStart=function stateChangeStart(){fakeXhr.readyState=xhr.readyState;if(xhr.readyState>=FakeXMLHttpRequest.HEADERS_RECEIVED){copyAttrs(["status","statusText"]);}if(xhr.readyState>=FakeXMLHttpRequest.LOADING){copyAttrs(["response"]);if(xhr.responseType===""||xhr.responseType==="text"){copyAttrs(["responseText"]);}}if(xhr.readyState===FakeXMLHttpRequest.DONE&&(xhr.responseType===""||xhr.responseType==="document")){copyAttrs(["responseXML"]);}};var stateChangeEnd=function stateChangeEnd(){if(fakeXhr.onreadystatechange){// eslint-disable-next-line no-useless-call + fakeXhr.onreadystatechange.call(fakeXhr,{target:fakeXhr,currentTarget:fakeXhr});}};var stateChange=function stateChange(){stateChangeStart();stateChangeEnd();};if(xhr.addEventListener){xhr.addEventListener("readystatechange",stateChangeStart);Object.keys(fakeXhr.eventListeners).forEach(function(event){/*eslint-disable no-loop-func*/fakeXhr.eventListeners[event].forEach(function(handler){xhr.addEventListener(event,handler.listener,{capture:handler.capture,once:handler.once});});/*eslint-enable no-loop-func*/});xhr.addEventListener("readystatechange",stateChangeEnd);}else {xhr.onreadystatechange=stateChange;}apply(xhr,"open",xhrArgs);};FakeXMLHttpRequest.useFilters=false;function verifyRequestOpened(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){var errorMessage=xhr.readyState===FakeXMLHttpRequest.UNSENT?"INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first...":"INVALID_STATE_ERR - ".concat(xhr.readyState);throw new Error(errorMessage);}}function verifyRequestSent(xhr){if(xhr.readyState===FakeXMLHttpRequest.DONE){throw new Error("Request done");}}function verifyHeadersReceived(xhr){if(xhr.async&&xhr.readyState!==FakeXMLHttpRequest.HEADERS_RECEIVED){throw new Error("No headers received");}}function convertResponseBody(responseType,contentType,body){if(responseType===""||responseType==="text"){return body;}else if(supportsArrayBuffer&&responseType==="arraybuffer"){return convertToArrayBuffer(body);}else if(responseType==="json"){try{return JSON.parse(body);}catch(e){// Return parsing failure as null + return null;}}else if(supportsBlob&&responseType==="blob"){if(body instanceof Blob){return body;}var blobOptions={};if(contentType){blobOptions.type=contentType;}return new Blob([convertToArrayBuffer(body)],blobOptions);}else if(responseType==="document"){if(isXmlContentType(contentType)){return FakeXMLHttpRequest.parseXML(body);}return null;}throw new Error("Invalid responseType ".concat(responseType));}/** + * Steps to follow when there is an error, according to: + * https://xhr.spec.whatwg.org/#request-error-steps + */function requestErrorSteps(xhr){clearResponse(xhr);xhr.errorFlag=true;xhr.requestHeaders={};xhr.responseHeaders={};if(xhr.readyState!==FakeXMLHttpRequest.UNSENT&&xhr.sendFlag&&xhr.readyState!==FakeXMLHttpRequest.DONE){xhr.readyStateChange(FakeXMLHttpRequest.DONE);xhr.sendFlag=false;}}FakeXMLHttpRequest.parseXML=function parseXML(text){// Treat empty string as parsing failure + if(text!==""){try{if(typeof DOMParser!=="undefined"){var parser=new DOMParser();var parsererrorNS="";try{var parsererrors=parser.parseFromString("INVALID","text/xml").getElementsByTagName("parsererror");if(parsererrors.length){parsererrorNS=parsererrors[0].namespaceURI;}}catch(e){// passing invalid XML makes IE11 throw + // so no namespace needs to be determined + }var result;try{result=parser.parseFromString(text,"text/xml");}catch(err){return null;}return result.getElementsByTagNameNS(parsererrorNS,"parsererror").length?null:result;}var xmlDoc=new window.ActiveXObject("Microsoft.XMLDOM");xmlDoc.async="false";xmlDoc.loadXML(text);return xmlDoc.parseError.errorCode!==0?null:xmlDoc;}catch(e){// Unable to parse XML - no biggie + }}return null;};FakeXMLHttpRequest.statusCodes={100:"Continue",101:"Switching Protocols",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",300:"Multiple Choice",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported"};extend(FakeXMLHttpRequest.prototype,sinonEvent.EventTarget,{async:true,open:function open(method,url,async,username,password){this.method=method;this.url=url;this.async=typeof async==="boolean"?async:true;this.username=username;this.password=password;clearResponse(this);this.requestHeaders={};this.sendFlag=false;if(FakeXMLHttpRequest.useFilters===true){var xhrArgs=arguments;var defake=FakeXMLHttpRequest.filters.some(function(filter){return filter.apply(this,xhrArgs);});if(defake){FakeXMLHttpRequest.defake(this,arguments);return;}}this.readyStateChange(FakeXMLHttpRequest.OPENED);},readyStateChange:function readyStateChange(state){this.readyState=state;var readyStateChangeEvent=new sinonEvent.Event("readystatechange",false,false,this);if(typeof this.onreadystatechange==="function"){try{this.onreadystatechange(readyStateChangeEvent);}catch(e){this.logError("Fake XHR onreadystatechange handler",e);}}if(this.readyState!==FakeXMLHttpRequest.DONE){this.dispatchEvent(readyStateChangeEvent);}else {var event,progress;if(this.timedOut||this.aborted||this.status===0){progress={loaded:0,total:0};event=this.timedOut&&"timeout"||this.aborted&&"abort"||"error";}else {progress={loaded:100,total:100};event="load";}if(supportsProgress){this.upload.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}this.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.dispatchEvent(readyStateChangeEvent);this.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}},// Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method + setRequestHeader:function setRequestHeader(header,value){if(typeof value!=="string"){throw new TypeError("By RFC7230, section 3.2.4, header values should be strings. Got ".concat(_typeof$1(value)));}verifyState(this);var checkUnsafeHeaders=true;if(typeof this.unsafeHeadersEnabled==="function"){checkUnsafeHeaders=this.unsafeHeadersEnabled();}if(checkUnsafeHeaders&&(getHeader(unsafeHeaders,header)!==null||/^(Sec-|Proxy-)/i.test(header))){throw new Error(// eslint-disable-next-line quotes + "Refused to set unsafe header \"".concat(header,"\""));}// eslint-disable-next-line no-param-reassign + value=normalizeHeaderValue(value);var existingHeader=getHeader(this.requestHeaders,header);if(existingHeader){this.requestHeaders[existingHeader]+=", ".concat(value);}else {this.requestHeaders[header]=value;}},setStatus:function setStatus(status){var sanitizedStatus=typeof status==="number"?status:200;verifyRequestOpened(this);this.status=sanitizedStatus;this.statusText=FakeXMLHttpRequest.statusCodes[sanitizedStatus];},// Helps testing + setResponseHeaders:function setResponseHeaders(headers){verifyRequestOpened(this);var responseHeaders=this.responseHeaders={};Object.keys(headers).forEach(function(header){responseHeaders[header]=headers[header];});if(this.async){this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);}else {this.readyState=FakeXMLHttpRequest.HEADERS_RECEIVED;}},// Currently treats ALL data as a DOMString (i.e. no Document) + send:function send(data){verifyState(this);if(!/^(head)$/i.test(this.method)){var contentType=getHeader(this.requestHeaders,"Content-Type");if(this.requestHeaders[contentType]){var value=this.requestHeaders[contentType].split(";");this.requestHeaders[contentType]="".concat(value[0],";charset=utf-8");}else if(supportsFormData&&!(data instanceof FormData)){this.requestHeaders["Content-Type"]="text/plain;charset=utf-8";}this.requestBody=data;}this.errorFlag=false;this.sendFlag=this.async;clearResponse(this);if(typeof this.onSend==="function"){this.onSend(this);}// Only listen if setInterval and Date are a stubbed. + if(sinonXhr.supportsTimeout&&_typeof$1(setInterval.clock)==="object"&&_typeof$1(Date.clock)==="object"){var initiatedTime=Date.now();var self=this;// Listen to any possible tick by fake timers and check to see if timeout has + // been exceeded. It's important to note that timeout can be changed while a request + // is in flight, so we must check anytime the end user forces a clock tick to make + // sure timeout hasn't changed. + // https://xhr.spec.whatwg.org/#dfnReturnLink-2 + var clearIntervalId=setInterval(function(){// Check if the readyState has been reset or is done. If this is the case, there + // should be no timeout. This will also prevent aborted requests and + // fakeServerWithClock from triggering unnecessary responses. + if(self.readyState===FakeXMLHttpRequest.UNSENT||self.readyState===FakeXMLHttpRequest.DONE){clearInterval(clearIntervalId);}else if(typeof self.timeout==="number"&&self.timeout>0){if(Date.now()>=initiatedTime+self.timeout){self.triggerTimeout();clearInterval(clearIntervalId);}}},1);}this.dispatchEvent(new sinonEvent.Event("loadstart",false,false,this));},abort:function abort(){this.aborted=true;requestErrorSteps(this);this.readyState=FakeXMLHttpRequest.UNSENT;},error:function error(){clearResponse(this);this.errorFlag=true;this.requestHeaders={};this.responseHeaders={};this.readyStateChange(FakeXMLHttpRequest.DONE);},triggerTimeout:function triggerTimeout(){if(sinonXhr.supportsTimeout){this.timedOut=true;requestErrorSteps(this);}},getResponseHeader:function getResponseHeader(header){if(this.readyState=FakeXMLHttpRequest.LOADING){throw new Error("INVALID_STATE_ERR");}this.overriddenMimeType=type;}});var states={UNSENT:0,OPENED:1,HEADERS_RECEIVED:2,LOADING:3,DONE:4};extend(FakeXMLHttpRequest,states);extend(FakeXMLHttpRequest.prototype,states);function useFakeXMLHttpRequest(){FakeXMLHttpRequest.restore=function restore(keepOnCreate){if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=sinonXhr.GlobalXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=sinonXhr.GlobalActiveXObject;}delete FakeXMLHttpRequest.restore;if(keepOnCreate!==true){delete FakeXMLHttpRequest.onCreate;}};if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=FakeXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=function ActiveXObject(objId){if(objId==="Microsoft.XMLHTTP"||/^Msxml2\.XMLHTTP/i.test(objId)){return new FakeXMLHttpRequest();}return new sinonXhr.GlobalActiveXObject(objId);};}return FakeXMLHttpRequest;}return {xhr:sinonXhr,FakeXMLHttpRequest:FakeXMLHttpRequest,useFakeXMLHttpRequest:useFakeXMLHttpRequest};}module.exports=extend(fakeXMLHttpRequestFor(globalObject),{fakeXMLHttpRequestFor:fakeXMLHttpRequestFor});},{"../configure-logger":117,"../event":121,"./blob":126,"@sinonjs/commons":135,"@sinonjs/text-encoding":108,"just-extend":115}],128:[function(require,module,exports){module.exports={fakeServer:require("./fake-server"),fakeServerWithClock:require("./fake-server/fake-server-with-clock"),fakeXhr:require("./fake-xhr")};},{"./fake-server":124,"./fake-server/fake-server-with-clock":123,"./fake-xhr":127}],129:[function(require,module,exports){arguments[4][42][0].apply(exports,arguments);},{"./prototypes/array":137,"dup":42}],130:[function(require,module,exports){arguments[4][43][0].apply(exports,arguments);},{"./function-name":133,"dup":43}],131:[function(require,module,exports){arguments[4][44][0].apply(exports,arguments);},{"dup":44}],132:[function(require,module,exports){arguments[4][45][0].apply(exports,arguments);},{"dup":45}],133:[function(require,module,exports){arguments[4][46][0].apply(exports,arguments);},{"dup":46}],134:[function(require,module,exports){arguments[4][47][0].apply(exports,arguments);},{"dup":47}],135:[function(require,module,exports){arguments[4][48][0].apply(exports,arguments);},{"./called-in-order":129,"./class-name":130,"./deprecated":131,"./every":132,"./function-name":133,"./global":134,"./order-by-first-call":136,"./prototypes":140,"./type-of":146,"./value-to-string":147,"dup":48}],136:[function(require,module,exports){arguments[4][49][0].apply(exports,arguments);},{"./prototypes/array":137,"dup":49}],137:[function(require,module,exports){arguments[4][50][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":50}],138:[function(require,module,exports){arguments[4][51][0].apply(exports,arguments);},{"./throws-on-proto":145,"dup":51}],139:[function(require,module,exports){arguments[4][52][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":52}],140:[function(require,module,exports){arguments[4][53][0].apply(exports,arguments);},{"./array":137,"./function":139,"./map":141,"./object":142,"./set":143,"./string":144,"dup":53}],141:[function(require,module,exports){arguments[4][54][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":54}],142:[function(require,module,exports){arguments[4][55][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":55}],143:[function(require,module,exports){arguments[4][56][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":56}],144:[function(require,module,exports){arguments[4][57][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":57}],145:[function(require,module,exports){arguments[4][58][0].apply(exports,arguments);},{"dup":58}],146:[function(require,module,exports){arguments[4][59][0].apply(exports,arguments);},{"dup":59,"type-detect":151}],147:[function(require,module,exports){arguments[4][60][0].apply(exports,arguments);},{"dup":60}],148:[function(require,module,exports){var isarray=require('isarray');/** + * Expose `pathToRegexp`. + */module.exports=pathToRegexp;module.exports.parse=parse;module.exports.compile=compile;module.exports.tokensToFunction=tokensToFunction;module.exports.tokensToRegExp=tokensToRegExp;/** + * The main path matching regexp utility. + * + * @type {RegExp} + */var PATH_REGEXP=new RegExp([// Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)',// Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'].join('|'),'g');/** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */function parse(str,options){var tokens=[];var key=0;var index=0;var path='';var defaultDelimiter=options&&options.delimiter||'/';var res;while((res=PATH_REGEXP.exec(str))!=null){var m=res[0];var escaped=res[1];var offset=res.index;path+=str.slice(index,offset);index=offset+m.length;// Ignore already escaped sequences. + if(escaped){path+=escaped[1];continue;}var next=str[index];var prefix=res[2];var name=res[3];var capture=res[4];var group=res[5];var modifier=res[6];var asterisk=res[7];// Push the current path onto the tokens. + if(path){tokens.push(path);path='';}var partial=prefix!=null&&next!=null&&next!==prefix;var repeat=modifier==='+'||modifier==='*';var optional=modifier==='?'||modifier==='*';var delimiter=res[2]||defaultDelimiter;var pattern=capture||group;tokens.push({name:name||key++,prefix:prefix||'',delimiter:delimiter,optional:optional,repeat:repeat,partial:partial,asterisk:!!asterisk,pattern:pattern?escapeGroup(pattern):asterisk?'.*':'[^'+escapeString(delimiter)+']+?'});}// Match any characters still remaining. + if(index + * MIT Licensed + */var promiseExists=typeof Promise==='function';/* eslint-disable no-undef */var globalObject=(typeof self==="undefined"?"undefined":_typeof$1(self))==='object'?self:commonjsGlobal;// eslint-disable-line id-blacklist + var symbolExists=typeof Symbol!=='undefined';var mapExists=typeof Map!=='undefined';var setExists=typeof Set!=='undefined';var weakMapExists=typeof WeakMap!=='undefined';var weakSetExists=typeof WeakSet!=='undefined';var dataViewExists=typeof DataView!=='undefined';var symbolIteratorExists=symbolExists&&typeof Symbol.iterator!=='undefined';var symbolToStringTagExists=symbolExists&&typeof Symbol.toStringTag!=='undefined';var setEntriesExists=setExists&&typeof Set.prototype.entries==='function';var mapEntriesExists=mapExists&&typeof Map.prototype.entries==='function';var setIteratorPrototype=setEntriesExists&&Object.getPrototypeOf(new Set().entries());var mapIteratorPrototype=mapEntriesExists&&Object.getPrototypeOf(new Map().entries());var arrayIteratorExists=symbolIteratorExists&&typeof Array.prototype[Symbol.iterator]==='function';var arrayIteratorPrototype=arrayIteratorExists&&Object.getPrototypeOf([][Symbol.iterator]());var stringIteratorExists=symbolIteratorExists&&typeof String.prototype[Symbol.iterator]==='function';var stringIteratorPrototype=stringIteratorExists&&Object.getPrototypeOf(''[Symbol.iterator]());var toStringLeftSliceLength=8;var toStringRightSliceLength=-1;/** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */function typeDetect(obj){/* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */var typeofObj=_typeof$1(obj);if(typeofObj!=='object'){return typeofObj;}/* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */if(obj===null){return 'null';}/* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */if(obj===globalObject){return 'global';}/* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) + */if(Array.isArray(obj)&&(symbolToStringTagExists===false||!(Symbol.toStringTag in obj))){return 'Array';}// Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if((typeof window==="undefined"?"undefined":_typeof$1(window))==='object'&&window!==null){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" + */if(_typeof$1(window.location)==='object'&&obj===window.location){return 'Location';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */if(_typeof$1(window.document)==='object'&&obj===window.document){return 'Document';}if(_typeof$1(window.navigator)==='object'){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */if(_typeof$1(window.navigator.mimeTypes)==='object'&&obj===window.navigator.mimeTypes){return 'MimeTypeArray';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */if(_typeof$1(window.navigator.plugins)==='object'&&obj===window.navigator.plugins){return 'PluginArray';}}if((typeof window.HTMLElement==='function'||_typeof$1(window.HTMLElement)==='object')&&obj instanceof window.HTMLElement){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */if(obj.tagName==='BLOCKQUOTE'){return 'HTMLQuoteElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TD'){return 'HTMLTableDataCellElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TH'){return 'HTMLTableHeaderCellElement';}}}/* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */var stringTag=symbolToStringTagExists&&obj[Symbol.toStringTag];if(typeof stringTag==='string'){return stringTag;}var objPrototype=Object.getPrototypeOf(obj);/* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */if(objPrototype===RegExp.prototype){return 'RegExp';}/* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */if(objPrototype===Date.prototype){return 'Date';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */if(promiseExists&&objPrototype===Promise.prototype){return 'Promise';}/* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */if(setExists&&objPrototype===Set.prototype){return 'Set';}/* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */if(mapExists&&objPrototype===Map.prototype){return 'Map';}/* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */if(weakSetExists&&objPrototype===WeakSet.prototype){return 'WeakSet';}/* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */if(weakMapExists&&objPrototype===WeakMap.prototype){return 'WeakMap';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */if(dataViewExists&&objPrototype===DataView.prototype){return 'DataView';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */if(mapExists&&objPrototype===mapIteratorPrototype){return 'Map Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" + */if(setExists&&objPrototype===setIteratorPrototype){return 'Set Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(arrayIteratorExists&&objPrototype===arrayIteratorPrototype){return 'Array Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(stringIteratorExists&&objPrototype===stringIteratorPrototype){return 'String Iterator';}/* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */if(objPrototype===null){return 'Object';}return Object.prototype.toString.call(obj).slice(toStringLeftSliceLength,toStringRightSliceLength);}return typeDetect;});},{}]},{},[1]);var sinon$1=sinon;sinon.leakThreshold;sinon.assert;sinon.serverPrototype;sinon.getFakes;sinon.createStubInstance;sinon.inject;sinon.mock;sinon.reset;sinon.resetBehavior;sinon.resetHistory;sinon.restore;sinon.restoreContext;sinon.replace;sinon.define;sinon.replaceGetter;sinon.replaceSetter;sinon.spy;sinon.stub;sinon.fake;sinon.useFakeTimers;sinon.verify;sinon.verifyAndRestore;sinon.useFakeServer;sinon.useFakeXMLHttpRequest;sinon.usingPromise;sinon.createSandbox;sinon.match;sinon.restoreObject;sinon.expectation;sinon.defaultConfig;sinon.timers;sinon.xhr;sinon.FakeXMLHttpRequest;sinon.fakeServer;sinon.fakeServerWithClock;sinon.createFakeServer;sinon.createFakeServerWithClock;sinon.addBehavior;sinon.promise;var SDKProductActionType;(function(SDKProductActionType){SDKProductActionType[SDKProductActionType["Unknown"]=0]="Unknown";SDKProductActionType[SDKProductActionType["AddToCart"]=1]="AddToCart";SDKProductActionType[SDKProductActionType["RemoveFromCart"]=2]="RemoveFromCart";SDKProductActionType[SDKProductActionType["Checkout"]=3]="Checkout";SDKProductActionType[SDKProductActionType["CheckoutOption"]=4]="CheckoutOption";SDKProductActionType[SDKProductActionType["Click"]=5]="Click";SDKProductActionType[SDKProductActionType["ViewDetail"]=6]="ViewDetail";SDKProductActionType[SDKProductActionType["Purchase"]=7]="Purchase";SDKProductActionType[SDKProductActionType["Refund"]=8]="Refund";SDKProductActionType[SDKProductActionType["AddToWishlist"]=9]="AddToWishlist";SDKProductActionType[SDKProductActionType["RemoveFromWishlist"]=10]="RemoveFromWishlist";})(SDKProductActionType||(SDKProductActionType={}));var SDKIdentityTypeEnum;(function(SDKIdentityTypeEnum){SDKIdentityTypeEnum["other"]="other";SDKIdentityTypeEnum["customerId"]="customerid";SDKIdentityTypeEnum["facebook"]="facebook";SDKIdentityTypeEnum["twitter"]="twitter";SDKIdentityTypeEnum["google"]="google";SDKIdentityTypeEnum["microsoft"]="microsoft";SDKIdentityTypeEnum["yahoo"]="yahoo";SDKIdentityTypeEnum["email"]="email";SDKIdentityTypeEnum["alias"]="alias";SDKIdentityTypeEnum["facebookCustomAudienceId"]="facebookcustomaudienceid";SDKIdentityTypeEnum["otherId2"]="other2";SDKIdentityTypeEnum["otherId3"]="other3";SDKIdentityTypeEnum["otherId4"]="other4";SDKIdentityTypeEnum["otherId5"]="other5";SDKIdentityTypeEnum["otherId6"]="other6";SDKIdentityTypeEnum["otherId7"]="other7";SDKIdentityTypeEnum["otherId8"]="other8";SDKIdentityTypeEnum["otherId9"]="other9";SDKIdentityTypeEnum["otherId10"]="other10";SDKIdentityTypeEnum["mobileNumber"]="mobile_number";SDKIdentityTypeEnum["phoneNumber2"]="phone_number_2";SDKIdentityTypeEnum["phoneNumber3"]="phone_number_3";})(SDKIdentityTypeEnum||(SDKIdentityTypeEnum={}));var dist={};(function(exports){Object.defineProperty(exports,"__esModule",{value:true});(function(ApplicationInformationOsEnum){ApplicationInformationOsEnum["unknown"]="Unknown";ApplicationInformationOsEnum["iOS"]="IOS";ApplicationInformationOsEnum["android"]="Android";ApplicationInformationOsEnum["windowsPhone"]="WindowsPhone";ApplicationInformationOsEnum["mobileWeb"]="MobileWeb";ApplicationInformationOsEnum["unityIOS"]="UnityIOS";ApplicationInformationOsEnum["unityAndroid"]="UnityAndroid";ApplicationInformationOsEnum["desktop"]="Desktop";ApplicationInformationOsEnum["tvOS"]="TVOS";ApplicationInformationOsEnum["roku"]="Roku";ApplicationInformationOsEnum["outOfBand"]="OutOfBand";ApplicationInformationOsEnum["alexa"]="Alexa";ApplicationInformationOsEnum["smartTV"]="SmartTV";ApplicationInformationOsEnum["fireTV"]="FireTV";ApplicationInformationOsEnum["xbox"]="Xbox";})(exports.ApplicationInformationOsEnum||(exports.ApplicationInformationOsEnum={}));(function(ApplicationStateTransitionEventEventTypeEnum){ApplicationStateTransitionEventEventTypeEnum["applicationStateTransition"]="application_state_transition";})(exports.ApplicationStateTransitionEventEventTypeEnum||(exports.ApplicationStateTransitionEventEventTypeEnum={}));(function(ApplicationStateTransitionEventDataApplicationTransitionTypeEnum){ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationInitialized"]="application_initialized";ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationExit"]="application_exit";ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationBackground"]="application_background";ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationForeground"]="application_foreground";})(exports.ApplicationStateTransitionEventDataApplicationTransitionTypeEnum||(exports.ApplicationStateTransitionEventDataApplicationTransitionTypeEnum={}));(function(BatchEnvironmentEnum){BatchEnvironmentEnum["unknown"]="unknown";BatchEnvironmentEnum["development"]="development";BatchEnvironmentEnum["production"]="production";})(exports.BatchEnvironmentEnum||(exports.BatchEnvironmentEnum={}));(function(BreadcrumbEventEventTypeEnum){BreadcrumbEventEventTypeEnum["breadcrumb"]="breadcrumb";})(exports.BreadcrumbEventEventTypeEnum||(exports.BreadcrumbEventEventTypeEnum={}));(function(CommerceEventEventTypeEnum){CommerceEventEventTypeEnum["commerceEvent"]="commerce_event";})(exports.CommerceEventEventTypeEnum||(exports.CommerceEventEventTypeEnum={}));(function(CommerceEventDataCustomEventTypeEnum){CommerceEventDataCustomEventTypeEnum["addToCart"]="add_to_cart";CommerceEventDataCustomEventTypeEnum["removeFromCart"]="remove_from_cart";CommerceEventDataCustomEventTypeEnum["checkout"]="checkout";CommerceEventDataCustomEventTypeEnum["checkoutOption"]="checkout_option";CommerceEventDataCustomEventTypeEnum["click"]="click";CommerceEventDataCustomEventTypeEnum["viewDetail"]="view_detail";CommerceEventDataCustomEventTypeEnum["purchase"]="purchase";CommerceEventDataCustomEventTypeEnum["refund"]="refund";CommerceEventDataCustomEventTypeEnum["promotionView"]="promotion_view";CommerceEventDataCustomEventTypeEnum["promotionClick"]="promotion_click";CommerceEventDataCustomEventTypeEnum["addToWishlist"]="add_to_wishlist";CommerceEventDataCustomEventTypeEnum["removeFromWishlist"]="remove_from_wishlist";CommerceEventDataCustomEventTypeEnum["impression"]="impression";})(exports.CommerceEventDataCustomEventTypeEnum||(exports.CommerceEventDataCustomEventTypeEnum={}));(function(CrashReportEventEventTypeEnum){CrashReportEventEventTypeEnum["crashReport"]="crash_report";})(exports.CrashReportEventEventTypeEnum||(exports.CrashReportEventEventTypeEnum={}));(function(CustomEventEventTypeEnum){CustomEventEventTypeEnum["customEvent"]="custom_event";})(exports.CustomEventEventTypeEnum||(exports.CustomEventEventTypeEnum={}));(function(CustomEventDataCustomEventTypeEnum){CustomEventDataCustomEventTypeEnum["navigation"]="navigation";CustomEventDataCustomEventTypeEnum["location"]="location";CustomEventDataCustomEventTypeEnum["search"]="search";CustomEventDataCustomEventTypeEnum["transaction"]="transaction";CustomEventDataCustomEventTypeEnum["userContent"]="user_content";CustomEventDataCustomEventTypeEnum["userPreference"]="user_preference";CustomEventDataCustomEventTypeEnum["social"]="social";CustomEventDataCustomEventTypeEnum["media"]="media";CustomEventDataCustomEventTypeEnum["other"]="other";CustomEventDataCustomEventTypeEnum["unknown"]="unknown";})(exports.CustomEventDataCustomEventTypeEnum||(exports.CustomEventDataCustomEventTypeEnum={}));(function(DeviceCurrentStateDeviceOrientationEnum){DeviceCurrentStateDeviceOrientationEnum["portrait"]="portrait";DeviceCurrentStateDeviceOrientationEnum["portraitUpsideDown"]="portrait_upside_down";DeviceCurrentStateDeviceOrientationEnum["landscape"]="landscape";DeviceCurrentStateDeviceOrientationEnum["landscapeLeft"]="LandscapeLeft";DeviceCurrentStateDeviceOrientationEnum["landscapeRight"]="LandscapeRight";DeviceCurrentStateDeviceOrientationEnum["faceUp"]="FaceUp";DeviceCurrentStateDeviceOrientationEnum["faceDown"]="FaceDown";DeviceCurrentStateDeviceOrientationEnum["square"]="Square";})(exports.DeviceCurrentStateDeviceOrientationEnum||(exports.DeviceCurrentStateDeviceOrientationEnum={}));(function(DeviceCurrentStateStatusBarOrientationEnum){DeviceCurrentStateStatusBarOrientationEnum["portrait"]="portrait";DeviceCurrentStateStatusBarOrientationEnum["portraitUpsideDown"]="portrait_upside_down";DeviceCurrentStateStatusBarOrientationEnum["landscape"]="landscape";DeviceCurrentStateStatusBarOrientationEnum["landscapeLeft"]="LandscapeLeft";DeviceCurrentStateStatusBarOrientationEnum["landscapeRight"]="LandscapeRight";DeviceCurrentStateStatusBarOrientationEnum["faceUp"]="FaceUp";DeviceCurrentStateStatusBarOrientationEnum["faceDown"]="FaceDown";DeviceCurrentStateStatusBarOrientationEnum["square"]="Square";})(exports.DeviceCurrentStateStatusBarOrientationEnum||(exports.DeviceCurrentStateStatusBarOrientationEnum={}));(function(DeviceInformationPlatformEnum){DeviceInformationPlatformEnum["iOS"]="iOS";DeviceInformationPlatformEnum["android"]="Android";DeviceInformationPlatformEnum["web"]="web";DeviceInformationPlatformEnum["desktop"]="desktop";DeviceInformationPlatformEnum["tvOS"]="tvOS";DeviceInformationPlatformEnum["roku"]="roku";DeviceInformationPlatformEnum["outOfBand"]="out_of_band";DeviceInformationPlatformEnum["smartTV"]="smart_tv";DeviceInformationPlatformEnum["xbox"]="xbox";})(exports.DeviceInformationPlatformEnum||(exports.DeviceInformationPlatformEnum={}));(function(EventTypeEnum){EventTypeEnum["unknown"]="unknown";EventTypeEnum["sessionStart"]="session_start";EventTypeEnum["sessionEnd"]="session_end";EventTypeEnum["screenView"]="screen_view";EventTypeEnum["customEvent"]="custom_event";EventTypeEnum["crashReport"]="crash_report";EventTypeEnum["optOut"]="opt_out";EventTypeEnum["firstRun"]="first_run";EventTypeEnum["preAttribution"]="pre_attribution";EventTypeEnum["pushRegistration"]="push_registration";EventTypeEnum["applicationStateTransition"]="application_state_transition";EventTypeEnum["pushMessage"]="push_message";EventTypeEnum["networkPerformance"]="network_performance";EventTypeEnum["breadcrumb"]="breadcrumb";EventTypeEnum["profile"]="profile";EventTypeEnum["pushReaction"]="push_reaction";EventTypeEnum["commerceEvent"]="commerce_event";EventTypeEnum["userAttributeChange"]="user_attribute_change";EventTypeEnum["userIdentityChange"]="user_identity_change";EventTypeEnum["uninstall"]="uninstall";EventTypeEnum["validationResult"]="validation_result";})(exports.EventTypeEnum||(exports.EventTypeEnum={}));(function(IdentityTypeEnum){IdentityTypeEnum["other"]="other";IdentityTypeEnum["customerId"]="customer_id";IdentityTypeEnum["facebook"]="facebook";IdentityTypeEnum["twitter"]="twitter";IdentityTypeEnum["google"]="google";IdentityTypeEnum["microsoft"]="microsoft";IdentityTypeEnum["yahoo"]="yahoo";IdentityTypeEnum["email"]="email";IdentityTypeEnum["alias"]="alias";IdentityTypeEnum["facebookCustomAudienceId"]="facebook_custom_audience_id";IdentityTypeEnum["otherId2"]="other_id_2";IdentityTypeEnum["otherId3"]="other_id_3";IdentityTypeEnum["otherId4"]="other_id_4";IdentityTypeEnum["otherId5"]="other_id_5";IdentityTypeEnum["otherId6"]="other_id_6";IdentityTypeEnum["otherId7"]="other_id_7";IdentityTypeEnum["otherId8"]="other_id_8";IdentityTypeEnum["otherId9"]="other_id_9";IdentityTypeEnum["otherId10"]="other_id_10";IdentityTypeEnum["mobileNumber"]="mobile_number";IdentityTypeEnum["phoneNumber2"]="phone_number_2";IdentityTypeEnum["phoneNumber3"]="phone_number_3";})(exports.IdentityTypeEnum||(exports.IdentityTypeEnum={}));(function(NetworkPerformanceEventEventTypeEnum){NetworkPerformanceEventEventTypeEnum["networkPerformance"]="network_performance";})(exports.NetworkPerformanceEventEventTypeEnum||(exports.NetworkPerformanceEventEventTypeEnum={}));(function(OptOutEventEnum){OptOutEventEnum["optOut"]="opt_out";})(exports.OptOutEventEnum||(exports.OptOutEventEnum={}));(function(ProductActionActionEnum){ProductActionActionEnum["unknown"]="unknown";ProductActionActionEnum["addToCart"]="add_to_cart";ProductActionActionEnum["removeFromCart"]="remove_from_cart";ProductActionActionEnum["checkout"]="checkout";ProductActionActionEnum["checkoutOption"]="checkout_option";ProductActionActionEnum["click"]="click";ProductActionActionEnum["viewDetail"]="view_detail";ProductActionActionEnum["purchase"]="purchase";ProductActionActionEnum["refund"]="refund";ProductActionActionEnum["addToWishlist"]="add_to_wishlist";ProductActionActionEnum["removeFromWishlist"]="remove_from_wish_list";})(exports.ProductActionActionEnum||(exports.ProductActionActionEnum={}));(function(ProfileEventEventTypeEnum){ProfileEventEventTypeEnum["profile"]="profile";})(exports.ProfileEventEventTypeEnum||(exports.ProfileEventEventTypeEnum={}));(function(ProfileEventDataProfileEventTypeEnum){ProfileEventDataProfileEventTypeEnum["signup"]="signup";ProfileEventDataProfileEventTypeEnum["login"]="login";ProfileEventDataProfileEventTypeEnum["logout"]="logout";ProfileEventDataProfileEventTypeEnum["update"]="update";ProfileEventDataProfileEventTypeEnum["delete"]="delete";})(exports.ProfileEventDataProfileEventTypeEnum||(exports.ProfileEventDataProfileEventTypeEnum={}));(function(PromotionActionActionEnum){PromotionActionActionEnum["view"]="view";PromotionActionActionEnum["click"]="click";})(exports.PromotionActionActionEnum||(exports.PromotionActionActionEnum={}));(function(PushMessageEventEventTypeEnum){PushMessageEventEventTypeEnum["pushMessage"]="push_message";})(exports.PushMessageEventEventTypeEnum||(exports.PushMessageEventEventTypeEnum={}));(function(PushMessageEventDataPushMessageTypeEnum){PushMessageEventDataPushMessageTypeEnum["sent"]="sent";PushMessageEventDataPushMessageTypeEnum["received"]="received";PushMessageEventDataPushMessageTypeEnum["action"]="action";})(exports.PushMessageEventDataPushMessageTypeEnum||(exports.PushMessageEventDataPushMessageTypeEnum={}));(function(PushMessageEventDataApplicationStateEnum){PushMessageEventDataApplicationStateEnum["notRunning"]="not_running";PushMessageEventDataApplicationStateEnum["background"]="background";PushMessageEventDataApplicationStateEnum["foreground"]="foreground";})(exports.PushMessageEventDataApplicationStateEnum||(exports.PushMessageEventDataApplicationStateEnum={}));(function(PushMessageEventDataPushMessageBehaviorEnum){PushMessageEventDataPushMessageBehaviorEnum["received"]="Received";PushMessageEventDataPushMessageBehaviorEnum["directOpen"]="DirectOpen";PushMessageEventDataPushMessageBehaviorEnum["read"]="Read";PushMessageEventDataPushMessageBehaviorEnum["influencedOpen"]="InfluencedOpen";PushMessageEventDataPushMessageBehaviorEnum["displayed"]="Displayed";})(exports.PushMessageEventDataPushMessageBehaviorEnum||(exports.PushMessageEventDataPushMessageBehaviorEnum={}));(function(PushRegistrationEventEventTypeEnum){PushRegistrationEventEventTypeEnum["pushRegistration"]="push_registration";})(exports.PushRegistrationEventEventTypeEnum||(exports.PushRegistrationEventEventTypeEnum={}));(function(SessionEndEventEventTypeEnum){SessionEndEventEventTypeEnum["sessionEnd"]="session_end";})(exports.SessionEndEventEventTypeEnum||(exports.SessionEndEventEventTypeEnum={}));(function(SessionStartEventEventTypeEnum){SessionStartEventEventTypeEnum["sessionStart"]="session_start";})(exports.SessionStartEventEventTypeEnum||(exports.SessionStartEventEventTypeEnum={}));(function(SourceInformationChannelEnum){SourceInformationChannelEnum["native"]="native";SourceInformationChannelEnum["javascript"]="javascript";SourceInformationChannelEnum["pixel"]="pixel";SourceInformationChannelEnum["desktop"]="desktop";SourceInformationChannelEnum["partner"]="partner";SourceInformationChannelEnum["serverToServer"]="server_to_server";})(exports.SourceInformationChannelEnum||(exports.SourceInformationChannelEnum={}));(function(UserAttributeChangeEventEventTypeEnum){UserAttributeChangeEventEventTypeEnum["userAttributeChange"]="user_attribute_change";})(exports.UserAttributeChangeEventEventTypeEnum||(exports.UserAttributeChangeEventEventTypeEnum={}));(function(UserIdentityChangeEventEventTypeEnum){UserIdentityChangeEventEventTypeEnum["userIdentityChange"]="user_identity_change";})(exports.UserIdentityChangeEventEventTypeEnum||(exports.UserIdentityChangeEventEventTypeEnum={}));})(dist);var _TriggerUploadType;var MessageType$1={SessionStart:1,SessionEnd:2,PageView:3,PageEvent:4,CrashReport:5,OptOut:6,AppStateTransition:10,Profile:14,Commerce:16,Media:20,UserAttributeChange:17,UserIdentityChange:18};// Dictionary that contains MessageTypes that will + // trigger an immediate upload. + var TriggerUploadType=(_TriggerUploadType={},_defineProperty$1(_TriggerUploadType,MessageType$1.Commerce,1),_defineProperty$1(_TriggerUploadType,MessageType$1.UserAttributeChange,1),_defineProperty$1(_TriggerUploadType,MessageType$1.UserIdentityChange,1),_TriggerUploadType);var EventType={Unknown:0,Navigation:1,Location:2,Search:3,Transaction:4,UserContent:5,UserPreference:6,Social:7,Other:8,Media:9,getName:function getName(id){switch(id){case EventType.Unknown:return 'Unknown';case EventType.Navigation:return 'Navigation';case EventType.Location:return 'Location';case EventType.Search:return 'Search';case EventType.Transaction:return 'Transaction';case EventType.UserContent:return 'User Content';case EventType.UserPreference:return 'User Preference';case EventType.Social:return 'Social';case CommerceEventType.ProductAddToCart:return 'Product Added to Cart';case CommerceEventType.ProductAddToWishlist:return 'Product Added to Wishlist';case CommerceEventType.ProductCheckout:return 'Product Checkout';case CommerceEventType.ProductCheckoutOption:return 'Product Checkout Options';case CommerceEventType.ProductClick:return 'Product Click';case CommerceEventType.ProductImpression:return 'Product Impression';case CommerceEventType.ProductPurchase:return 'Product Purchased';case CommerceEventType.ProductRefund:return 'Product Refunded';case CommerceEventType.ProductRemoveFromCart:return 'Product Removed From Cart';case CommerceEventType.ProductRemoveFromWishlist:return 'Product Removed from Wishlist';case CommerceEventType.ProductViewDetail:return 'Product View Details';case CommerceEventType.PromotionClick:return 'Promotion Click';case CommerceEventType.PromotionView:return 'Promotion View';default:return 'Other';}}};// Continuation of enum above, but in seperate object since we don't expose these to end user + var CommerceEventType={ProductAddToCart:10,ProductRemoveFromCart:11,ProductCheckout:12,ProductCheckoutOption:13,ProductClick:14,ProductViewDetail:15,ProductPurchase:16,ProductRefund:17,PromotionView:18,PromotionClick:19,ProductAddToWishlist:20,ProductRemoveFromWishlist:21,ProductImpression:22};var IdentityType={Other:0,CustomerId:1,Facebook:2,Twitter:3,Google:4,Microsoft:5,Yahoo:6,Email:7,FacebookCustomAudienceId:9,Other2:10,Other3:11,Other4:12,Other5:13,Other6:14,Other7:15,Other8:16,Other9:17,Other10:18,MobileNumber:19,PhoneNumber2:20,PhoneNumber3:21};IdentityType.isValid=function(identityType){if(typeof identityType==='number'){for(var prop in IdentityType){if(IdentityType.hasOwnProperty(prop)){if(IdentityType[prop]===identityType){return true;}}}}return false;};IdentityType.getName=function(identityType){switch(identityType){case window.mParticle.IdentityType.CustomerId:return 'Customer ID';case window.mParticle.IdentityType.Facebook:return 'Facebook ID';case window.mParticle.IdentityType.Twitter:return 'Twitter ID';case window.mParticle.IdentityType.Google:return 'Google ID';case window.mParticle.IdentityType.Microsoft:return 'Microsoft ID';case window.mParticle.IdentityType.Yahoo:return 'Yahoo ID';case window.mParticle.IdentityType.Email:return 'Email';case window.mParticle.IdentityType.FacebookCustomAudienceId:return 'Facebook App User ID';default:return 'Other ID';}};IdentityType.getIdentityType=function(identityName){switch(identityName){case'other':return IdentityType.Other;case'customerid':return IdentityType.CustomerId;case'facebook':return IdentityType.Facebook;case'twitter':return IdentityType.Twitter;case'google':return IdentityType.Google;case'microsoft':return IdentityType.Microsoft;case'yahoo':return IdentityType.Yahoo;case'email':return IdentityType.Email;case'facebookcustomaudienceid':return IdentityType.FacebookCustomAudienceId;case'other2':return IdentityType.Other2;case'other3':return IdentityType.Other3;case'other4':return IdentityType.Other4;case'other5':return IdentityType.Other5;case'other6':return IdentityType.Other6;case'other7':return IdentityType.Other7;case'other8':return IdentityType.Other8;case'other9':return IdentityType.Other9;case'other10':return IdentityType.Other10;case'mobile_number':return IdentityType.MobileNumber;case'phone_number_2':return IdentityType.PhoneNumber2;case'phone_number_3':return IdentityType.PhoneNumber3;default:return false;}};IdentityType.getIdentityName=function(identityType){switch(identityType){case IdentityType.Other:return 'other';case IdentityType.CustomerId:return 'customerid';case IdentityType.Facebook:return 'facebook';case IdentityType.Twitter:return 'twitter';case IdentityType.Google:return 'google';case IdentityType.Microsoft:return 'microsoft';case IdentityType.Yahoo:return 'yahoo';case IdentityType.Email:return 'email';case IdentityType.FacebookCustomAudienceId:return 'facebookcustomaudienceid';case IdentityType.Other2:return 'other2';case IdentityType.Other3:return 'other3';case IdentityType.Other4:return 'other4';case IdentityType.Other5:return 'other5';case IdentityType.Other6:return 'other6';case IdentityType.Other7:return 'other7';case IdentityType.Other8:return 'other8';case IdentityType.Other9:return 'other9';case IdentityType.Other10:return 'other10';case IdentityType.MobileNumber:return 'mobile_number';case IdentityType.PhoneNumber2:return 'phone_number_2';case IdentityType.PhoneNumber3:return 'phone_number_3';}};var ProductActionType={Unknown:0,AddToCart:1,RemoveFromCart:2,Checkout:3,CheckoutOption:4,Click:5,ViewDetail:6,Purchase:7,Refund:8,AddToWishlist:9,RemoveFromWishlist:10};ProductActionType.getName=function(id){switch(id){case ProductActionType.AddToCart:return 'Add to Cart';case ProductActionType.RemoveFromCart:return 'Remove from Cart';case ProductActionType.Checkout:return 'Checkout';case ProductActionType.CheckoutOption:return 'Checkout Option';case ProductActionType.Click:return 'Click';case ProductActionType.ViewDetail:return 'View Detail';case ProductActionType.Purchase:return 'Purchase';case ProductActionType.Refund:return 'Refund';case ProductActionType.AddToWishlist:return 'Add to Wishlist';case ProductActionType.RemoveFromWishlist:return 'Remove from Wishlist';default:return 'Unknown';}};// these are the action names used by server and mobile SDKs when expanding a CommerceEvent + ProductActionType.getExpansionName=function(id){switch(id){case ProductActionType.AddToCart:return 'add_to_cart';case ProductActionType.RemoveFromCart:return 'remove_from_cart';case ProductActionType.Checkout:return 'checkout';case ProductActionType.CheckoutOption:return 'checkout_option';case ProductActionType.Click:return 'click';case ProductActionType.ViewDetail:return 'view_detail';case ProductActionType.Purchase:return 'purchase';case ProductActionType.Refund:return 'refund';case ProductActionType.AddToWishlist:return 'add_to_wishlist';case ProductActionType.RemoveFromWishlist:return 'remove_from_wishlist';default:return 'unknown';}};var PromotionActionType={Unknown:0,PromotionView:1,PromotionClick:2};PromotionActionType.getName=function(id){switch(id){case PromotionActionType.PromotionView:return 'view';case PromotionActionType.PromotionClick:return 'click';default:return 'unknown';}};// these are the names that the server and mobile SDKs use while expanding CommerceEvent + PromotionActionType.getExpansionName=function(id){switch(id){case PromotionActionType.PromotionView:return 'view';case PromotionActionType.PromotionClick:return 'click';default:return 'unknown';}};var ProfileMessageType={Logout:3};var ApplicationTransitionType$1={AppInit:1};var Environment={Production:'production',Development:'development'};var Types={MessageType:MessageType$1,EventType:EventType,CommerceEventType:CommerceEventType,IdentityType:IdentityType,ProfileMessageType:ProfileMessageType,ApplicationTransitionType:ApplicationTransitionType$1,ProductActionType:ProductActionType,PromotionActionType:PromotionActionType,TriggerUploadType:TriggerUploadType,Environment:Environment};function convertEvents(mpid,sdkEvents,mpInstance){if(!mpid){return null;}if(!sdkEvents||sdkEvents.length<1){return null;}var user=mpInstance.Identity.getCurrentUser();var uploadEvents=[];var lastEvent=null;for(var _i=0,sdkEvents_1=sdkEvents;_i=BatchUploader.MINIMUM_INTERVAL_MILLIS;if(this.uploadIntervalMillis=rampNumber;};// Adds listeners to be used trigger Navigator.sendBeacon if the browser + // loses focus for any reason, such as closing browser tab or minimizing window + BatchUploader.prototype.addEventListeners=function(){var _this=this;// visibility change is a document property, not window + document.addEventListener('visibilitychange',function(){_this.prepareAndUpload(false,_this.isBeaconAvailable());});window.addEventListener('beforeunload',function(){_this.prepareAndUpload(false,_this.isBeaconAvailable());});window.addEventListener('pagehide',function(){_this.prepareAndUpload(false,_this.isBeaconAvailable());});};BatchUploader.prototype.isBeaconAvailable=function(){if(navigator.sendBeacon){return true;}return false;};// Triggers a setTimeout for prepareAndUpload + BatchUploader.prototype.triggerUploadInterval=function(triggerFuture,useBeacon){var _this_1=this;if(triggerFuture===void 0){triggerFuture=false;}if(useBeacon===void 0){useBeacon=false;}setTimeout(function(){_this_1.prepareAndUpload(triggerFuture,useBeacon);},this.uploadIntervalMillis);};/** + * This method will queue a single Event which will eventually be processed into a Batch + * @param event event that should be queued + */BatchUploader.prototype.queueEvent=function(event){if(!isEmpty(event)){this.eventsQueuedForProcessing.push(event);if(this.offlineStorageEnabled&&this.eventVault){this.eventVault.store(this.eventsQueuedForProcessing);}this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(event)));this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length));// TODO: Remove this check once the v2 code path is removed + // https://go.mparticle.com/work/SQDSDKS-3720 + if(!this.batchingEnabled||Types.TriggerUploadType[event.EventDataType]){this.prepareAndUpload(false,false);}}};/** + * This implements crucial logic to: + * - bucket pending events by MPID, and then by Session, and upload individual batches for each bucket. + * + * In the future this should enforce other requirements such as maximum batch size. + * + * @param sdkEvents current pending events + * @param defaultUser the user to reference for events that are missing data + */BatchUploader.createNewBatches=function(sdkEvents,defaultUser,mpInstance){if(!defaultUser||!sdkEvents||!sdkEvents.length){return null;}//bucket by MPID, and then by session, ordered by timestamp + var newUploads=[];var eventsByUser=new Map();for(var _i=0,sdkEvents_1=sdkEvents;_i=200&&response.status<300){logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id));}else if(response.status>=500||response.status===429){logger.error("HTTP error status ".concat(response.status," received"));// Server error, add back current batches and try again later + return [2/*return*/,uploads.slice(i,uploads.length)];}else if(response.status>=401){logger.error("HTTP error status ".concat(response.status," while uploading - please verify your API key."));//if we're getting a 401, assume we'll keep getting a 401 and clear the uploads. + return [2/*return*/,null];}else {// In case there is an HTTP error we did not anticipate. + console.error("HTTP error status ".concat(response.status," while uploading events."),response);throw new Error("Uncaught HTTP Error ".concat(response.status,". Batch upload will be re-attempted."));}return [3/*break*/,5];case 4:e_1=_a.sent();logger.error("Error sending event to mParticle servers. ".concat(e_1));return [2/*return*/,uploads.slice(i,uploads.length)];case 5:i++;return [3/*break*/,1];case 6:return [2/*return*/,null];}});});};// We upload JSON, but this content type is required to avoid a CORS preflight request + BatchUploader.CONTENT_TYPE='text/plain;charset=UTF-8';BatchUploader.MINIMUM_INTERVAL_MILLIS=500;return BatchUploader;}();var AsyncUploader=/** @class */function(){function AsyncUploader(url){this.url=url;}return AsyncUploader;}();var FetchUploader=/** @class */function(_super){__extends(FetchUploader,_super);function FetchUploader(){return _super!==null&&_super.apply(this,arguments)||this;}FetchUploader.prototype.upload=function(fetchPayload){return __awaiter(this,void 0,void 0,function(){var response;return __generator(this,function(_a){switch(_a.label){case 0:return [4/*yield*/,fetch(this.url,fetchPayload)];case 1:response=_a.sent();return [2/*return*/,response];}});});};return FetchUploader;}(AsyncUploader);var XHRUploader=/** @class */function(_super){__extends(XHRUploader,_super);function XHRUploader(){return _super!==null&&_super.apply(this,arguments)||this;}XHRUploader.prototype.upload=function(fetchPayload){return __awaiter(this,void 0,void 0,function(){var response;return __generator(this,function(_a){switch(_a.label){case 0:return [4/*yield*/,this.makeRequest(this.url,fetchPayload.body)];case 1:response=_a.sent();return [2/*return*/,response];}});});};XHRUploader.prototype.makeRequest=function(url,data){return __awaiter(this,void 0,void 0,function(){var xhr;return __generator(this,function(_a){xhr=new XMLHttpRequest();return [2/*return*/,new Promise(function(resolve,reject){xhr.onreadystatechange=function(){if(xhr.readyState!==4)return;// Process the response + if(xhr.status>=200&&xhr.status<300){resolve(xhr);}else {reject(xhr);}};xhr.open('post',url);xhr.send(data);})];});});};return XHRUploader;}(AsyncUploader);var chai$2={};/*! + * assertion-error + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ /*! + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */function Hash(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ /** + * ### .hasProperty(object, name) * - * @private - * @name has - * @memberOf Hash - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */function hashHas(key){var data=this.__data__;return nativeCreate?data[key]!==undefined:hasOwnProperty.call(data,key);}/** - * Sets the hash `key` to `value`. + * This allows checking whether an object has own + * or inherited from prototype chain named property. * - * @private - * @name set - * @memberOf Hash - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the hash instance. - */function hashSet(key,value){var data=this.__data__;data[key]=nativeCreate&&value===undefined?HASH_UNDEFINED:value;return this;}// Add methods to `Hash`. - Hash.prototype.clear=hashClear;Hash.prototype['delete']=hashDelete;Hash.prototype.get=hashGet;Hash.prototype.has=hashHas;Hash.prototype.set=hashSet;/** - * Creates an list cache object. + * Basically does the same thing as the `in` + * operator but works properly with null/undefined values + * and other primitives. * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */function ListCache(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index-1;}/** - * Sets the list cache `key` to `value`. + * hasProperty(obj.arr, 'length'); // true + * hasProperty(obj.arr, 2); // true + * hasProperty(obj.arr, 3); // false * - * @private - * @name set - * @memberOf ListCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. - */function listCacheSet(key,value){var data=this.__data__,index=assocIndexOf(data,key);if(index<0){data.push([key,value]);}else {data[index][1]=value;}return this;}// Add methods to `ListCache`. - ListCache.prototype.clear=listCacheClear;ListCache.prototype['delete']=listCacheDelete;ListCache.prototype.get=listCacheGet;ListCache.prototype.has=listCacheHas;ListCache.prototype.set=listCacheSet;/** - * Creates a map cache object to store key-value pairs. + * @param {Object} object + * @param {String|Symbol} name + * @returns {Boolean} whether it exists + * @namespace Utils + * @name hasProperty + * @api public + */function hasProperty(obj,name){if(typeof obj==='undefined'||obj===null){return false;}// The `in` operator does not work with primitives. + return name in Object(obj);}/* ! + * ## parsePath(path) * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */function MapCache(entries){var index=-1,length=entries?entries.length:0;this.clear();while(++index1?internalGetPathValue(obj,parsed,parsed.length-1):obj,name:last.p||last.i,value:internalGetPathValue(obj,parsed)};info.exists=hasProperty(info.parent,info.name);return info;}/** + * ### .getPathValue(object, path) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue(obj, 'prop1.str'); // Hello + * getPathValue(obj, 'prop1.att[2]'); // b + * getPathValue(obj, 'prop2.arr[0].nested'); // Universe + * + * @param {Object} object + * @param {String} path + * @returns {Object} value or `undefined` + * @namespace Utils + * @name getPathValue + * @api public + */function getPathValue(obj,path){var info=getPathInfo(obj,path);return info.value;}/** + * ### .setPathValue(object, path, value) + * + * Define the value in an object at a given string path. + * + * ```js + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * }; + * ``` + * + * The following would be acceptable. + * + * ```js + * var properties = require('tea-properties'); + * properties.set(obj, 'prop1.str', 'Hello Universe!'); + * properties.set(obj, 'prop1.arr[2]', 'B'); + * properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' }); + * ``` + * + * @param {Object} object + * @param {String} path + * @param {Mixed} value + * @api private + */function setPathValue(obj,path,val){var parsed=parsePath(path);internalSetPathValue(obj,val,parsed);return obj;}var pathval={hasProperty:hasProperty,getPathInfo:getPathInfo,getPathValue:getPathValue,setPathValue:setPathValue};/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .flag(object, key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @namespace Utils + * @name flag + * @api private + */var flag$5=function flag(obj,key,value){var flags=obj.__flags||(obj.__flags=Object.create(null));if(arguments.length===3){flags[key]=value;}else {return flags[key];}};/*! + * Chai - test utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /*! + * Module dependencies + */var flag$4=flag$5;/** + * ### .test(object, expression) + * + * Test an object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name test + */var test=function test(obj,args){var negate=flag$4(obj,'negate'),expr=args[0];return negate?!expr:expr;};var typeDetect={exports:{}};typeDetect.exports;(function(module,exports){(function(global,factory){module.exports=factory();})(commonjsGlobal$1,function(){/* ! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */var promiseExists=typeof Promise==='function';/* eslint-disable no-undef */var globalObject=(typeof self==="undefined"?"undefined":_typeof$1(self))==='object'?self:commonjsGlobal$1;// eslint-disable-line id-blacklist + var symbolExists=typeof Symbol!=='undefined';var mapExists=typeof Map!=='undefined';var setExists=typeof Set!=='undefined';var weakMapExists=typeof WeakMap!=='undefined';var weakSetExists=typeof WeakSet!=='undefined';var dataViewExists=typeof DataView!=='undefined';var symbolIteratorExists=symbolExists&&typeof Symbol.iterator!=='undefined';var symbolToStringTagExists=symbolExists&&typeof Symbol.toStringTag!=='undefined';var setEntriesExists=setExists&&typeof Set.prototype.entries==='function';var mapEntriesExists=mapExists&&typeof Map.prototype.entries==='function';var setIteratorPrototype=setEntriesExists&&Object.getPrototypeOf(new Set().entries());var mapIteratorPrototype=mapEntriesExists&&Object.getPrototypeOf(new Map().entries());var arrayIteratorExists=symbolIteratorExists&&typeof Array.prototype[Symbol.iterator]==='function';var arrayIteratorPrototype=arrayIteratorExists&&Object.getPrototypeOf([][Symbol.iterator]());var stringIteratorExists=symbolIteratorExists&&typeof String.prototype[Symbol.iterator]==='function';var stringIteratorPrototype=stringIteratorExists&&Object.getPrototypeOf(''[Symbol.iterator]());var toStringLeftSliceLength=8;var toStringRightSliceLength=-1;/** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */function typeDetect(obj){/* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */var typeofObj=_typeof$1(obj);if(typeofObj!=='object'){return typeofObj;}/* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */if(obj===null){return 'null';}/* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */if(obj===globalObject){return 'global';}/* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) + */if(Array.isArray(obj)&&(symbolToStringTagExists===false||!(Symbol.toStringTag in obj))){return 'Array';}// Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if((typeof window==="undefined"?"undefined":_typeof$1(window))==='object'&&window!==null){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" + */if(_typeof$1(window.location)==='object'&&obj===window.location){return 'Location';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */if(_typeof$1(window.document)==='object'&&obj===window.document){return 'Document';}if(_typeof$1(window.navigator)==='object'){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */if(_typeof$1(window.navigator.mimeTypes)==='object'&&obj===window.navigator.mimeTypes){return 'MimeTypeArray';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */if(_typeof$1(window.navigator.plugins)==='object'&&obj===window.navigator.plugins){return 'PluginArray';}}if((typeof window.HTMLElement==='function'||_typeof$1(window.HTMLElement)==='object')&&obj instanceof window.HTMLElement){/* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */if(obj.tagName==='BLOCKQUOTE'){return 'HTMLQuoteElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TD'){return 'HTMLTableDataCellElement';}/* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */if(obj.tagName==='TH'){return 'HTMLTableHeaderCellElement';}}}/* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */var stringTag=symbolToStringTagExists&&obj[Symbol.toStringTag];if(typeof stringTag==='string'){return stringTag;}var objPrototype=Object.getPrototypeOf(obj);/* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */if(objPrototype===RegExp.prototype){return 'RegExp';}/* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */if(objPrototype===Date.prototype){return 'Date';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */if(promiseExists&&objPrototype===Promise.prototype){return 'Promise';}/* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */if(setExists&&objPrototype===Set.prototype){return 'Set';}/* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */if(mapExists&&objPrototype===Map.prototype){return 'Map';}/* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */if(weakSetExists&&objPrototype===WeakSet.prototype){return 'WeakSet';}/* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */if(weakMapExists&&objPrototype===WeakMap.prototype){return 'WeakMap';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */if(dataViewExists&&objPrototype===DataView.prototype){return 'DataView';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */if(mapExists&&objPrototype===mapIteratorPrototype){return 'Map Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" + */if(setExists&&objPrototype===setIteratorPrototype){return 'Set Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(arrayIteratorExists&&objPrototype===arrayIteratorPrototype){return 'Array Iterator';}/* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */if(stringIteratorExists&&objPrototype===stringIteratorPrototype){return 'String Iterator';}/* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */if(objPrototype===null){return 'Object';}return Object.prototype.toString.call(obj).slice(toStringLeftSliceLength,toStringRightSliceLength);}return typeDetect;});})(typeDetect,typeDetect.exports);var typeDetectExports=typeDetect.exports;/*! + * Chai - expectTypes utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .expectTypes(obj, types) + * + * Ensures that the object being tested against is of a valid type. + * + * utils.expectTypes(this, ['array', 'object', 'string']); + * + * @param {Mixed} obj constructed Assertion + * @param {Array} type A list of allowed types for this assertion + * @namespace Utils + * @name expectTypes + * @api public + */var AssertionError=assertionError;var flag$3=flag$5;var type$2=typeDetectExports;var expectTypes=function expectTypes(obj,types){var flagMsg=flag$3(obj,'message');var ssfi=flag$3(obj,'ssfi');flagMsg=flagMsg?flagMsg+': ':'';obj=flag$3(obj,'object');types=types.map(function(t){return t.toLowerCase();});types.sort();// Transforms ['lorem', 'ipsum'] into 'a lorem, or an ipsum' + var str=types.map(function(t,index){var art=~['a','e','i','o','u'].indexOf(t.charAt(0))?'an':'a';var or=types.length>1&&index===types.length-1?'or ':'';return or+art+' '+t;}).join(', ');var objType=type$2(obj).toLowerCase();if(!types.some(function(expected){return objType===expected;})){throw new AssertionError(flagMsg+'object tested must be '+str+', but '+objType+' given',undefined,ssfi);}};/*! + * Chai - getActual utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getActual + */var getActual$1=function getActual(obj,args){return args.length>4?args[4]:obj._obj;};/* ! + * Chai - getFuncName utility + * Copyright(c) 2012-2016 Jake Luer + * MIT Licensed + */ /** + * ### .getFuncName(constructorFn) * - * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */function mapCacheGet(key){return getMapData(this,key).get(key);}/** - * Checks if a map value for `key` exists. + * Returns the name of a function. + * When a non-function instance is passed, returns `null`. + * This also includes a polyfill function if `aFunc.name` is not defined. * - * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */function mapCacheHas(key){return getMapData(this,key).has(key);}/** - * Sets the map `key` to `value`. + * @name getFuncName + * @param {Function} funct + * @namespace Utils + * @api public + */var toString$1=Function.prototype.toString;var functionNameMatch=/\s*function(?:\s|\s*\/\*[^(?:*\/)]+\*\/\s*)*([^\s\(\/]+)/;var maxFunctionSourceLength=512;function getFuncName(aFunc){if(typeof aFunc!=='function'){return null;}var name='';if(typeof Function.prototype.name==='undefined'&&typeof aFunc.name==='undefined'){// eslint-disable-next-line prefer-reflect + var functionSource=toString$1.call(aFunc);// To avoid unconstrained resource consumption due to pathalogically large function names, + // we limit the available return value to be less than 512 characters. + if(functionSource.indexOf('(')>maxFunctionSourceLength){return name;}// Here we run a polyfill if Function does not support the `name` property and if aFunc.name is not defined + var match=functionSource.match(functionNameMatch);if(match){name=match[1];}}else {// If we've got a `name` property we just use it + name=aFunc.name;}return name;}var getFuncName_1=getFuncName;var getFuncName$1=/*@__PURE__*/getDefaultExportFromCjs(getFuncName_1);var ansiColors={bold:['1','22'],dim:['2','22'],italic:['3','23'],underline:['4','24'],// 5 & 6 are blinking + inverse:['7','27'],hidden:['8','28'],strike:['9','29'],// 10-20 are fonts + // 21-29 are resets for 1-9 + black:['30','39'],red:['31','39'],green:['32','39'],yellow:['33','39'],blue:['34','39'],magenta:['35','39'],cyan:['36','39'],white:['37','39'],brightblack:['30;1','39'],brightred:['31;1','39'],brightgreen:['32;1','39'],brightyellow:['33;1','39'],brightblue:['34;1','39'],brightmagenta:['35;1','39'],brightcyan:['36;1','39'],brightwhite:['37;1','39'],grey:['90','39']};var styles={special:'cyan',number:'yellow',bigint:'yellow',"boolean":'yellow',undefined:'grey',"null":'bold',string:'green',symbol:'green',date:'magenta',regexp:'red'};var truncator='…';function colorise(value,styleType){var color=ansiColors[styles[styleType]]||ansiColors[styleType];if(!color){return String(value);}return "\x1B[".concat(color[0],"m").concat(String(value),"\x1B[").concat(color[1],"m");}function normaliseOptions(){var _ref28=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{},_ref28$showHidden=_ref28.showHidden,showHidden=_ref28$showHidden===void 0?false:_ref28$showHidden,_ref28$depth=_ref28.depth,depth=_ref28$depth===void 0?2:_ref28$depth,_ref28$colors=_ref28.colors,colors=_ref28$colors===void 0?false:_ref28$colors,_ref28$customInspect=_ref28.customInspect,customInspect=_ref28$customInspect===void 0?true:_ref28$customInspect,_ref28$showProxy=_ref28.showProxy,showProxy=_ref28$showProxy===void 0?false:_ref28$showProxy,_ref28$maxArrayLength=_ref28.maxArrayLength,maxArrayLength=_ref28$maxArrayLength===void 0?Infinity:_ref28$maxArrayLength,_ref28$breakLength=_ref28.breakLength,breakLength=_ref28$breakLength===void 0?Infinity:_ref28$breakLength,_ref28$seen=_ref28.seen,seen=_ref28$seen===void 0?[]:_ref28$seen,_ref28$truncate=_ref28.truncate,truncate=_ref28$truncate===void 0?Infinity:_ref28$truncate,_ref28$stylize=_ref28.stylize,stylize=_ref28$stylize===void 0?String:_ref28$stylize;var options={showHidden:Boolean(showHidden),depth:Number(depth),colors:Boolean(colors),customInspect:Boolean(customInspect),showProxy:Boolean(showProxy),maxArrayLength:Number(maxArrayLength),breakLength:Number(breakLength),truncate:Number(truncate),seen:seen,stylize:stylize};if(options.colors){options.stylize=colorise;}return options;}function truncate(string,length){var tail=arguments.length>2&&arguments[2]!==undefined?arguments[2]:truncator;string=String(string);var tailLength=tail.length;var stringLength=string.length;if(tailLength>length&&stringLength>tailLength){return tail;}if(stringLength>length&&stringLength>tailLength){return "".concat(string.slice(0,length-tailLength)).concat(tail);}return string;}// eslint-disable-next-line complexity + function inspectList(list,options,inspectItem){var separator=arguments.length>3&&arguments[3]!==undefined?arguments[3]:', ';inspectItem=inspectItem||options.inspect;var size=list.length;if(size===0)return '';var originalLength=options.truncate;var output='';var peek='';var truncated='';for(var i=0;ioriginalLength&&output.length+truncated.length<=originalLength){break;}// If this isn't the last or second to last element to scan, + // but the string is already over length then break here + if(!last&&!secondToLast&&truncatedLength>originalLength){break;}// Peek at the next string to determine if we should + // break early before adding this item to the output + peek=last?'':inspectItem(list[i+1],options)+(secondToLast?'':separator);// If we have one element left, but this element and + // the next takes over length, the break early + if(!last&&secondToLast&&truncatedLength>originalLength&&nextLength+peek.length>originalLength){break;}output+=string;// If the next element takes us to length - + // but there are more after that, then we should truncate now + if(!last&&!secondToLast&&nextLength+peek.length>=originalLength){truncated="".concat(truncator,"(").concat(list.length-i-1,")");break;}truncated='';}return "".concat(output).concat(truncated);}function quoteComplexKey(key){if(key.match(/^[a-zA-Z_][a-zA-Z_0-9]*$/)){return key;}return JSON.stringify(key).replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'");}function inspectProperty(_ref29,options){var _ref30=_slicedToArray(_ref29,2),key=_ref30[0],value=_ref30[1];options.truncate-=2;if(typeof key==='string'){key=quoteComplexKey(key);}else if(typeof key!=='number'){key="[".concat(options.inspect(key,options),"]");}options.truncate-=key.length;value=options.inspect(value,options);return "".concat(key,": ").concat(value);}function inspectArray(array,options){// Object.keys will always output the Array indices first, so we can slice by + // `array.length` to get non-index properties + var nonIndexProperties=Object.keys(array).slice(array.length);if(!array.length&&!nonIndexProperties.length)return '[]';options.truncate-=4;var listContents=inspectList(array,options);options.truncate-=listContents.length;var propertyContents='';if(nonIndexProperties.length){propertyContents=inspectList(nonIndexProperties.map(function(key){return [key,array[key]];}),options,inspectProperty);}return "[ ".concat(listContents).concat(propertyContents?", ".concat(propertyContents):''," ]");}var getArrayName=function getArrayName(array){// We need to special case Node.js' Buffers, which report to be Uint8Array + if(typeof Buffer==='function'&&array instanceof Buffer){return 'Buffer';}if(array[Symbol.toStringTag]){return array[Symbol.toStringTag];}return getFuncName$1(array.constructor);};function inspectTypedArray(array,options){var name=getArrayName(array);options.truncate-=name.length+4;// Object.keys will always output the Array indices first, so we can slice by + // `array.length` to get non-index properties + var nonIndexProperties=Object.keys(array).slice(array.length);if(!array.length&&!nonIndexProperties.length)return "".concat(name,"[]");// As we know TypedArrays only contain Unsigned Integers, we can skip inspecting each one and simply + // stylise the toString() value of them + var output='';for(var i=0;i ").concat(value);}// IE11 doesn't support `map.entries()` + function mapToEntries(map){var entries=[];map.forEach(function(value,key){entries.push([key,value]);});return entries;}function inspectMap(map,options){var size=map.size-1;if(size<=0){return 'Map{}';}options.truncate-=7;return "Map{ ".concat(inspectList(mapToEntries(map),options,inspectMapEntry)," }");}var isNaN$2=Number.isNaN||function(i){return i!==i;};// eslint-disable-line no-self-compare + function inspectNumber(number,options){if(isNaN$2(number)){return options.stylize('NaN','number');}if(number===Infinity){return options.stylize('Infinity','number');}if(number===-Infinity){return options.stylize('-Infinity','number');}if(number===0){return options.stylize(1/number===Infinity?'+0':'-0','number');}return options.stylize(truncate(number,options.truncate),'number');}function inspectBigInt(number,options){var nums=truncate(number.toString(),options.truncate-1);if(nums!==truncator)nums+='n';return options.stylize(nums,'bigint');}function inspectRegExp(value,options){var flags=value.toString().split('/')[2];var sourceLength=options.truncate-(2+flags.length);var source=value.source;return options.stylize("/".concat(truncate(source,sourceLength),"/").concat(flags),'regexp');}// IE11 doesn't support `Array.from(set)` + function arrayFromSet(set){var values=[];set.forEach(function(value){values.push(value);});return values;}function inspectSet(set,options){if(set.size===0)return 'Set{}';options.truncate-=7;return "Set{ ".concat(inspectList(arrayFromSet(set),options)," }");}var stringEscapeChars=new RegExp("['\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5"+"\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]",'g');var escapeCharacters={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r',"'":"\\'",'\\':'\\\\'};var hex=16;var unicodeLength=4;function escape(_char){return escapeCharacters[_char]||"\\u".concat("0000".concat(_char.charCodeAt(0).toString(hex)).slice(-unicodeLength));}function inspectString(string,options){if(stringEscapeChars.test(string)){string=string.replace(stringEscapeChars,escape);}return options.stylize("'".concat(truncate(string,options.truncate-2),"'"),'string');}function inspectSymbol(value){if('description'in Symbol.prototype){return value.description?"Symbol(".concat(value.description,")"):'Symbol()';}return value.toString();}var getPromiseValue=function getPromiseValue(){return 'Promise{…}';};try{var _process$binding=process.binding('util'),getPromiseDetails=_process$binding.getPromiseDetails,kPending=_process$binding.kPending,kRejected=_process$binding.kRejected;if(Array.isArray(getPromiseDetails(Promise.resolve()))){getPromiseValue=function getPromiseValue(value,options){var _getPromiseDetails=getPromiseDetails(value),_getPromiseDetails2=_slicedToArray(_getPromiseDetails,2),state=_getPromiseDetails2[0],innerValue=_getPromiseDetails2[1];if(state===kPending){return 'Promise{}';}return "Promise".concat(state===kRejected?'!':'',"{").concat(options.inspect(innerValue,options),"}");};}}catch(notNode){/* ignore */}var inspectPromise=getPromiseValue;function inspectObject$1(object,options){var properties=Object.getOwnPropertyNames(object);var symbols=Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(object):[];if(properties.length===0&&symbols.length===0){return '{}';}options.truncate-=4;options.seen=options.seen||[];if(options.seen.indexOf(object)>=0){return '[Circular]';}options.seen.push(object);var propertyContents=inspectList(properties.map(function(key){return [key,object[key]];}),options,inspectProperty);var symbolContents=inspectList(symbols.map(function(key){return [key,object[key]];}),options,inspectProperty);options.seen.pop();var sep='';if(propertyContents&&symbolContents){sep=', ';}return "{ ".concat(propertyContents).concat(sep).concat(symbolContents," }");}var toStringTag=typeof Symbol!=='undefined'&&Symbol.toStringTag?Symbol.toStringTag:false;function inspectClass(value,options){var name='';if(toStringTag&&toStringTag in value){name=value[toStringTag];}name=name||getFuncName$1(value.constructor);// Babel transforms anonymous classes to the name `_class` + if(!name||name==='_class'){name='';}options.truncate-=name.length;return "".concat(name).concat(inspectObject$1(value,options));}function inspectArguments(args,options){if(args.length===0)return 'Arguments[]';options.truncate-=13;return "Arguments[ ".concat(inspectList(args,options)," ]");}var errorKeys=['stack','line','column','name','message','fileName','lineNumber','columnNumber','number','description'];function inspectObject(error,options){var properties=Object.getOwnPropertyNames(error).filter(function(key){return errorKeys.indexOf(key)===-1;});var name=error.name;options.truncate-=name.length;var message='';if(typeof error.message==='string'){message=truncate(error.message,options.truncate);}else {properties.unshift('message');}message=message?": ".concat(message):'';options.truncate-=message.length+5;var propertyContents=inspectList(properties.map(function(key){return [key,error[key]];}),options,inspectProperty);return "".concat(name).concat(message).concat(propertyContents?" { ".concat(propertyContents," }"):'');}function inspectAttribute(_ref33,options){var _ref34=_slicedToArray(_ref33,2),key=_ref34[0],value=_ref34[1];options.truncate-=3;if(!value){return "".concat(options.stylize(key,'yellow'));}return "".concat(options.stylize(key,'yellow'),"=").concat(options.stylize("\"".concat(value,"\""),'string'));}function inspectHTMLCollection(collection,options){// eslint-disable-next-line no-use-before-define + return inspectList(collection,options,inspectHTML,'\n');}function inspectHTML(element,options){var properties=element.getAttributeNames();var name=element.tagName.toLowerCase();var head=options.stylize("<".concat(name),'special');var headClose=options.stylize(">",'special');var tail=options.stylize(""),'special');options.truncate-=name.length*2+5;var propertyContents='';if(properties.length>0){propertyContents+=' ';propertyContents+=inspectList(properties.map(function(key){return [key,element.getAttribute(key)];}),options,inspectAttribute,' ');}options.truncate-=propertyContents.length;var truncate=options.truncate;var children=inspectHTMLCollection(element.children,options);if(children&&children.length>truncate){children="".concat(truncator,"(").concat(element.children.length,")");}return "".concat(head).concat(propertyContents).concat(headClose).concat(children).concat(tail);}/* ! + * loupe + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */var symbolsSupported=typeof Symbol==='function'&&typeof Symbol["for"]==='function';var chaiInspect=symbolsSupported?Symbol["for"]('chai/inspect'):'@@chai/inspect';var nodeInspect=false;try{// eslint-disable-next-line global-require + var nodeUtil=require('util');nodeInspect=nodeUtil.inspect?nodeUtil.inspect.custom:false;}catch(noNodeInspect){nodeInspect=false;}function FakeMap$1(){// eslint-disable-next-line prefer-template + this.key='chai/loupe__'+Math.random()+Date.now();}FakeMap$1.prototype={// eslint-disable-next-line object-shorthand + get:function get(key){return key[this.key];},// eslint-disable-next-line object-shorthand + has:function has(key){return this.key in key;},// eslint-disable-next-line object-shorthand + set:function set(key,value){if(Object.isExtensible(key)){Object.defineProperty(key,this.key,{// eslint-disable-next-line object-shorthand + value:value,configurable:true});}}};var constructorMap=new(typeof WeakMap==='function'?WeakMap:FakeMap$1)();var stringTagMap={};var baseTypesMap={undefined:function undefined$1(value,options){return options.stylize('undefined','undefined');},"null":function _null(value,options){return options.stylize(null,'null');},"boolean":function boolean(value,options){return options.stylize(value,'boolean');},Boolean:function Boolean(value,options){return options.stylize(value,'boolean');},number:inspectNumber,Number:inspectNumber,bigint:inspectBigInt,BigInt:inspectBigInt,string:inspectString,String:inspectString,"function":inspectFunction,Function:inspectFunction,symbol:inspectSymbol,// A Symbol polyfill will return `Symbol` not `symbol` from typedetect + Symbol:inspectSymbol,Array:inspectArray,Date:inspectDate,Map:inspectMap,Set:inspectSet,RegExp:inspectRegExp,Promise:inspectPromise,// WeakSet, WeakMap are totally opaque to us + WeakSet:function WeakSet(value,options){return options.stylize('WeakSet{…}','special');},WeakMap:function WeakMap(value,options){return options.stylize('WeakMap{…}','special');},Arguments:inspectArguments,Int8Array:inspectTypedArray,Uint8Array:inspectTypedArray,Uint8ClampedArray:inspectTypedArray,Int16Array:inspectTypedArray,Uint16Array:inspectTypedArray,Int32Array:inspectTypedArray,Uint32Array:inspectTypedArray,Float32Array:inspectTypedArray,Float64Array:inspectTypedArray,Generator:function Generator(){return '';},DataView:function DataView(){return '';},ArrayBuffer:function ArrayBuffer(){return '';},Error:inspectObject,HTMLCollection:inspectHTMLCollection,NodeList:inspectHTMLCollection};// eslint-disable-next-line complexity + var inspectCustom=function inspectCustom(value,options,type){if(chaiInspect in value&&typeof value[chaiInspect]==='function'){return value[chaiInspect](options);}if(nodeInspect&&nodeInspect in value&&typeof value[nodeInspect]==='function'){return value[nodeInspect](options.depth,options);}if('inspect'in value&&typeof value.inspect==='function'){return value.inspect(options.depth,options);}if('constructor'in value&&constructorMap.has(value.constructor)){return constructorMap.get(value.constructor)(value,options);}if(stringTagMap[type]){return stringTagMap[type](value,options);}return '';};var toString=Object.prototype.toString;// eslint-disable-next-line complexity + function inspect$3(value,options){options=normaliseOptions(options);options.inspect=inspect$3;var _options=options,customInspect=_options.customInspect;var type=value===null?'null':_typeof$1(value);if(type==='object'){type=toString.call(value).slice(8,-1);}// If it is a base value that we already support, then use Loupe's inspector + if(baseTypesMap[type]){return baseTypesMap[type](value,options);}// If `options.customInspect` is set to true then try to use the custom inspector + if(customInspect&&value){var output=inspectCustom(value,options,type);if(output){if(typeof output==='string')return output;return inspect$3(output,options);}}var proto=value?Object.getPrototypeOf(value):false;// If it's a plain Object then use Loupe's inspector + if(proto===Object.prototype||proto===null){return inspectObject$1(value,options);}// Specifically account for HTMLElements + // eslint-disable-next-line no-undef + if(value&&typeof HTMLElement==='function'&&value instanceof HTMLElement){return inspectHTML(value,options);}if('constructor'in value){// If it is a class, inspect it like an object but add the constructor name + if(value.constructor!==Object){return inspectClass(value,options);}// If it is an object with an anonymous prototype, display it as an object. + return inspectObject$1(value,options);}// last chance to check if it's an object + if(value===Object(value)){return inspectObject$1(value,options);}// We have run out of options! Just stringify the value + return options.stylize(String(value),type);}function registerConstructor(constructor,inspector){if(constructorMap.has(constructor)){return false;}constructorMap.set(constructor,inspector);return true;}function registerStringTag(stringTag,inspector){if(stringTag in stringTagMap){return false;}stringTagMap[stringTag]=inspector;return true;}var custom=chaiInspect;var loupe$1=/*#__PURE__*/Object.freeze({__proto__:null,inspect:inspect$3,registerConstructor:registerConstructor,registerStringTag:registerStringTag,custom:custom,'default':inspect$3});var require$$1=/*@__PURE__*/getAugmentedNamespace(loupe$1);var config$5={/** + * ### config.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message. + * + * chai.config.includeStack = true; // enable stack on error + * + * @param {Boolean} + * @api public + */includeStack:false,/** + * ### config.showDiff + * + * User configurable property, influences whether or not + * the `showDiff` flag should be included in the thrown + * AssertionErrors. `false` will always be `false`; `true` + * will be true when the assertion has requested a diff + * be shown. + * + * @param {Boolean} + * @api public + */showDiff:true,/** + * ### config.truncateThreshold + * + * User configurable property, sets length threshold for actual and + * expected values in assertion errors. If this threshold is exceeded, for + * example for large data structures, the value is replaced with something + * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. + * + * Set it to zero if you want to disable truncating altogether. + * + * This is especially userful when doing assertions on arrays: having this + * set to a reasonable large value makes the failure messages readily + * inspectable. + * + * chai.config.truncateThreshold = 0; // disable truncating + * + * @param {Number} + * @api public + */truncateThreshold:40,/** + * ### config.useProxy + * + * User configurable property, defines if chai will use a Proxy to throw + * an error when a non-existent property is read, which protects users + * from typos when using property-based assertions. + * + * Set it to false if you want to disable this feature. + * + * chai.config.useProxy = false; // disable use of Proxy + * + * This feature is automatically disabled regardless of this config value + * in environments that don't support proxies. + * + * @param {Boolean} + * @api public + */useProxy:true,/** + * ### config.proxyExcludedKeys + * + * User configurable property, defines which properties should be ignored + * instead of throwing an error if they do not exist on the assertion. + * This is only applied if the environment Chai is running in supports proxies and + * if the `useProxy` configuration setting is enabled. + * By default, `then` and `inspect` will not throw an error if they do not exist on the + * assertion object because the `.inspect` property is read by `util.inspect` (for example, when + * using `console.log` on the assertion object) and `.then` is necessary for promise type-checking. + * + * // By default these keys will not throw an error if they do not exist on the assertion object + * chai.config.proxyExcludedKeys = ['then', 'inspect']; + * + * @param {Array} + * @api public + */proxyExcludedKeys:['then','catch','inspect','toJSON']};var loupe=require$$1;var config$4=config$5;var inspect_1=inspect$2;/** + * ### .inspect(obj, [showHidden], [depth], [colors]) * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */function mapCacheSet(key,value){getMapData(this,key).set(key,value);return this;}// Add methods to `MapCache`. - MapCache.prototype.clear=mapCacheClear;MapCache.prototype['delete']=mapCacheDelete;MapCache.prototype.get=mapCacheGet;MapCache.prototype.has=mapCacheHas;MapCache.prototype.set=mapCacheSet;/** - * Gets the index at which the `key` is found in `array` of key-value pairs. + * Echoes the value of a value. Tries to print the value out + * in the best way possible given the different types. * - * @private - * @param {Array} array The array to inspect. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - */function assocIndexOf(array,key){var length=array.length;while(length--){if(eq(array[length][0],key)){return length;}}return -1;}/** - * The base implementation of `_.get` without support for default values. + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. Default is false. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + * @namespace Utils + * @name inspect + */function inspect$2(obj,showHidden,depth,colors){var options={colors:colors,depth:typeof depth==='undefined'?2:depth,showHidden:showHidden,truncate:config$4.truncateThreshold?config$4.truncateThreshold:Infinity};return loupe.inspect(obj,options);}/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /*! + * Module dependencies + */var inspect$1=inspect_1;var config$3=config$5;/** + * ### .objDisplay(object) * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @returns {*} Returns the resolved value. - */function baseGet(object,path){path=isKey(path,object)?[path]:castPath(path);var index=0,length=path.length;while(object!=null&&index=config$3.truncateThreshold){if(type==='[object Function]'){return !obj.name||obj.name===''?'[Function]':'[Function: '+obj.name+']';}else if(type==='[object Array]'){return '[ Array('+obj.length+') ]';}else if(type==='[object Object]'){var keys=Object.keys(obj),kstr=keys.length>2?keys.splice(0,2).join(', ')+', ...':keys.join(', ');return '{ Object ('+kstr+') }';}else {return str;}}else {return str;}};/*! + * Chai - message composition utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /*! + * Module dependencies + */var flag$2=flag$5,getActual=getActual$1,objDisplay=objDisplay$1;/** + * ### .getMessage(object, message, negateMessage) * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */function baseToString(value){// Exit early for strings to avoid a performance hit in some environments. - if(typeof value=='string'){return value;}if(isSymbol(value)){return symbolToString?symbolToString.call(value):'';}var result=value+'';return result=='0'&&1/value==-INFINITY?'-0':result;}/** - * Casts `value` to a path array if it's not one. + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. * - * @private - * @param {*} value The value to inspect. - * @returns {Array} Returns the cast property path array. - */function castPath(value){return isArray(value)?value:stringToPath(value);}/** - * Gets the data for `map`. + * Message template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value * - * @private - * @param {Object} map The map to query. - * @param {string} key The reference key. - * @returns {*} Returns the map data. - */function getMapData(map,key){var data=map.__data__;return isKeyable(key)?data[typeof key=='string'?'string':'hash']:data.map;}/** - * Gets the native function at `key` of `object`. + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getMessage + * @api public + */var getMessage$1=function getMessage(obj,args){var negate=flag$2(obj,'negate'),val=flag$2(obj,'object'),expected=args[3],actual=getActual(obj,args),msg=negate?args[2]:args[1],flagMsg=flag$2(obj,'message');if(typeof msg==="function")msg=msg();msg=msg||'';msg=msg.replace(/#\{this\}/g,function(){return objDisplay(val);}).replace(/#\{act\}/g,function(){return objDisplay(actual);}).replace(/#\{exp\}/g,function(){return objDisplay(expected);});return flagMsg?flagMsg+': '+msg:msg;};/*! + * Chai - transferFlags utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .transferFlags(assertion, object, includeAll = true) * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. - */function getNative(object,key){var value=getValue(object,key);return baseIsNative(value)?value:undefined;}/** - * Checks if `value` is a property name and not a property path. + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, `lockSsfi`, + * and `message`) will not be transferred. * - * @private - * @param {*} value The value to check. - * @param {Object} [object] The object to query keys on. - * @returns {boolean} Returns `true` if `value` is a property name, else `false`. - */function isKey(value,object){if(isArray(value)){return false;}var type=_typeof(value);if(type=='number'||type=='symbol'||type=='boolean'||value==null||isSymbol(value)){return true;}return reIsPlainProp.test(value)||!reIsDeepProp.test(value)||object!=null&&value in Object(object);}/** - * Checks if `value` is suitable for use as unique object key. * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is suitable, else `false`. - */function isKeyable(value){var type=_typeof(value);return type=='string'||type=='number'||type=='symbol'||type=='boolean'?value!=='__proto__':value===null;}/** - * Checks if `func` has its source masked. + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. - */function isMasked(func){return !!maskSrcKey&&maskSrcKey in func;}/** - * Converts `string` to a property path array. + * var anotherAssertion = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the property path array. - */var stringToPath=memoize(function(string){string=toString(string);var result=[];if(reLeadingDot.test(string)){result.push('');}string.replace(rePropName,function(match,number,quote,string){result.push(quote?string.replace(reEscapeChar,'$1'):number||match);});return result;});/** - * Converts `value` to a string key if it's not a string or symbol. + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags to; usually a new assertion + * @param {Boolean} includeAll + * @namespace Utils + * @name transferFlags + * @api private + */var transferFlags=function transferFlags(assertion,object,includeAll){var flags=assertion.__flags||(assertion.__flags=Object.create(null));if(!object.__flags){object.__flags=Object.create(null);}includeAll=arguments.length===3?includeAll:true;for(var flag in flags){if(includeAll||flag!=='object'&&flag!=='ssfi'&&flag!=='lockSsfi'&&flag!='message'){object.__flags[flag]=flags[flag];}}};var deepEql={exports:{}};/* globals Symbol: false, Uint8Array: false, WeakMap: false */ /*! + * deep-eql + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */var type$1=typeDetectExports;function FakeMap(){this._key='chai/deep-eql__'+Math.random()+Date.now();}FakeMap.prototype={get:function get(key){return key[this._key];},set:function set(key,value){if(Object.isExtensible(key)){Object.defineProperty(key,this._key,{value:value,configurable:true});}}};var MemoizeMap=typeof WeakMap==='function'?WeakMap:FakeMap;/*! + * Check to see if the MemoizeMap has recorded a result of the two operands * - * @private - * @param {*} value The value to inspect. - * @returns {string|symbol} Returns the key. - */function toKey(value){if(typeof value=='string'||isSymbol(value)){return value;}var result=value+'';return result=='0'&&1/value==-INFINITY?'-0':result;}/** - * Converts `func` to its source code. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {MemoizeMap} memoizeMap + * @returns {Boolean|null} result + */function memoizeCompare(leftHandOperand,rightHandOperand,memoizeMap){// Technically, WeakMap keys can *only* be objects, not primitives. + if(!memoizeMap||isPrimitive(leftHandOperand)||isPrimitive(rightHandOperand)){return null;}var leftHandMap=memoizeMap.get(leftHandOperand);if(leftHandMap){var result=leftHandMap.get(rightHandOperand);if(typeof result==='boolean'){return result;}}return null;}/*! + * Set the result of the equality into the MemoizeMap * - * @private - * @param {Function} func The function to process. - * @returns {string} Returns the source code. - */function toSource(func){if(func!=null){try{return funcToString.call(func);}catch(e){}try{return func+'';}catch(e){}}return '';}/** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided, it determines the cache key for storing the result based on the - * arguments provided to the memoized function. By default, the first argument - * provided to the memoized function is used as the map cache key. The `func` - * is invoked with the `this` binding of the memoized function. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {MemoizeMap} memoizeMap + * @param {Boolean} result + */function memoizeSet(leftHandOperand,rightHandOperand,memoizeMap,result){// Technically, WeakMap keys can *only* be objects, not primitives. + if(!memoizeMap||isPrimitive(leftHandOperand)||isPrimitive(rightHandOperand)){return;}var leftHandMap=memoizeMap.get(leftHandOperand);if(leftHandMap){leftHandMap.set(rightHandOperand,result);}else {leftHandMap=new MemoizeMap();leftHandMap.set(rightHandOperand,result);memoizeMap.set(leftHandOperand,leftHandMap);}}/*! + * Primary Export + */deepEql.exports=deepEqual;deepEql.exports.MemoizeMap=MemoizeMap;/** + * Assert deeply nested sameValue equality between two objects of any type. * - * **Note:** The cache is exposed as the `cache` property on the memoized - * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) - * method interface of `delete`, `get`, `has`, and `set`. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (optional) Additional options + * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality. + * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of + complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular + references to blow the stack. + * @return {Boolean} equal match + */function deepEqual(leftHandOperand,rightHandOperand,options){// If we have a comparator, we can't assume anything; so bail to its check first. + if(options&&options.comparator){return extensiveDeepEqual(leftHandOperand,rightHandOperand,options);}var simpleResult=simpleEqual(leftHandOperand,rightHandOperand);if(simpleResult!==null){return simpleResult;}// Deeper comparisons are pushed through to a larger function + return extensiveDeepEqual(leftHandOperand,rightHandOperand,options);}/** + * Many comparisons can be canceled out early via simple equality or primitive checks. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @return {Boolean|null} equal match + */function simpleEqual(leftHandOperand,rightHandOperand){// Equal references (except for Numbers) can be returned early + if(leftHandOperand===rightHandOperand){// Handle +-0 cases + return leftHandOperand!==0||1/leftHandOperand===1/rightHandOperand;}// handle NaN cases + if(leftHandOperand!==leftHandOperand&&// eslint-disable-line no-self-compare + rightHandOperand!==rightHandOperand// eslint-disable-line no-self-compare + ){return true;}// Anything that is not an 'object', i.e. symbols, functions, booleans, numbers, + // strings, and undefined, can be compared by reference. + if(isPrimitive(leftHandOperand)||isPrimitive(rightHandOperand)){// Easy out b/c it would have passed the first equality check + return false;}return null;}/*! + * The main logic of the `deepEqual` function. * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] The function to resolve the cache key. - * @returns {Function} Returns the new memoized function. - * @example + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (optional) Additional options + * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality. + * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of + complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular + references to blow the stack. + * @return {Boolean} equal match + */function extensiveDeepEqual(leftHandOperand,rightHandOperand,options){options=options||{};options.memoize=options.memoize===false?false:options.memoize||new MemoizeMap();var comparator=options&&options.comparator;// Check if a memoized result exists. + var memoizeResultLeft=memoizeCompare(leftHandOperand,rightHandOperand,options.memoize);if(memoizeResultLeft!==null){return memoizeResultLeft;}var memoizeResultRight=memoizeCompare(rightHandOperand,leftHandOperand,options.memoize);if(memoizeResultRight!==null){return memoizeResultRight;}// If a comparator is present, use it. + if(comparator){var comparatorResult=comparator(leftHandOperand,rightHandOperand);// Comparators may return null, in which case we want to go back to default behavior. + if(comparatorResult===false||comparatorResult===true){memoizeSet(leftHandOperand,rightHandOperand,options.memoize,comparatorResult);return comparatorResult;}// To allow comparators to override *any* behavior, we ran them first. Since it didn't decide + // what to do, we need to make sure to return the basic tests first before we move on. + var simpleResult=simpleEqual(leftHandOperand,rightHandOperand);if(simpleResult!==null){// Don't memoize this, it takes longer to set/retrieve than to just compare. + return simpleResult;}}var leftHandType=type$1(leftHandOperand);if(leftHandType!==type$1(rightHandOperand)){memoizeSet(leftHandOperand,rightHandOperand,options.memoize,false);return false;}// Temporarily set the operands in the memoize object to prevent blowing the stack + memoizeSet(leftHandOperand,rightHandOperand,options.memoize,true);var result=extensiveDeepEqualByType(leftHandOperand,rightHandOperand,leftHandType,options);memoizeSet(leftHandOperand,rightHandOperand,options.memoize,result);return result;}function extensiveDeepEqualByType(leftHandOperand,rightHandOperand,leftHandType,options){switch(leftHandType){case'String':case'Number':case'Boolean':case'Date':// If these types are their instance types (e.g. `new Number`) then re-deepEqual against their values + return deepEqual(leftHandOperand.valueOf(),rightHandOperand.valueOf());case'Promise':case'Symbol':case'function':case'WeakMap':case'WeakSet':return leftHandOperand===rightHandOperand;case'Error':return keysEqual(leftHandOperand,rightHandOperand,['name','message','code'],options);case'Arguments':case'Int8Array':case'Uint8Array':case'Uint8ClampedArray':case'Int16Array':case'Uint16Array':case'Int32Array':case'Uint32Array':case'Float32Array':case'Float64Array':case'Array':return iterableEqual(leftHandOperand,rightHandOperand,options);case'RegExp':return regexpEqual(leftHandOperand,rightHandOperand);case'Generator':return generatorEqual(leftHandOperand,rightHandOperand,options);case'DataView':return iterableEqual(new Uint8Array(leftHandOperand.buffer),new Uint8Array(rightHandOperand.buffer),options);case'ArrayBuffer':return iterableEqual(new Uint8Array(leftHandOperand),new Uint8Array(rightHandOperand),options);case'Set':return entriesEqual(leftHandOperand,rightHandOperand,options);case'Map':return entriesEqual(leftHandOperand,rightHandOperand,options);case'Temporal.PlainDate':case'Temporal.PlainTime':case'Temporal.PlainDateTime':case'Temporal.Instant':case'Temporal.ZonedDateTime':case'Temporal.PlainYearMonth':case'Temporal.PlainMonthDay':return leftHandOperand.equals(rightHandOperand);case'Temporal.Duration':return leftHandOperand.total('nanoseconds')===rightHandOperand.total('nanoseconds');case'Temporal.TimeZone':case'Temporal.Calendar':return leftHandOperand.toString()===rightHandOperand.toString();default:return objectEqual(leftHandOperand,rightHandOperand,options);}}/*! + * Compare two Regular Expressions for equality. * - * var object = { 'a': 1, 'b': 2 }; - * var other = { 'c': 3, 'd': 4 }; + * @param {RegExp} leftHandOperand + * @param {RegExp} rightHandOperand + * @return {Boolean} result + */function regexpEqual(leftHandOperand,rightHandOperand){return leftHandOperand.toString()===rightHandOperand.toString();}/*! + * Compare two Sets/Maps for equality. Faster than other equality functions. * - * var values = _.memoize(_.values); - * values(object); - * // => [1, 2] + * @param {Set} leftHandOperand + * @param {Set} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */function entriesEqual(leftHandOperand,rightHandOperand,options){// IE11 doesn't support Set#entries or Set#@@iterator, so we need manually populate using Set#forEach + if(leftHandOperand.size!==rightHandOperand.size){return false;}if(leftHandOperand.size===0){return true;}var leftHandItems=[];var rightHandItems=[];leftHandOperand.forEach(function gatherEntries(key,value){leftHandItems.push([key,value]);});rightHandOperand.forEach(function gatherEntries(key,value){rightHandItems.push([key,value]);});return iterableEqual(leftHandItems.sort(),rightHandItems.sort(),options);}/*! + * Simple equality for flat iterable objects such as Arrays, TypedArrays or Node.js buffers. * - * values(other); - * // => [3, 4] + * @param {Iterable} leftHandOperand + * @param {Iterable} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */function iterableEqual(leftHandOperand,rightHandOperand,options){var length=leftHandOperand.length;if(length!==rightHandOperand.length){return false;}if(length===0){return true;}var index=-1;while(++index [1, 2] + * @param {Iterable} leftHandOperand + * @param {Iterable} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */function generatorEqual(leftHandOperand,rightHandOperand,options){return iterableEqual(getGeneratorEntries(leftHandOperand),getGeneratorEntries(rightHandOperand),options);}/*! + * Determine if the given object has an @@iterator function. * - * // Modify the result cache. - * values.cache.set(object, ['a', 'b']); - * values(object); - * // => ['a', 'b'] + * @param {Object} target + * @return {Boolean} `true` if the object has an @@iterator function. + */function hasIteratorFunction(target){return typeof Symbol!=='undefined'&&_typeof$1(target)==='object'&&typeof Symbol.iterator!=='undefined'&&typeof target[Symbol.iterator]==='function';}/*! + * Gets all iterator entries from the given Object. If the Object has no @@iterator function, returns an empty array. + * This will consume the iterator - which could have side effects depending on the @@iterator implementation. * - * // Replace `_.memoize.Cache`. - * _.memoize.Cache = WeakMap; - */function memoize(func,resolver){if(typeof func!='function'||resolver&&typeof resolver!='function'){throw new TypeError(FUNC_ERROR_TEXT);}var memoized=function memoized(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key);}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result;};memoized.cache=new(memoize.Cache||MapCache)();return memoized;}// Assign cache to `_.memoize`. - memoize.Cache=MapCache;/** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. + * @param {Object} target + * @returns {Array} an array of entries from the @@iterator function + */function getIteratorEntries(target){if(hasIteratorFunction(target)){try{return getGeneratorEntries(target[Symbol.iterator]());}catch(iteratorError){return [];}}return [];}/*! + * Gets all entries from a Generator. This will consume the generator - which could have side effects. * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example + * @param {Generator} target + * @returns {Array} an array of entries from the Generator. + */function getGeneratorEntries(generator){var generatorResult=generator.next();var accumulator=[generatorResult.value];while(generatorResult.done===false){generatorResult=generator.next();accumulator.push(generatorResult.value);}return accumulator;}/*! + * Gets all own and inherited enumerable keys from a target. * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; + * @param {Object} target + * @returns {Array} an array of own and inherited enumerable keys from the target. + */function getEnumerableKeys(target){var keys=[];for(var key in target){keys.push(key);}return keys;}function getEnumerableSymbols(target){var keys=[];var allKeys=Object.getOwnPropertySymbols(target);for(var i=0;i true + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Array} keys An array of keys to compare the values of leftHandOperand and rightHandOperand against + * @param {Object} [options] (Optional) + * @return {Boolean} result + */function keysEqual(leftHandOperand,rightHandOperand,keys,options){var length=keys.length;if(length===0){return true;}for(var i=0;i false + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */function objectEqual(leftHandOperand,rightHandOperand,options){var leftHandKeys=getEnumerableKeys(leftHandOperand);var rightHandKeys=getEnumerableKeys(rightHandOperand);var leftHandSymbols=getEnumerableSymbols(leftHandOperand);var rightHandSymbols=getEnumerableSymbols(rightHandOperand);leftHandKeys=leftHandKeys.concat(leftHandSymbols);rightHandKeys=rightHandKeys.concat(rightHandSymbols);if(leftHandKeys.length&&leftHandKeys.length===rightHandKeys.length){if(iterableEqual(mapSymbols(leftHandKeys).sort(),mapSymbols(rightHandKeys).sort())===false){return false;}return keysEqual(leftHandOperand,rightHandOperand,leftHandKeys,options);}var leftHandEntries=getIteratorEntries(leftHandOperand);var rightHandEntries=getIteratorEntries(rightHandOperand);if(leftHandEntries.length&&leftHandEntries.length===rightHandEntries.length){leftHandEntries.sort();rightHandEntries.sort();return iterableEqual(leftHandEntries,rightHandEntries,options);}if(leftHandKeys.length===0&&leftHandEntries.length===0&&rightHandKeys.length===0&&rightHandEntries.length===0){return true;}return false;}/*! + * Returns true if the argument is a primitive. * - * _.eq('a', 'a'); - * // => true + * This intentionally returns true for all objects that can be compared by reference, + * including functions and symbols. * - * _.eq('a', Object('a')); - * // => false + * @param {Mixed} value + * @return {Boolean} result + */function isPrimitive(value){return value===null||_typeof$1(value)!=='object';}function mapSymbols(arr){return arr.map(function mapSymbol(entry){if(_typeof$1(entry)==='symbol'){return entry.toString();}return entry;});}var deepEqlExports=deepEql.exports;var config$2=config$5;/*! + * Chai - isProxyEnabled helper + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .isProxyEnabled() * - * _.eq(NaN, NaN); - * // => true - */function eq(value,other){return value===other||value!==value&&other!==other;}/** - * Checks if `value` is classified as an `Array` object. + * Helper function to check if Chai's proxy protection feature is enabled. If + * proxies are unsupported or disabled via the user's Chai config, then return + * false. Otherwise, return true. * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example + * @namespace Utils + * @name isProxyEnabled + */var isProxyEnabled$1=function isProxyEnabled(){return config$2.useProxy&&typeof Proxy!=='undefined'&&typeof Reflect!=='undefined';};/*! + * Chai - addProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var addProperty;var hasRequiredAddProperty;function requireAddProperty(){if(hasRequiredAddProperty)return addProperty;hasRequiredAddProperty=1;var chai=requireChai();var flag=flag$5;var isProxyEnabled=isProxyEnabled$1;var transferFlags$1=transferFlags;/** + * ### .addProperty(ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @namespace Utils + * @name addProperty + * @api public + */addProperty=function addProperty(ctx,name,getter){getter=getter===undefined?function(){}:getter;Object.defineProperty(ctx,name,{get:function propertyGetter(){// Setting the `ssfi` flag to `propertyGetter` causes this function to + // be the starting point for removing implementation frames from the + // stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set and proxy protection is disabled. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked + // from inside of another assertion. In the first case, the `ssfi` flag + // has already been set by the overwriting assertion. In the second + // case, the `ssfi` flag has already been set by the outer assertion. + // + // If proxy protection is enabled, then the `ssfi` flag has already been + // set by the proxy getter. + if(!isProxyEnabled()&&!flag(this,'lockSsfi')){flag(this,'ssfi',propertyGetter);}var result=getter.call(this);if(result!==undefined)return result;var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;},configurable:true});};return addProperty;}var fnLengthDesc=Object.getOwnPropertyDescriptor(function(){},'length');/*! + * Chai - addLengthGuard utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .addLengthGuard(fn, assertionName, isChainable) * - * _.isArray([1, 2, 3]); - * // => true + * Define `length` as a getter on the given uninvoked method assertion. The + * getter acts as a guard against chaining `length` directly off of an uninvoked + * method assertion, which is a problem because it references `function`'s + * built-in `length` property instead of Chai's `length` assertion. When the + * getter catches the user making this mistake, it throws an error with a + * helpful message. * - * _.isArray(document.body.children); - * // => false + * There are two ways in which this mistake can be made. The first way is by + * chaining the `length` assertion directly off of an uninvoked chainable + * method. In this case, Chai suggests that the user use `lengthOf` instead. The + * second way is by chaining the `length` assertion directly off of an uninvoked + * non-chainable method. Non-chainable methods must be invoked prior to + * chaining. In this case, Chai suggests that the user consult the docs for the + * given assertion. * - * _.isArray('abc'); - * // => false + * If the `length` property of functions is unconfigurable, then return `fn` + * without modification. * - * _.isArray(_.noop); - * // => false - */var isArray=Array.isArray;/** - * Checks if `value` is classified as a `Function` object. + * Note that in ES6, the function's `length` property is configurable, so once + * support for legacy environments is dropped, Chai's `length` property can + * replace the built-in function's `length` property, and this length guard will + * no longer be necessary. In the mean time, maintaining consistency across all + * environments is the priority. * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example + * @param {Function} fn + * @param {String} assertionName + * @param {Boolean} isChainable + * @namespace Utils + * @name addLengthGuard + */var addLengthGuard=function addLengthGuard(fn,assertionName,isChainable){if(!fnLengthDesc.configurable)return fn;Object.defineProperty(fn,'length',{get:function get(){if(isChainable){throw Error('Invalid Chai property: '+assertionName+'.length. Due'+' to a compatibility issue, "length" cannot directly follow "'+assertionName+'". Use "'+assertionName+'.lengthOf" instead.');}throw Error('Invalid Chai property: '+assertionName+'.length. See'+' docs for proper usage of "'+assertionName+'".');}});return fn;};/*! + * Chai - getProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .getProperties(object) * - * _.isFunction(_); - * // => true + * This allows the retrieval of property names of an object, enumerable or not, + * inherited or not. * - * _.isFunction(/abc/); - * // => false - */function isFunction(value){// The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8-9 which returns 'object' for typed array and other constructors. - var tag=isObject(value)?objectToString.call(value):'';return tag==funcTag||tag==genTag;}/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getProperties + * @api public + */var getProperties$1=function getProperties(object){var result=Object.getOwnPropertyNames(object);function addProperty(property){if(result.indexOf(property)===-1){result.push(property);}}var proto=Object.getPrototypeOf(object);while(proto!==null){Object.getOwnPropertyNames(proto).forEach(addProperty);proto=Object.getPrototypeOf(proto);}return result;};var config$1=config$5;var flag$1=flag$5;var getProperties=getProperties$1;var isProxyEnabled=isProxyEnabled$1;/*! + * Chai - proxify utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ /** + * ### .proxify(object) * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example + * Return a proxy of given object that throws an error when a non-existent + * property is read. By default, the root cause is assumed to be a misspelled + * property, and thus an attempt is made to offer a reasonable suggestion from + * the list of existing properties. However, if a nonChainableMethodName is + * provided, then the root cause is instead a failure to invoke a non-chainable + * method prior to reading the non-existent property. + * + * If proxies are unsupported or disabled via the user's Chai config, then + * return object without modification. + * + * @param {Object} obj + * @param {String} nonChainableMethodName + * @namespace Utils + * @name proxify + */var builtins=['__flags','__methods','_obj','assert'];var proxify=function proxify(obj,nonChainableMethodName){if(!isProxyEnabled())return obj;return new Proxy(obj,{get:function proxyGetter(target,property){// This check is here because we should not throw errors on Symbol properties + // such as `Symbol.toStringTag`. + // The values for which an error should be thrown can be configured using + // the `config.proxyExcludedKeys` setting. + if(typeof property==='string'&&config$1.proxyExcludedKeys.indexOf(property)===-1&&!Reflect.has(target,property)){// Special message for invalid property access of non-chainable methods. + if(nonChainableMethodName){throw Error('Invalid Chai property: '+nonChainableMethodName+'.'+property+'. See docs for proper usage of "'+nonChainableMethodName+'".');}// If the property is reasonably close to an existing Chai property, + // suggest that property to the user. Only suggest properties with a + // distance less than 4. + var suggestion=null;var suggestionDistance=4;getProperties(target).forEach(function(prop){if(!Object.prototype.hasOwnProperty(prop)&&builtins.indexOf(prop)===-1){var dist=stringDistanceCapped(property,prop,suggestionDistance);if(dist=cap){return cap;}var memo=[];// `memo` is a two-dimensional array containing distances. + // memo[i][j] is the distance between strA.slice(0, i) and + // strB.slice(0, j). + for(var i=0;i<=strA.length;i++){memo[i]=Array(strB.length+1).fill(0);memo[i][0]=i;}for(var j=0;j=cap){memo[i][j]=cap;continue;}memo[i][j]=Math.min(memo[i-1][j]+1,memo[i][j-1]+1,memo[i-1][j-1]+(ch===strB.charCodeAt(j-1)?0:1));}}return memo[strA.length][strB.length];}/*! + * Chai - addMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var addMethod;var hasRequiredAddMethod;function requireAddMethod(){if(hasRequiredAddMethod)return addMethod;hasRequiredAddMethod=1;var addLengthGuard$1=addLengthGuard;var chai=requireChai();var flag=flag$5;var proxify$1=proxify;var transferFlags$1=transferFlags;/** + * ### .addMethod(ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @namespace Utils + * @name addMethod + * @api public + */addMethod=function addMethod(ctx,name,method){var methodWrapper=function methodWrapper(){// Setting the `ssfi` flag to `methodWrapper` causes this function to be the + // starting point for removing implementation frames from the stack trace of + // a failed assertion. + // + // However, we only want to use this function as the starting point if the + // `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked from + // inside of another assertion. In the first case, the `ssfi` flag has + // already been set by the overwriting assertion. In the second case, the + // `ssfi` flag has already been set by the outer assertion. + if(!flag(this,'lockSsfi')){flag(this,'ssfi',methodWrapper);}var result=method.apply(this,arguments);if(result!==undefined)return result;var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;};addLengthGuard$1(methodWrapper,name,false);ctx[name]=proxify$1(methodWrapper,name);};return addMethod;}/*! + * Chai - overwriteProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var overwriteProperty;var hasRequiredOverwriteProperty;function requireOverwriteProperty(){if(hasRequiredOverwriteProperty)return overwriteProperty;hasRequiredOverwriteProperty=1;var chai=requireChai();var flag=flag$5;var isProxyEnabled=isProxyEnabled$1;var transferFlags$1=transferFlags;/** + * ### .overwriteProperty(ctx, name, fn) + * + * Overwrites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @namespace Utils + * @name overwriteProperty + * @api public + */overwriteProperty=function overwriteProperty(ctx,name,getter){var _get=Object.getOwnPropertyDescriptor(ctx,name),_super=function _super(){};if(_get&&'function'===typeof _get.get)_super=_get.get;Object.defineProperty(ctx,name,{get:function overwritingPropertyGetter(){// Setting the `ssfi` flag to `overwritingPropertyGetter` causes this + // function to be the starting point for removing implementation frames + // from the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set and proxy protection is disabled. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked + // from inside of another assertion. In the first case, the `ssfi` flag + // has already been set by the overwriting assertion. In the second + // case, the `ssfi` flag has already been set by the outer assertion. + // + // If proxy protection is enabled, then the `ssfi` flag has already been + // set by the proxy getter. + if(!isProxyEnabled()&&!flag(this,'lockSsfi')){flag(this,'ssfi',overwritingPropertyGetter);}// Setting the `lockSsfi` flag to `true` prevents the overwritten + // assertion from changing the `ssfi` flag. By this point, the `ssfi` + // flag is already set to the correct starting point for this assertion. + var origLockSsfi=flag(this,'lockSsfi');flag(this,'lockSsfi',true);var result=getter(_super).call(this);flag(this,'lockSsfi',origLockSsfi);if(result!==undefined){return result;}var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;},configurable:true});};return overwriteProperty;}/*! + * Chai - overwriteMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var overwriteMethod;var hasRequiredOverwriteMethod;function requireOverwriteMethod(){if(hasRequiredOverwriteMethod)return overwriteMethod;hasRequiredOverwriteMethod=1;var addLengthGuard$1=addLengthGuard;var chai=requireChai();var flag=flag$5;var proxify$1=proxify;var transferFlags$1=transferFlags;/** + * ### .overwriteMethod(ctx, name, fn) + * + * Overwrites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @namespace Utils + * @name overwriteMethod + * @api public + */overwriteMethod=function overwriteMethod(ctx,name,method){var _method=ctx[name],_super=function _super(){throw new Error(name+' is not a function');};if(_method&&'function'===typeof _method)_super=_method;var overwritingMethodWrapper=function overwritingMethodWrapper(){// Setting the `ssfi` flag to `overwritingMethodWrapper` causes this + // function to be the starting point for removing implementation frames from + // the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if the + // `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked from + // inside of another assertion. In the first case, the `ssfi` flag has + // already been set by the overwriting assertion. In the second case, the + // `ssfi` flag has already been set by the outer assertion. + if(!flag(this,'lockSsfi')){flag(this,'ssfi',overwritingMethodWrapper);}// Setting the `lockSsfi` flag to `true` prevents the overwritten assertion + // from changing the `ssfi` flag. By this point, the `ssfi` flag is already + // set to the correct starting point for this assertion. + var origLockSsfi=flag(this,'lockSsfi');flag(this,'lockSsfi',true);var result=method(_super).apply(this,arguments);flag(this,'lockSsfi',origLockSsfi);if(result!==undefined){return result;}var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;};addLengthGuard$1(overwritingMethodWrapper,name,false);ctx[name]=proxify$1(overwritingMethodWrapper,name);};return overwriteMethod;}/*! + * Chai - addChainingMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var addChainableMethod;var hasRequiredAddChainableMethod;function requireAddChainableMethod(){if(hasRequiredAddChainableMethod)return addChainableMethod;hasRequiredAddChainableMethod=1;/*! + * Module dependencies + */var addLengthGuard$1=addLengthGuard;var chai=requireChai();var flag=flag$5;var proxify$1=proxify;var transferFlags$1=transferFlags;/*! + * Module variables + */ // Check whether `Object.setPrototypeOf` is supported + var canSetPrototype=typeof Object.setPrototypeOf==='function';// Without `Object.setPrototypeOf` support, this module will need to add properties to a function. + // However, some of functions' own props are not configurable and should be skipped. + var testFn=function testFn(){};var excludeNames=Object.getOwnPropertyNames(testFn).filter(function(name){var propDesc=Object.getOwnPropertyDescriptor(testFn,name);// Note: PhantomJS 1.x includes `callee` as one of `testFn`'s own properties, + // but then returns `undefined` as the property descriptor for `callee`. As a + // workaround, we perform an otherwise unnecessary type-check for `propDesc`, + // and then filter it out if it's not an object as it should be. + if(_typeof$1(propDesc)!=='object')return true;return !propDesc.configurable;});// Cache `Function` properties + var call=Function.prototype.call,apply=Function.prototype.apply;/** + * ### .addChainableMethod(ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @namespace Utils + * @name addChainableMethod + * @api public + */addChainableMethod=function addChainableMethod(ctx,name,method,chainingBehavior){if(typeof chainingBehavior!=='function'){chainingBehavior=function chainingBehavior(){};}var chainableBehavior={method:method,chainingBehavior:chainingBehavior};// save the methods so we can overwrite them later, if we need to. + if(!ctx.__methods){ctx.__methods={};}ctx.__methods[name]=chainableBehavior;Object.defineProperty(ctx,name,{get:function chainableMethodGetter(){chainableBehavior.chainingBehavior.call(this);var chainableMethodWrapper=function chainableMethodWrapper(){// Setting the `ssfi` flag to `chainableMethodWrapper` causes this + // function to be the starting point for removing implementation + // frames from the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then this assertion is being + // invoked from inside of another assertion. In this case, the `ssfi` + // flag has already been set by the outer assertion. + // + // Note that overwriting a chainable method merely replaces the saved + // methods in `ctx.__methods` instead of completely replacing the + // overwritten assertion. Therefore, an overwriting assertion won't + // set the `ssfi` or `lockSsfi` flags. + if(!flag(this,'lockSsfi')){flag(this,'ssfi',chainableMethodWrapper);}var result=chainableBehavior.method.apply(this,arguments);if(result!==undefined){return result;}var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;};addLengthGuard$1(chainableMethodWrapper,name,true);// Use `Object.setPrototypeOf` if available + if(canSetPrototype){// Inherit all properties from the object by replacing the `Function` prototype + var prototype=Object.create(this);// Restore the `call` and `apply` methods from `Function` + prototype.call=call;prototype.apply=apply;Object.setPrototypeOf(chainableMethodWrapper,prototype);}// Otherwise, redefine all properties (slow!) + else {var asserterNames=Object.getOwnPropertyNames(ctx);asserterNames.forEach(function(asserterName){if(excludeNames.indexOf(asserterName)!==-1){return;}var pd=Object.getOwnPropertyDescriptor(ctx,asserterName);Object.defineProperty(chainableMethodWrapper,asserterName,pd);});}transferFlags$1(this,chainableMethodWrapper);return proxify$1(chainableMethodWrapper);},configurable:true});};return addChainableMethod;}/*! + * Chai - overwriteChainableMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */var overwriteChainableMethod;var hasRequiredOverwriteChainableMethod;function requireOverwriteChainableMethod(){if(hasRequiredOverwriteChainableMethod)return overwriteChainableMethod;hasRequiredOverwriteChainableMethod=1;var chai=requireChai();var transferFlags$1=transferFlags;/** + * ### .overwriteChainableMethod(ctx, name, method, chainingBehavior) + * + * Overwrites an already existing chainable method + * and provides access to the previous function or + * property. Must return functions to be used for + * name. + * + * utils.overwriteChainableMethod(chai.Assertion.prototype, 'lengthOf', + * function (_super) { + * } + * , function (_super) { + * } + * ); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteChainableMethod('foo', fn, fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.have.lengthOf(3); + * expect(myFoo).to.have.lengthOf.above(3); + * + * @param {Object} ctx object whose method / property is to be overwritten + * @param {String} name of method / property to overwrite + * @param {Function} method function that returns a function to be used for name + * @param {Function} chainingBehavior function that returns a function to be used for property + * @namespace Utils + * @name overwriteChainableMethod + * @api public + */overwriteChainableMethod=function overwriteChainableMethod(ctx,name,method,chainingBehavior){var chainableBehavior=ctx.__methods[name];var _chainingBehavior=chainableBehavior.chainingBehavior;chainableBehavior.chainingBehavior=function overwritingChainableMethodGetter(){var result=chainingBehavior(_chainingBehavior).call(this);if(result!==undefined){return result;}var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;};var _method=chainableBehavior.method;chainableBehavior.method=function overwritingChainableMethodWrapper(){var result=method(_method).apply(this,arguments);if(result!==undefined){return result;}var newAssertion=new chai.Assertion();transferFlags$1(this,newAssertion);return newAssertion;};};return overwriteChainableMethod;}/*! + * Chai - compareByInspect utility + * Copyright(c) 2011-2016 Jake Luer + * MIT Licensed + */ /*! + * Module dependencies + */var inspect=inspect_1;/** + * ### .compareByInspect(mixed, mixed) * - * _.isObject({}); - * // => true + * To be used as a compareFunction with Array.prototype.sort. Compares elements + * using inspect instead of default behavior of using toString so that Symbols + * and objects with irregular/missing toString can still be sorted without a + * TypeError. * - * _.isObject([1, 2, 3]); - * // => true + * @param {Mixed} first element to compare + * @param {Mixed} second element to compare + * @returns {Number} -1 if 'a' should come before 'b'; otherwise 1 + * @name compareByInspect + * @namespace Utils + * @api public + */var compareByInspect=function compareByInspect(a,b){return inspect(a) + * MIT Licensed + */ /** + * ### .getOwnEnumerablePropertySymbols(object) * - * _.isObject(_.noop); - * // => true + * This allows the retrieval of directly-owned enumerable property symbols of an + * object. This function is necessary because Object.getOwnPropertySymbols + * returns both enumerable and non-enumerable property symbols. * - * _.isObject(null); - * // => false - */function isObject(value){var type=_typeof(value);return !!value&&(type=='object'||type=='function');}/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getOwnEnumerablePropertySymbols + * @api public + */var getOwnEnumerablePropertySymbols$1=function getOwnEnumerablePropertySymbols(obj){if(typeof Object.getOwnPropertySymbols!=='function')return [];return Object.getOwnPropertySymbols(obj).filter(function(sym){return Object.getOwnPropertyDescriptor(obj,sym).enumerable;});};/*! + * Chai - getOwnEnumerableProperties utility + * Copyright(c) 2011-2016 Jake Luer + * MIT Licensed + */ /*! + * Module dependencies + */var getOwnEnumerablePropertySymbols=getOwnEnumerablePropertySymbols$1;/** + * ### .getOwnEnumerableProperties(object) * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example + * This allows the retrieval of directly-owned enumerable property names and + * symbols of an object. This function is necessary because Object.keys only + * returns enumerable property names, not enumerable property symbols. * - * _.isObjectLike({}); - * // => true + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getOwnEnumerableProperties + * @api public + */var getOwnEnumerableProperties=function getOwnEnumerableProperties(obj){return Object.keys(obj).concat(getOwnEnumerablePropertySymbols(obj));};/* ! + * Chai - checkError utility + * Copyright(c) 2012-2016 Jake Luer + * MIT Licensed + */var getFunctionName=getFuncName_1;/** + * ### .checkError * - * _.isObjectLike([1, 2, 3]); - * // => true + * Checks that an error conforms to a given set of criteria and/or retrieves information about it. * - * _.isObjectLike(_.noop); - * // => false + * @api public + */ /** + * ### .compatibleInstance(thrown, errorLike) * - * _.isObjectLike(null); - * // => false - */function isObjectLike(value){return !!value&&_typeof(value)=='object';}/** - * Checks if `value` is classified as a `Symbol` primitive or object. + * Checks if two instances are compatible (strict equal). + * Returns false if errorLike is not an instance of Error, because instances + * can only be compatible if they're both error instances. * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example + * @name compatibleInstance + * @param {Error} thrown error + * @param {Error|ErrorConstructor} errorLike object to compare against + * @namespace Utils + * @api public + */function compatibleInstance(thrown,errorLike){return errorLike instanceof Error&&thrown===errorLike;}/** + * ### .compatibleConstructor(thrown, errorLike) * - * _.isSymbol(Symbol.iterator); - * // => true + * Checks if two constructors are compatible. + * This function can receive either an error constructor or + * an error instance as the `errorLike` argument. + * Constructors are compatible if they're the same or if one is + * an instance of another. * - * _.isSymbol('abc'); - * // => false - */function isSymbol(value){return _typeof(value)=='symbol'||isObjectLike(value)&&objectToString.call(value)==symbolTag;}/** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. + * @name compatibleConstructor + * @param {Error} thrown error + * @param {Error|ErrorConstructor} errorLike object to compare against + * @namespace Utils + * @api public + */function compatibleConstructor(thrown,errorLike){if(errorLike instanceof Error){// If `errorLike` is an instance of any error we compare their constructors + return thrown.constructor===errorLike.constructor||thrown instanceof errorLike.constructor;}else if(errorLike.prototype instanceof Error||errorLike===Error){// If `errorLike` is a constructor that inherits from Error, we compare `thrown` to `errorLike` directly + return thrown.constructor===errorLike||thrown instanceof errorLike;}return false;}/** + * ### .compatibleMessage(thrown, errMatcher) * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {string} Returns the string. - * @example + * Checks if an error's message is compatible with a matcher (String or RegExp). + * If the message contains the String or passes the RegExp test, + * it is considered compatible. * - * _.toString(null); - * // => '' + * @name compatibleMessage + * @param {Error} thrown error + * @param {String|RegExp} errMatcher to look for into the message + * @namespace Utils + * @api public + */function compatibleMessage(thrown,errMatcher){var comparisonString=typeof thrown==='string'?thrown:thrown.message;if(errMatcher instanceof RegExp){return errMatcher.test(comparisonString);}else if(typeof errMatcher==='string'){return comparisonString.indexOf(errMatcher)!==-1;// eslint-disable-line no-magic-numbers + }return false;}/** + * ### .getConstructorName(errorLike) * - * _.toString(-0); - * // => '-0' + * Gets the constructor name for an Error instance or constructor itself. * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */function toString(value){return value==null?'':baseToString(value);}/** - * Gets the value at `path` of `object`. If the resolved value is - * `undefined`, the `defaultValue` is returned in its place. + * @name getConstructorName + * @param {Error|ErrorConstructor} errorLike + * @namespace Utils + * @api public + */function getConstructorName(errorLike){var constructorName=errorLike;if(errorLike instanceof Error){constructorName=getFunctionName(errorLike.constructor);}else if(typeof errorLike==='function'){// If `err` is not an instance of Error it is an error constructor itself or another function. + // If we've got a common function we get its name, otherwise we may need to create a new instance + // of the error just in case it's a poorly-constructed error. Please see chaijs/chai/issues/45 to know more. + constructorName=getFunctionName(errorLike);if(constructorName===''){var newConstructorName=getFunctionName(new errorLike());// eslint-disable-line new-cap + constructorName=newConstructorName||constructorName;}}return constructorName;}/** + * ### .getMessage(errorLike) * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example + * Gets the error message from an error. + * If `err` is a String itself, we return it. + * If the error has no message, we return an empty string. * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * @name getMessage + * @param {Error|String} errorLike + * @namespace Utils + * @api public + */function getMessage(errorLike){var msg='';if(errorLike&&errorLike.message){msg=errorLike.message;}else if(typeof errorLike==='string'){msg=errorLike;}return msg;}var checkError={compatibleInstance:compatibleInstance,compatibleConstructor:compatibleConstructor,compatibleMessage:compatibleMessage,getMessage:getMessage,getConstructorName:getConstructorName};/*! + * Chai - isNaN utility + * Copyright(c) 2012-2015 Sakthipriyan Vairamani + * MIT Licensed + */ /** + * ### .isNaN(value) * - * _.get(object, 'a[0].b.c'); - * // => 3 + * Checks if the given value is NaN or not. * - * _.get(object, ['a', '0', 'b', 'c']); - * // => 3 + * utils.isNaN(NaN); // true * - * _.get(object, 'a.b.c', 'default'); - * // => 'default' - */function get(object,path,defaultValue){var result=object==null?undefined:baseGet(object,path);return result===undefined?defaultValue:result;}module.exports=get;},{}],117:[function(require,module,exports){// cache a reference to setTimeout, so that our reference won't be stubbed out - // when using fake timers and errors will still get logged - // https://github.com/cjohansen/Sinon.JS/issues/381 - var realSetTimeout=setTimeout;function configureLogger(config){// eslint-disable-next-line no-param-reassign - config=config||{};// Function which prints errors. - if(!config.hasOwnProperty("logger")){// eslint-disable-next-line no-empty-function - config.logger=function(){};}// When set to true, any errors logged will be thrown immediately; - // If set to false, the errors will be thrown in separate execution frame. - if(!config.hasOwnProperty("useImmediateExceptions")){config.useImmediateExceptions=true;}// wrap realSetTimeout with something we can stub in tests - if(!config.hasOwnProperty("setTimeout")){config.setTimeout=realSetTimeout;}return function logError(label,e){var msg="".concat(label," threw exception: ");var err={name:e.name||label,message:e.message||e.toString(),stack:e.stack};function throwLoggedError(){err.message=msg+err.message;throw err;}config.logger("".concat(msg,"[").concat(err.name,"] ").concat(err.message));if(err.stack){config.logger(err.stack);}if(config.useImmediateExceptions){throwLoggedError();}else {config.setTimeout(throwLoggedError,0);}};}module.exports=configureLogger;},{}],118:[function(require,module,exports){var Event=require("./event");function CustomEvent(type,customData,target){this.initEvent(type,false,false,target);this.detail=customData.detail||null;}CustomEvent.prototype=new Event();CustomEvent.prototype.constructor=CustomEvent;module.exports=CustomEvent;},{"./event":120}],119:[function(require,module,exports){function flattenOptions(options){if(options!==Object(options)){return {capture:Boolean(options),once:false,passive:false};}return {capture:Boolean(options.capture),once:Boolean(options.once),passive:Boolean(options.passive)};}function not(fn){return function(){return !fn.apply(this,arguments);};}function hasListenerFilter(listener,capture){return function(listenerSpec){return listenerSpec.capture===capture&&listenerSpec.listener===listener;};}var EventTarget={// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener - addEventListener:function addEventListener(event,listener,providedOptions){// 3. Let capture, passive, and once be the result of flattening more options. - // Flatten property before executing step 2, - // feture detection is usually based on registering handler with options object, - // that has getter defined - // addEventListener("load", () => {}, { - // get once() { supportsOnce = true; } - // }); - var options=flattenOptions(providedOptions);// 2. If callback is null, then return. - if(listener===null||listener===undefined){return;}this.eventListeners=this.eventListeners||{};this.eventListeners[event]=this.eventListeners[event]||[];// 4. If context object’s associated list of event listener - // does not contain an event listener whose type is type, - // callback is callback, and capture is capture, then append - // a new event listener to it, whose type is type, callback is - // callback, capture is capture, passive is passive, and once is once. - if(!this.eventListeners[event].some(hasListenerFilter(listener,options.capture))){this.eventListeners[event].push({listener:listener,capture:options.capture,once:options.once});}},// https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener - removeEventListener:function removeEventListener(event,listener,providedOptions){if(!this.eventListeners||!this.eventListeners[event]){return;}// 2. Let capture be the result of flattening options. - var options=flattenOptions(providedOptions);// 3. If there is an event listener in the associated list of - // event listeners whose type is type, callback is callback, - // and capture is capture, then set that event listener’s - // removed to true and remove it from the associated list of event listeners. - this.eventListeners[event]=this.eventListeners[event].filter(not(hasListenerFilter(listener,options.capture)));},dispatchEvent:function dispatchEvent(event){if(!this.eventListeners||!this.eventListeners[event.type]){return Boolean(event.defaultPrevented);}var self=this;var type=event.type;var listeners=self.eventListeners[type];// Remove listeners, that should be dispatched once - // before running dispatch loop to avoid nested dispatch issues - self.eventListeners[type]=listeners.filter(function(listenerSpec){return !listenerSpec.once;});listeners.forEach(function(listenerSpec){var listener=listenerSpec.listener;if(typeof listener==="function"){listener.call(self,event);}else {listener.handleEvent(event);}});return Boolean(event.defaultPrevented);}};module.exports=EventTarget;},{}],120:[function(require,module,exports){function Event(type,bubbles,cancelable,target){this.initEvent(type,bubbles,cancelable,target);}Event.prototype={initEvent:function initEvent(type,bubbles,cancelable,target){this.type=type;this.bubbles=bubbles;this.cancelable=cancelable;this.target=target;this.currentTarget=target;},// eslint-disable-next-line no-empty-function - stopPropagation:function stopPropagation(){},preventDefault:function preventDefault(){this.defaultPrevented=true;}};module.exports=Event;},{}],121:[function(require,module,exports){module.exports={Event:require("./event"),ProgressEvent:require("./progress-event"),CustomEvent:require("./custom-event"),EventTarget:require("./event-target")};},{"./custom-event":118,"./event":120,"./event-target":119,"./progress-event":122}],122:[function(require,module,exports){var Event=require("./event");function ProgressEvent(type,progressEventRaw,target){this.initEvent(type,false,false,target);this.loaded=typeof progressEventRaw.loaded==="number"?progressEventRaw.loaded:null;this.total=typeof progressEventRaw.total==="number"?progressEventRaw.total:null;this.lengthComputable=Boolean(progressEventRaw.total);}ProgressEvent.prototype=new Event();ProgressEvent.prototype.constructor=ProgressEvent;module.exports=ProgressEvent;},{"./event":120}],123:[function(require,module,exports){var FakeTimers=require("@sinonjs/fake-timers");var fakeServer=require("./index");// eslint-disable-next-line no-empty-function - function Server(){}Server.prototype=fakeServer;var fakeServerWithClock=new Server();fakeServerWithClock.addRequest=function addRequest(xhr){if(xhr.async){if(_typeof(setTimeout.clock)==="object"){this.clock=setTimeout.clock;}else {this.clock=FakeTimers.install();this.resetClock=true;}if(!this.longestTimeout){var clockSetTimeout=this.clock.setTimeout;var clockSetInterval=this.clock.setInterval;var server=this;this.clock.setTimeout=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetTimeout.apply(this,arguments);};this.clock.setInterval=function(fn,timeout){server.longestTimeout=Math.max(timeout,server.longestTimeout||0);return clockSetInterval.apply(this,arguments);};}}return fakeServer.addRequest.call(this,xhr);};fakeServerWithClock.respond=function respond(){var returnVal=fakeServer.respond.apply(this,arguments);if(this.clock){this.clock.tick(this.longestTimeout||0);this.longestTimeout=0;if(this.resetClock){this.clock.uninstall();this.resetClock=false;}}return returnVal;};fakeServerWithClock.restore=function restore(){if(this.clock){this.clock.uninstall();}return fakeServer.restore.apply(this,arguments);};module.exports=fakeServerWithClock;},{"./index":124,"@sinonjs/fake-timers":61}],124:[function(require,module,exports){var fakeXhr=require("../fake-xhr");var push=[].push;var log=require("./log");var configureLogError=require("../configure-logger");var pathToRegexp=require("path-to-regexp");var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";function responseArray(handler){var response=handler;if(Object.prototype.toString.call(handler)!=="[object Array]"){response=[200,{},handler];}if(typeof response[2]!=="string"){if(!supportsArrayBuffer){throw new TypeError("Fake server response body should be a string, but was ".concat(_typeof(response[2])));}else if(!(response[2]instanceof ArrayBuffer)){throw new TypeError("Fake server response body should be a string or ArrayBuffer, but was ".concat(_typeof(response[2])));}}return response;}function getDefaultWindowLocation(){var winloc={hostname:"localhost",port:process.env.PORT||80,protocol:"http:"};winloc.host=winloc.hostname+(String(winloc.port)==="80"?"":":".concat(winloc.port));return winloc;}function getWindowLocation(){if(typeof window==="undefined"){// Fallback - return getDefaultWindowLocation();}if(typeof window.location!=="undefined"){// Browsers place location on window - return window.location;}if(typeof window.window!=="undefined"&&typeof window.window.location!=="undefined"){// React Native on Android places location on window.window - return window.window.location;}return getDefaultWindowLocation();}function matchOne(response,reqMethod,reqUrl){var rmeth=response.method;var matchMethod=!rmeth||rmeth.toLowerCase()===reqMethod.toLowerCase();var url=response.url;var matchUrl=!url||url===reqUrl||typeof url.test==="function"&&url.test(reqUrl)||typeof url==="function"&&url(reqUrl)===true;return matchMethod&&matchUrl;}function match(response,request){var wloc=getWindowLocation();var rCurrLoc=new RegExp("^".concat(wloc.protocol,"//").concat(wloc.host,"/"));var requestUrl=request.url;if(!/^https?:\/\//.test(requestUrl)||rCurrLoc.test(requestUrl)){requestUrl=requestUrl.replace(rCurrLoc,"/");}if(matchOne(response,this.getHTTPMethod(request),requestUrl)){if(typeof response.response==="function"){var ru=response.url;var args=[request].concat(ru&&typeof ru.exec==="function"?ru.exec(requestUrl).slice(1):[]);return response.response.apply(response,args);}return true;}return false;}function incrementRequestCount(){var count=++this.requestCount;this.requested=true;this.requestedOnce=count===1;this.requestedTwice=count===2;this.requestedThrice=count===3;this.firstRequest=this.getRequest(0);this.secondRequest=this.getRequest(1);this.thirdRequest=this.getRequest(2);this.lastRequest=this.getRequest(count-1);}var fakeServer={create:function create(config){var server=Object.create(this);server.configure(config);this.xhr=fakeXhr.useFakeXMLHttpRequest();server.requests=[];server.requestCount=0;server.queue=[];server.responses=[];this.xhr.onCreate=function(xhrObj){xhrObj.unsafeHeadersEnabled=function(){return !(server.unsafeHeadersEnabled===false);};server.addRequest(xhrObj);};return server;},configure:function configure(config){var self=this;var allowlist={autoRespond:true,autoRespondAfter:true,respondImmediately:true,fakeHTTPMethods:true,logger:true,unsafeHeadersEnabled:true};// eslint-disable-next-line no-param-reassign - config=config||{};Object.keys(config).forEach(function(setting){if(setting in allowlist){self[setting]=config[setting];}});self.logError=configureLogError(config);},addRequest:function addRequest(xhrObj){var server=this;push.call(this.requests,xhrObj);incrementRequestCount.call(this);xhrObj.onSend=function(){server.handleRequest(this);if(server.respondImmediately){server.respond();}else if(server.autoRespond&&!server.responding){setTimeout(function(){server.responding=false;server.respond();},server.autoRespondAfter||10);server.responding=true;}};},getHTTPMethod:function getHTTPMethod(request){if(this.fakeHTTPMethods&&/post/i.test(request.method)){var matches=(request.requestBody||"").match(/_method=([^\b;]+)/);return matches?matches[1]:request.method;}return request.method;},handleRequest:function handleRequest(xhr){if(xhr.async){push.call(this.queue,xhr);}else {this.processRequest(xhr);}},logger:function logger(){// no-op; override via configure() - },logError:configureLogError({}),log:log,respondWith:function respondWith(method,url,body){if(arguments.length===1&&typeof method!=="function"){this.response=responseArray(method);return;}if(arguments.length===1){// eslint-disable-next-line no-param-reassign - body=method;// eslint-disable-next-line no-param-reassign - url=method=null;}if(arguments.length===2){// eslint-disable-next-line no-param-reassign - body=url;// eslint-disable-next-line no-param-reassign - url=method;// eslint-disable-next-line no-param-reassign - method=null;}// Escape port number to prevent "named" parameters in 'path-to-regexp' module - if(typeof url==="string"&&url!==""&&/:[0-9]+\//.test(url)){var m=url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/);// eslint-disable-next-line no-param-reassign - url="".concat(m[1],"\\:").concat(m[2]);}push.call(this.responses,{method:method,url:typeof url==="string"&&url!==""?pathToRegexp(url):url,response:typeof body==="function"?body:responseArray(body)});},respond:function respond(){if(arguments.length>0){this.respondWith.apply(this,arguments);}var queue=this.queue||[];var requests=queue.splice(0,queue.length);var self=this;requests.forEach(function(request){self.processRequest(request);});},respondAll:function respondAll(){if(this.respondImmediately){return;}this.queue=this.requests.slice(0);var request;while(request=this.queue.shift()){this.processRequest(request);}},processRequest:function processRequest(request){try{if(request.aborted){return;}var response=this.response||[404,{},""];if(this.responses){for(var l=this.responses.length,i=l-1;i>=0;i--){if(match.call(this,this.responses[i],request)){response=this.responses[i].response;break;}}}if(request.readyState!==4){this.log(response,request);request.respond(response[0],response[1],response[2]);}}catch(e){this.logError("Fake server request processing",e);}},restore:function restore(){return this.xhr.restore&&this.xhr.restore.apply(this.xhr,arguments);},getRequest:function getRequest(index){return this.requests[index]||null;},reset:function reset(){this.resetBehavior();this.resetHistory();},resetBehavior:function resetBehavior(){this.responses.length=this.queue.length=0;},resetHistory:function resetHistory(){this.requests.length=this.requestCount=0;this.requestedOnce=this.requestedTwice=this.requestedThrice=this.requested=false;this.firstRequest=this.secondRequest=this.thirdRequest=this.lastRequest=null;}};module.exports=fakeServer;},{"../configure-logger":117,"../fake-xhr":127,"./log":125,"path-to-regexp":148}],125:[function(require,module,exports){var inspect=require("util").inspect;function log(response,request){var str;str="Request:\n".concat(inspect(request),"\n\n");str+="Response:\n".concat(inspect(response),"\n\n");/* istanbul ignore else: when this.logger is not a function, it can't be called */if(typeof this.logger==="function"){this.logger(str);}}module.exports=log;},{"util":113}],126:[function(require,module,exports){exports.isSupported=function(){try{return Boolean(new Blob());}catch(e){return false;}}();},{}],127:[function(require,module,exports){var GlobalTextEncoder=typeof TextEncoder!=="undefined"?TextEncoder:require("@sinonjs/text-encoding").TextEncoder;var globalObject=require("@sinonjs/commons").global;var configureLogError=require("../configure-logger");var sinonEvent=require("../event");var extend=require("just-extend");var supportsProgress=typeof ProgressEvent!=="undefined";var supportsCustomEvent=typeof CustomEvent!=="undefined";var supportsFormData=typeof FormData!=="undefined";var supportsArrayBuffer=typeof ArrayBuffer!=="undefined";var supportsBlob=require("./blob").isSupported;function getWorkingXHR(globalScope){var supportsXHR=typeof globalScope.XMLHttpRequest!=="undefined";if(supportsXHR){return globalScope.XMLHttpRequest;}var supportsActiveX=typeof globalScope.ActiveXObject!=="undefined";if(supportsActiveX){return function(){return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");};}return false;}// Ref: https://fetch.spec.whatwg.org/#forbidden-header-name - var unsafeHeaders={"Accept-Charset":true,"Access-Control-Request-Headers":true,"Access-Control-Request-Method":true,"Accept-Encoding":true,Connection:true,"Content-Length":true,Cookie:true,Cookie2:true,"Content-Transfer-Encoding":true,Date:true,DNT:true,Expect:true,Host:true,"Keep-Alive":true,Origin:true,Referer:true,TE:true,Trailer:true,"Transfer-Encoding":true,Upgrade:true,"User-Agent":true,Via:true};function EventTargetHandler(){var self=this;var events=["loadstart","progress","abort","error","load","timeout","loadend"];function addEventListener(eventName){self.addEventListener(eventName,function(event){var listener=self["on".concat(eventName)];if(listener&&typeof listener==="function"){listener.call(this,event);}});}events.forEach(addEventListener);}EventTargetHandler.prototype=sinonEvent.EventTarget;function normalizeHeaderValue(value){// Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes - /*eslint no-control-regex: "off"*/return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g,"");}function getHeader(headers,header){var foundHeader=Object.keys(headers).filter(function(h){return h.toLowerCase()===header.toLowerCase();});return foundHeader[0]||null;}function excludeSetCookie2Header(header){return !/^Set-Cookie2?$/i.test(header);}function verifyResponseBodyType(body,responseType){var error=null;var isString=typeof body==="string";if(responseType==="arraybuffer"){if(!isString&&!(body instanceof ArrayBuffer)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string or ArrayBuffer."));error.name="InvalidBodyException";}}else if(responseType==="blob"){if(!isString&&!(body instanceof ArrayBuffer)&&supportsBlob&&!(body instanceof Blob)){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string, ArrayBuffer, or Blob."));error.name="InvalidBodyException";}}else if(!isString){error=new Error("Attempted to respond to fake XMLHttpRequest with ".concat(body,", which is not a string."));error.name="InvalidBodyException";}if(error){throw error;}}function convertToArrayBuffer(body,encoding){if(body instanceof ArrayBuffer){return body;}return new GlobalTextEncoder(encoding||"utf-8").encode(body).buffer;}function isXmlContentType(contentType){return !contentType||/(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);}function clearResponse(xhr){if(xhr.responseType===""||xhr.responseType==="text"){xhr.response=xhr.responseText="";}else {xhr.response=xhr.responseText=null;}xhr.responseXML=null;}function fakeXMLHttpRequestFor(globalScope){var isReactNative=globalScope.navigator&&globalScope.navigator.product==="ReactNative";var sinonXhr={XMLHttpRequest:globalScope.XMLHttpRequest};sinonXhr.GlobalXMLHttpRequest=globalScope.XMLHttpRequest;sinonXhr.GlobalActiveXObject=globalScope.ActiveXObject;sinonXhr.supportsActiveX=typeof sinonXhr.GlobalActiveXObject!=="undefined";sinonXhr.supportsXHR=typeof sinonXhr.GlobalXMLHttpRequest!=="undefined";sinonXhr.workingXHR=getWorkingXHR(globalScope);sinonXhr.supportsTimeout=sinonXhr.supportsXHR&&"timeout"in new sinonXhr.GlobalXMLHttpRequest();sinonXhr.supportsCORS=isReactNative||sinonXhr.supportsXHR&&"withCredentials"in new sinonXhr.GlobalXMLHttpRequest();// Note that for FakeXMLHttpRequest to work pre ES5 - // we lose some of the alignment with the spec. - // To ensure as close a match as possible, - // set responseType before calling open, send or respond; - function FakeXMLHttpRequest(config){EventTargetHandler.call(this);this.readyState=FakeXMLHttpRequest.UNSENT;this.requestHeaders={};this.requestBody=null;this.status=0;this.statusText="";this.upload=new EventTargetHandler();this.responseType="";this.response="";this.logError=configureLogError(config);if(sinonXhr.supportsTimeout){this.timeout=0;}if(sinonXhr.supportsCORS){this.withCredentials=false;}if(typeof FakeXMLHttpRequest.onCreate==="function"){FakeXMLHttpRequest.onCreate(this);}}function verifyState(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){throw new Error("INVALID_STATE_ERR");}if(xhr.sendFlag){throw new Error("INVALID_STATE_ERR");}}// largest arity in XHR is 5 - XHR#open - var apply=function apply(obj,method,args){switch(args.length){case 0:return obj[method]();case 1:return obj[method](args[0]);case 2:return obj[method](args[0],args[1]);case 3:return obj[method](args[0],args[1],args[2]);case 4:return obj[method](args[0],args[1],args[2],args[3]);case 5:return obj[method](args[0],args[1],args[2],args[3],args[4]);default:throw new Error("Unhandled case");}};FakeXMLHttpRequest.filters=[];FakeXMLHttpRequest.addFilter=function addFilter(fn){this.filters.push(fn);};FakeXMLHttpRequest.defake=function defake(fakeXhr,xhrArgs){var xhr=new sinonXhr.workingXHR();// eslint-disable-line new-cap - ["open","setRequestHeader","abort","getResponseHeader","getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"].forEach(function(method){fakeXhr[method]=function(){return apply(xhr,method,arguments);};});fakeXhr.send=function(){// Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute - if(xhr.responseType!==fakeXhr.responseType){xhr.responseType=fakeXhr.responseType;}return apply(xhr,"send",arguments);};var copyAttrs=function copyAttrs(args){args.forEach(function(attr){fakeXhr[attr]=xhr[attr];});};var stateChangeStart=function stateChangeStart(){fakeXhr.readyState=xhr.readyState;if(xhr.readyState>=FakeXMLHttpRequest.HEADERS_RECEIVED){copyAttrs(["status","statusText"]);}if(xhr.readyState>=FakeXMLHttpRequest.LOADING){copyAttrs(["response"]);if(xhr.responseType===""||xhr.responseType==="text"){copyAttrs(["responseText"]);}}if(xhr.readyState===FakeXMLHttpRequest.DONE&&(xhr.responseType===""||xhr.responseType==="document")){copyAttrs(["responseXML"]);}};var stateChangeEnd=function stateChangeEnd(){if(fakeXhr.onreadystatechange){// eslint-disable-next-line no-useless-call - fakeXhr.onreadystatechange.call(fakeXhr,{target:fakeXhr,currentTarget:fakeXhr});}};var stateChange=function stateChange(){stateChangeStart();stateChangeEnd();};if(xhr.addEventListener){xhr.addEventListener("readystatechange",stateChangeStart);Object.keys(fakeXhr.eventListeners).forEach(function(event){/*eslint-disable no-loop-func*/fakeXhr.eventListeners[event].forEach(function(handler){xhr.addEventListener(event,handler.listener,{capture:handler.capture,once:handler.once});});/*eslint-enable no-loop-func*/});xhr.addEventListener("readystatechange",stateChangeEnd);}else {xhr.onreadystatechange=stateChange;}apply(xhr,"open",xhrArgs);};FakeXMLHttpRequest.useFilters=false;function verifyRequestOpened(xhr){if(xhr.readyState!==FakeXMLHttpRequest.OPENED){var errorMessage=xhr.readyState===FakeXMLHttpRequest.UNSENT?"INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first...":"INVALID_STATE_ERR - ".concat(xhr.readyState);throw new Error(errorMessage);}}function verifyRequestSent(xhr){if(xhr.readyState===FakeXMLHttpRequest.DONE){throw new Error("Request done");}}function verifyHeadersReceived(xhr){if(xhr.async&&xhr.readyState!==FakeXMLHttpRequest.HEADERS_RECEIVED){throw new Error("No headers received");}}function convertResponseBody(responseType,contentType,body){if(responseType===""||responseType==="text"){return body;}else if(supportsArrayBuffer&&responseType==="arraybuffer"){return convertToArrayBuffer(body);}else if(responseType==="json"){try{return JSON.parse(body);}catch(e){// Return parsing failure as null - return null;}}else if(supportsBlob&&responseType==="blob"){if(body instanceof Blob){return body;}var blobOptions={};if(contentType){blobOptions.type=contentType;}return new Blob([convertToArrayBuffer(body)],blobOptions);}else if(responseType==="document"){if(isXmlContentType(contentType)){return FakeXMLHttpRequest.parseXML(body);}return null;}throw new Error("Invalid responseType ".concat(responseType));}/** - * Steps to follow when there is an error, according to: - * https://xhr.spec.whatwg.org/#request-error-steps - */function requestErrorSteps(xhr){clearResponse(xhr);xhr.errorFlag=true;xhr.requestHeaders={};xhr.responseHeaders={};if(xhr.readyState!==FakeXMLHttpRequest.UNSENT&&xhr.sendFlag&&xhr.readyState!==FakeXMLHttpRequest.DONE){xhr.readyStateChange(FakeXMLHttpRequest.DONE);xhr.sendFlag=false;}}FakeXMLHttpRequest.parseXML=function parseXML(text){// Treat empty string as parsing failure - if(text!==""){try{if(typeof DOMParser!=="undefined"){var parser=new DOMParser();var parsererrorNS="";try{var parsererrors=parser.parseFromString("INVALID","text/xml").getElementsByTagName("parsererror");if(parsererrors.length){parsererrorNS=parsererrors[0].namespaceURI;}}catch(e){// passing invalid XML makes IE11 throw - // so no namespace needs to be determined - }var result;try{result=parser.parseFromString(text,"text/xml");}catch(err){return null;}return result.getElementsByTagNameNS(parsererrorNS,"parsererror").length?null:result;}var xmlDoc=new window.ActiveXObject("Microsoft.XMLDOM");xmlDoc.async="false";xmlDoc.loadXML(text);return xmlDoc.parseError.errorCode!==0?null:xmlDoc;}catch(e){// Unable to parse XML - no biggie - }}return null;};FakeXMLHttpRequest.statusCodes={100:"Continue",101:"Switching Protocols",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",300:"Multiple Choice",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported"};extend(FakeXMLHttpRequest.prototype,sinonEvent.EventTarget,{async:true,open:function open(method,url,async,username,password){this.method=method;this.url=url;this.async=typeof async==="boolean"?async:true;this.username=username;this.password=password;clearResponse(this);this.requestHeaders={};this.sendFlag=false;if(FakeXMLHttpRequest.useFilters===true){var xhrArgs=arguments;var defake=FakeXMLHttpRequest.filters.some(function(filter){return filter.apply(this,xhrArgs);});if(defake){FakeXMLHttpRequest.defake(this,arguments);return;}}this.readyStateChange(FakeXMLHttpRequest.OPENED);},readyStateChange:function readyStateChange(state){this.readyState=state;var readyStateChangeEvent=new sinonEvent.Event("readystatechange",false,false,this);if(typeof this.onreadystatechange==="function"){try{this.onreadystatechange(readyStateChangeEvent);}catch(e){this.logError("Fake XHR onreadystatechange handler",e);}}if(this.readyState!==FakeXMLHttpRequest.DONE){this.dispatchEvent(readyStateChangeEvent);}else {var event,progress;if(this.timedOut||this.aborted||this.status===0){progress={loaded:0,total:0};event=this.timedOut&&"timeout"||this.aborted&&"abort"||"error";}else {progress={loaded:100,total:100};event="load";}if(supportsProgress){this.upload.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.upload.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}this.dispatchEvent(new sinonEvent.ProgressEvent("progress",progress,this));this.dispatchEvent(new sinonEvent.ProgressEvent(event,progress,this));this.dispatchEvent(readyStateChangeEvent);this.dispatchEvent(new sinonEvent.ProgressEvent("loadend",progress,this));}},// Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method - setRequestHeader:function setRequestHeader(header,value){if(typeof value!=="string"){throw new TypeError("By RFC7230, section 3.2.4, header values should be strings. Got ".concat(_typeof(value)));}verifyState(this);var checkUnsafeHeaders=true;if(typeof this.unsafeHeadersEnabled==="function"){checkUnsafeHeaders=this.unsafeHeadersEnabled();}if(checkUnsafeHeaders&&(getHeader(unsafeHeaders,header)!==null||/^(Sec-|Proxy-)/i.test(header))){throw new Error(// eslint-disable-next-line quotes - "Refused to set unsafe header \"".concat(header,"\""));}// eslint-disable-next-line no-param-reassign - value=normalizeHeaderValue(value);var existingHeader=getHeader(this.requestHeaders,header);if(existingHeader){this.requestHeaders[existingHeader]+=", ".concat(value);}else {this.requestHeaders[header]=value;}},setStatus:function setStatus(status){var sanitizedStatus=typeof status==="number"?status:200;verifyRequestOpened(this);this.status=sanitizedStatus;this.statusText=FakeXMLHttpRequest.statusCodes[sanitizedStatus];},// Helps testing - setResponseHeaders:function setResponseHeaders(headers){verifyRequestOpened(this);var responseHeaders=this.responseHeaders={};Object.keys(headers).forEach(function(header){responseHeaders[header]=headers[header];});if(this.async){this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);}else {this.readyState=FakeXMLHttpRequest.HEADERS_RECEIVED;}},// Currently treats ALL data as a DOMString (i.e. no Document) - send:function send(data){verifyState(this);if(!/^(head)$/i.test(this.method)){var contentType=getHeader(this.requestHeaders,"Content-Type");if(this.requestHeaders[contentType]){var value=this.requestHeaders[contentType].split(";");this.requestHeaders[contentType]="".concat(value[0],";charset=utf-8");}else if(supportsFormData&&!(data instanceof FormData)){this.requestHeaders["Content-Type"]="text/plain;charset=utf-8";}this.requestBody=data;}this.errorFlag=false;this.sendFlag=this.async;clearResponse(this);if(typeof this.onSend==="function"){this.onSend(this);}// Only listen if setInterval and Date are a stubbed. - if(sinonXhr.supportsTimeout&&_typeof(setInterval.clock)==="object"&&_typeof(Date.clock)==="object"){var initiatedTime=Date.now();var self=this;// Listen to any possible tick by fake timers and check to see if timeout has - // been exceeded. It's important to note that timeout can be changed while a request - // is in flight, so we must check anytime the end user forces a clock tick to make - // sure timeout hasn't changed. - // https://xhr.spec.whatwg.org/#dfnReturnLink-2 - var clearIntervalId=setInterval(function(){// Check if the readyState has been reset or is done. If this is the case, there - // should be no timeout. This will also prevent aborted requests and - // fakeServerWithClock from triggering unnecessary responses. - if(self.readyState===FakeXMLHttpRequest.UNSENT||self.readyState===FakeXMLHttpRequest.DONE){clearInterval(clearIntervalId);}else if(typeof self.timeout==="number"&&self.timeout>0){if(Date.now()>=initiatedTime+self.timeout){self.triggerTimeout();clearInterval(clearIntervalId);}}},1);}this.dispatchEvent(new sinonEvent.Event("loadstart",false,false,this));},abort:function abort(){this.aborted=true;requestErrorSteps(this);this.readyState=FakeXMLHttpRequest.UNSENT;},error:function error(){clearResponse(this);this.errorFlag=true;this.requestHeaders={};this.responseHeaders={};this.readyStateChange(FakeXMLHttpRequest.DONE);},triggerTimeout:function triggerTimeout(){if(sinonXhr.supportsTimeout){this.timedOut=true;requestErrorSteps(this);}},getResponseHeader:function getResponseHeader(header){if(this.readyState=FakeXMLHttpRequest.LOADING){throw new Error("INVALID_STATE_ERR");}this.overriddenMimeType=type;}});var states={UNSENT:0,OPENED:1,HEADERS_RECEIVED:2,LOADING:3,DONE:4};extend(FakeXMLHttpRequest,states);extend(FakeXMLHttpRequest.prototype,states);function useFakeXMLHttpRequest(){FakeXMLHttpRequest.restore=function restore(keepOnCreate){if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=sinonXhr.GlobalXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=sinonXhr.GlobalActiveXObject;}delete FakeXMLHttpRequest.restore;if(keepOnCreate!==true){delete FakeXMLHttpRequest.onCreate;}};if(sinonXhr.supportsXHR){globalScope.XMLHttpRequest=FakeXMLHttpRequest;}if(sinonXhr.supportsActiveX){globalScope.ActiveXObject=function ActiveXObject(objId){if(objId==="Microsoft.XMLHTTP"||/^Msxml2\.XMLHTTP/i.test(objId)){return new FakeXMLHttpRequest();}return new sinonXhr.GlobalActiveXObject(objId);};}return FakeXMLHttpRequest;}return {xhr:sinonXhr,FakeXMLHttpRequest:FakeXMLHttpRequest,useFakeXMLHttpRequest:useFakeXMLHttpRequest};}module.exports=extend(fakeXMLHttpRequestFor(globalObject),{fakeXMLHttpRequestFor:fakeXMLHttpRequestFor});},{"../configure-logger":117,"../event":121,"./blob":126,"@sinonjs/commons":135,"@sinonjs/text-encoding":108,"just-extend":115}],128:[function(require,module,exports){module.exports={fakeServer:require("./fake-server"),fakeServerWithClock:require("./fake-server/fake-server-with-clock"),fakeXhr:require("./fake-xhr")};},{"./fake-server":124,"./fake-server/fake-server-with-clock":123,"./fake-xhr":127}],129:[function(require,module,exports){arguments[4][42][0].apply(exports,arguments);},{"./prototypes/array":137,"dup":42}],130:[function(require,module,exports){arguments[4][43][0].apply(exports,arguments);},{"./function-name":133,"dup":43}],131:[function(require,module,exports){arguments[4][44][0].apply(exports,arguments);},{"dup":44}],132:[function(require,module,exports){arguments[4][45][0].apply(exports,arguments);},{"dup":45}],133:[function(require,module,exports){arguments[4][46][0].apply(exports,arguments);},{"dup":46}],134:[function(require,module,exports){arguments[4][47][0].apply(exports,arguments);},{"dup":47}],135:[function(require,module,exports){arguments[4][48][0].apply(exports,arguments);},{"./called-in-order":129,"./class-name":130,"./deprecated":131,"./every":132,"./function-name":133,"./global":134,"./order-by-first-call":136,"./prototypes":140,"./type-of":146,"./value-to-string":147,"dup":48}],136:[function(require,module,exports){arguments[4][49][0].apply(exports,arguments);},{"./prototypes/array":137,"dup":49}],137:[function(require,module,exports){arguments[4][50][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":50}],138:[function(require,module,exports){arguments[4][51][0].apply(exports,arguments);},{"./throws-on-proto":145,"dup":51}],139:[function(require,module,exports){arguments[4][52][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":52}],140:[function(require,module,exports){arguments[4][53][0].apply(exports,arguments);},{"./array":137,"./function":139,"./map":141,"./object":142,"./set":143,"./string":144,"dup":53}],141:[function(require,module,exports){arguments[4][54][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":54}],142:[function(require,module,exports){arguments[4][55][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":55}],143:[function(require,module,exports){arguments[4][56][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":56}],144:[function(require,module,exports){arguments[4][57][0].apply(exports,arguments);},{"./copy-prototype-methods":138,"dup":57}],145:[function(require,module,exports){arguments[4][58][0].apply(exports,arguments);},{"dup":58}],146:[function(require,module,exports){arguments[4][59][0].apply(exports,arguments);},{"dup":59,"type-detect":151}],147:[function(require,module,exports){arguments[4][60][0].apply(exports,arguments);},{"dup":60}],148:[function(require,module,exports){var isarray=require('isarray');/** - * Expose `pathToRegexp`. - */module.exports=pathToRegexp;module.exports.parse=parse;module.exports.compile=compile;module.exports.tokensToFunction=tokensToFunction;module.exports.tokensToRegExp=tokensToRegExp;/** - * The main path matching regexp utility. + * @param {Value} The value which has to be checked if it is NaN + * @name isNaN + * @api private + */function isNaN$1(value){// Refer http://www.ecma-international.org/ecma-262/6.0/#sec-isnan-number + // section's NOTE. + return value!==value;}// If ECMAScript 6's Number.isNaN is present, prefer that. + var _isNaN=Number.isNaN||isNaN$1;var type=typeDetectExports;var flag=flag$5;function isObjectType(obj){var objectType=type(obj);var objectTypes=['Array','Object','function'];return objectTypes.indexOf(objectType)!==-1;}/** + * ### .getOperator(message) * - * @type {RegExp} - */var PATH_REGEXP=new RegExp([// Match escaped characters that would otherwise appear in future matches. - // This allows the user to escape special characters that won't transform. - '(\\\\.)',// Match Express-style parameters and un-named parameters with a prefix - // and optional suffixes. Matches appear as: + * Extract the operator from error message. + * Operator defined is based on below link + * https://nodejs.org/api/assert.html#assert_assert. + * + * Returns the `operator` or `undefined` value for an Assertion. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getOperator + * @api public + */var getOperator=function getOperator(obj,args){var operator=flag(obj,'operator');var negate=flag(obj,'negate');var expected=args[3];var msg=negate?args[2]:args[1];if(operator){return operator;}if(typeof msg==='function')msg=msg();msg=msg||'';if(!msg){return undefined;}if(/\shave\s/.test(msg)){return undefined;}var isObject=isObjectType(expected);if(/\snot\s/.test(msg)){return isObject?'notDeepStrictEqual':'notStrictEqual';}return isObject?'deepStrictEqual':'strictEqual';};/*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */var hasRequiredUtils;function requireUtils(){if(hasRequiredUtils)return utils;hasRequiredUtils=1;/*! + * Dependencies that are used for multiple exports are required here only once + */var pathval$1=pathval;/*! + * test utility + */utils.test=test;/*! + * type utility + */utils.type=typeDetectExports;/*! + * expectTypes utility + */utils.expectTypes=expectTypes;/*! + * message utility + */utils.getMessage=getMessage$1;/*! + * actual utility + */utils.getActual=getActual$1;/*! + * Inspect util + */utils.inspect=inspect_1;/*! + * Object Display util + */utils.objDisplay=objDisplay$1;/*! + * Flag utility + */utils.flag=flag$5;/*! + * Flag transferring utility + */utils.transferFlags=transferFlags;/*! + * Deep equal utility + */utils.eql=deepEqlExports;/*! + * Deep path info + */utils.getPathInfo=pathval$1.getPathInfo;/*! + * Check if a property exists + */utils.hasProperty=pathval$1.hasProperty;/*! + * Function name + */utils.getName=getFuncName_1;/*! + * add Property + */utils.addProperty=requireAddProperty();/*! + * add Method + */utils.addMethod=requireAddMethod();/*! + * overwrite Property + */utils.overwriteProperty=requireOverwriteProperty();/*! + * overwrite Method + */utils.overwriteMethod=requireOverwriteMethod();/*! + * Add a chainable method + */utils.addChainableMethod=requireAddChainableMethod();/*! + * Overwrite chainable method + */utils.overwriteChainableMethod=requireOverwriteChainableMethod();/*! + * Compare by inspect method + */utils.compareByInspect=compareByInspect;/*! + * Get own enumerable property symbols method + */utils.getOwnEnumerablePropertySymbols=getOwnEnumerablePropertySymbols$1;/*! + * Get own enumerable properties method + */utils.getOwnEnumerableProperties=getOwnEnumerableProperties;/*! + * Checks error against a given set of criteria + */utils.checkError=checkError;/*! + * Proxify util + */utils.proxify=proxify;/*! + * addLengthGuard util + */utils.addLengthGuard=addLengthGuard;/*! + * isProxyEnabled helper + */utils.isProxyEnabled=isProxyEnabled$1;/*! + * isNaN method + */utils.isNaN=_isNaN;/*! + * getOperator method + */utils.getOperator=getOperator;return utils;}/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */var config=config$5;var assertion=function assertion(_chai,util){/*! + * Module dependencies. + */var AssertionError=_chai.AssertionError,flag=util.flag;/*! + * Module export. + */_chai.Assertion=Assertion;/*! + * Assertion Constructor + * + * Creates object for chaining. + * + * `Assertion` objects contain metadata in the form of flags. Three flags can + * be assigned during instantiation by passing arguments to this constructor: + * + * - `object`: This flag contains the target of the assertion. For example, in + * the assertion `expect(numKittens).to.equal(7);`, the `object` flag will + * contain `numKittens` so that the `equal` assertion can reference it when + * needed. + * + * - `message`: This flag contains an optional custom error message to be + * prepended to the error message that's generated by the assertion when it + * fails. + * + * - `ssfi`: This flag stands for "start stack function indicator". It + * contains a function reference that serves as the starting point for + * removing frames from the stack trace of the error that's created by the + * assertion when it fails. The goal is to provide a cleaner stack trace to + * end users by removing Chai's internal functions. Note that it only works + * in environments that support `Error.captureStackTrace`, and only when + * `Chai.config.includeStack` hasn't been set to `false`. + * + * - `lockSsfi`: This flag controls whether or not the given `ssfi` flag + * should retain its current value, even as assertions are chained off of + * this object. This is usually set to `true` when creating a new assertion + * from within another assertion. It's also temporarily set to `true` before + * an overwritten assertion gets called by the overwriting assertion. + * + * @param {Mixed} obj target of the assertion + * @param {String} msg (optional) custom error message + * @param {Function} ssfi (optional) starting point for removing stack frames + * @param {Boolean} lockSsfi (optional) whether or not the ssfi flag is locked + * @api private + */function Assertion(obj,msg,ssfi,lockSsfi){flag(this,'ssfi',ssfi||Assertion);flag(this,'lockSsfi',lockSsfi);flag(this,'object',obj);flag(this,'message',msg);return util.proxify(this);}Object.defineProperty(Assertion,'includeStack',{get:function get(){console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');return config.includeStack;},set:function set(value){console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');config.includeStack=value;}});Object.defineProperty(Assertion,'showDiff',{get:function get(){console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');return config.showDiff;},set:function set(value){console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');config.showDiff=value;}});Assertion.addProperty=function(name,fn){util.addProperty(this.prototype,name,fn);};Assertion.addMethod=function(name,fn){util.addMethod(this.prototype,name,fn);};Assertion.addChainableMethod=function(name,fn,chainingBehavior){util.addChainableMethod(this.prototype,name,fn,chainingBehavior);};Assertion.overwriteProperty=function(name,fn){util.overwriteProperty(this.prototype,name,fn);};Assertion.overwriteMethod=function(name,fn){util.overwriteMethod(this.prototype,name,fn);};Assertion.overwriteChainableMethod=function(name,fn,chainingBehavior){util.overwriteChainableMethod(this.prototype,name,fn,chainingBehavior);};/** + * ### .assert(expression, message, negateMessage, expected, actual, showDiff) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String|Function} message or function that returns message to display if expression fails + * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails + * @api private + */Assertion.prototype.assert=function(expr,msg,negateMsg,expected,_actual,showDiff){var ok=util.test(this,arguments);if(false!==showDiff)showDiff=true;if(undefined===expected&&undefined===_actual)showDiff=false;if(true!==config.showDiff)showDiff=false;if(!ok){msg=util.getMessage(this,arguments);var actual=util.getActual(this,arguments);var assertionErrorObjectProperties={actual:actual,expected:expected,showDiff:showDiff};var operator=util.getOperator(this,arguments);if(operator){assertionErrorObjectProperties.operator=operator;}throw new AssertionError(msg,assertionErrorObjectProperties,config.includeStack?this.assert:flag(this,'ssfi'));}};/*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */Object.defineProperty(Assertion.prototype,'_obj',{get:function get(){return flag(this,'object');},set:function set(val){flag(this,'object',val);}});};/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */var assertions=function assertions(chai,_){var Assertion=chai.Assertion,AssertionError=chai.AssertionError,flag=_.flag;/** + * ### Language Chains + * + * The following are provided as chainable getters to improve the readability + * of your assertions. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - which + * - and + * - has + * - have + * - with + * - at + * - of + * - same + * - but + * - does + * - still + * - also + * + * @name language chains + * @namespace BDD + * @api public + */['to','be','been','is','and','has','have','with','that','which','at','of','same','but','does','still',"also"].forEach(function(chain){Assertion.addProperty(chain);});/** + * ### .not + * + * Negates all assertions that follow in the chain. + * + * expect(function () {}).to.not.throw(); + * expect({a: 1}).to.not.have.property('b'); + * expect([1, 2]).to.be.an('array').that.does.not.include(3); + * + * Just because you can negate any assertion with `.not` doesn't mean you + * should. With great power comes great responsibility. It's often best to + * assert that the one expected output was produced, rather than asserting + * that one of countless unexpected outputs wasn't produced. See individual + * assertions for specific guidance. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.not.equal(1); // Not recommended + * + * @name not + * @namespace BDD + * @api public + */Assertion.addProperty('not',function(){flag(this,'negate',true);});/** + * ### .deep + * + * Causes all `.equal`, `.include`, `.members`, `.keys`, and `.property` + * assertions that follow in the chain to use deep equality instead of strict + * (`===`) equality. See the `deep-eql` project page for info on the deep + * equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) equals `{a: 1}` + * expect({a: 1}).to.deep.equal({a: 1}); + * expect({a: 1}).to.not.equal({a: 1}); + * + * // Target array deeply (but not strictly) includes `{a: 1}` + * expect([{a: 1}]).to.deep.include({a: 1}); + * expect([{a: 1}]).to.not.include({a: 1}); + * + * // Target object deeply (but not strictly) includes `x: {a: 1}` + * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); + * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); + * + * // Target array deeply (but not strictly) has member `{a: 1}` + * expect([{a: 1}]).to.have.deep.members([{a: 1}]); + * expect([{a: 1}]).to.not.have.members([{a: 1}]); + * + * // Target set deeply (but not strictly) has key `{a: 1}` + * expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]); + * expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]); + * + * // Target object deeply (but not strictly) has property `x: {a: 1}` + * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); + * expect({x: {a: 1}}).to.not.have.property('x', {a: 1}); + * + * @name deep + * @namespace BDD + * @api public + */Assertion.addProperty('deep',function(){flag(this,'deep',true);});/** + * ### .nested + * + * Enables dot- and bracket-notation in all `.property` and `.include` + * assertions that follow in the chain. + * + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]'); + * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]'); + * expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\.a.\\[b\\]': 'x'}); + * + * `.nested` cannot be combined with `.own`. + * + * @name nested + * @namespace BDD + * @api public + */Assertion.addProperty('nested',function(){flag(this,'nested',true);});/** + * ### .own + * + * Causes all `.property` and `.include` assertions that follow in the chain + * to ignore inherited properties. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.have.own.property('a'); + * expect({a: 1}).to.have.property('b'); + * expect({a: 1}).to.not.have.own.property('b'); + * + * expect({a: 1}).to.own.include({a: 1}); + * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); + * + * `.own` cannot be combined with `.nested`. + * + * @name own + * @namespace BDD + * @api public + */Assertion.addProperty('own',function(){flag(this,'own',true);});/** + * ### .ordered + * + * Causes all `.members` assertions that follow in the chain to require that + * members be in the same order. + * + * expect([1, 2]).to.have.ordered.members([1, 2]) + * .but.not.have.ordered.members([2, 1]); + * + * When `.include` and `.ordered` are combined, the ordering begins at the + * start of both arrays. + * + * expect([1, 2, 3]).to.include.ordered.members([1, 2]) + * .but.not.include.ordered.members([2, 3]); + * + * @name ordered + * @namespace BDD + * @api public + */Assertion.addProperty('ordered',function(){flag(this,'ordered',true);});/** + * ### .any + * + * Causes all `.keys` assertions that follow in the chain to only require that + * the target have at least one of the given keys. This is the opposite of + * `.all`, which requires that the target have all of the given keys. + * + * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd'); + * + * See the `.keys` doc for guidance on when to use `.any` or `.all`. + * + * @name any + * @namespace BDD + * @api public + */Assertion.addProperty('any',function(){flag(this,'any',true);flag(this,'all',false);});/** + * ### .all + * + * Causes all `.keys` assertions that follow in the chain to require that the + * target have all of the given keys. This is the opposite of `.any`, which + * only requires that the target have at least one of the given keys. + * + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * + * Note that `.all` is used by default when neither `.all` nor `.any` are + * added earlier in the chain. However, it's often best to add `.all` anyway + * because it improves readability. + * + * See the `.keys` doc for guidance on when to use `.any` or `.all`. + * + * @name all + * @namespace BDD + * @api public + */Assertion.addProperty('all',function(){flag(this,'all',true);flag(this,'any',false);});/** + * ### .a(type[, msg]) + * + * Asserts that the target's type is equal to the given string `type`. Types + * are case insensitive. See the `type-detect` project page for info on the + * type detection algorithm: https://github.com/chaijs/type-detect. + * + * expect('foo').to.be.a('string'); + * expect({a: 1}).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * expect(new Error).to.be.an('error'); + * expect(Promise.resolve()).to.be.a('promise'); + * expect(new Float32Array).to.be.a('float32array'); + * expect(Symbol()).to.be.a('symbol'); + * + * `.a` supports objects that have a custom type set via `Symbol.toStringTag`. + * + * var myObj = { + * [Symbol.toStringTag]: 'myCustomType' + * }; + * + * expect(myObj).to.be.a('myCustomType').but.not.an('object'); + * + * It's often best to use `.a` to check a target's type before making more + * assertions on the same target. That way, you avoid unexpected behavior from + * any assertion that does different things based on the target's type. + * + * expect([1, 2, 3]).to.be.an('array').that.includes(2); + * expect([]).to.be.an('array').that.is.empty; + * + * Add `.not` earlier in the chain to negate `.a`. However, it's often best to + * assert that the target is the expected type, rather than asserting that it + * isn't one of many unexpected types. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.an('array'); // Not recommended + * + * `.a` accepts an optional `msg` argument which is a custom error message to + * show when the assertion fails. The message can also be given as the second + * argument to `expect`. + * + * expect(1).to.be.a('string', 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.a('string'); + * + * `.a` can also be used as a language chain to improve the readability of + * your assertions. + * + * expect({b: 2}).to.have.a.property('b'); + * + * The alias `.an` can be used interchangeably with `.a`. + * + * @name a + * @alias an + * @param {String} type + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function an(type,msg){if(msg)flag(this,'message',msg);type=type.toLowerCase();var obj=flag(this,'object'),article=~['a','e','i','o','u'].indexOf(type.charAt(0))?'an ':'a ';this.assert(type===_.type(obj).toLowerCase(),'expected #{this} to be '+article+type,'expected #{this} not to be '+article+type);}Assertion.addChainableMethod('an',an);Assertion.addChainableMethod('a',an);/** + * ### .include(val[, msg]) + * + * When the target is a string, `.include` asserts that the given string `val` + * is a substring of the target. + * + * expect('foobar').to.include('foo'); + * + * When the target is an array, `.include` asserts that the given `val` is a + * member of the target. + * + * expect([1, 2, 3]).to.include(2); + * + * When the target is an object, `.include` asserts that the given object + * `val`'s properties are a subset of the target's properties. + * + * expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2}); + * + * When the target is a Set or WeakSet, `.include` asserts that the given `val` is a + * member of the target. SameValueZero equality algorithm is used. + * + * expect(new Set([1, 2])).to.include(2); + * + * When the target is a Map, `.include` asserts that the given `val` is one of + * the values of the target. SameValueZero equality algorithm is used. + * + * expect(new Map([['a', 1], ['b', 2]])).to.include(2); + * + * Because `.include` does different things based on the target's type, it's + * important to check the target's type before using `.include`. See the `.a` + * doc for info on testing a target's type. + * + * expect([1, 2, 3]).to.be.an('array').that.includes(2); + * + * By default, strict (`===`) equality is used to compare array members and + * object properties. Add `.deep` earlier in the chain to use deep equality + * instead (WeakSet targets are not supported). See the `deep-eql` project + * page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target array deeply (but not strictly) includes `{a: 1}` + * expect([{a: 1}]).to.deep.include({a: 1}); + * expect([{a: 1}]).to.not.include({a: 1}); + * + * // Target object deeply (but not strictly) includes `x: {a: 1}` + * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); + * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); + * + * By default, all of the target's properties are searched when working with + * objects. This includes properties that are inherited and/or non-enumerable. + * Add `.own` earlier in the chain to exclude the target's inherited + * properties from the search. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.own.include({a: 1}); + * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); + * + * Note that a target object is always only searched for `val`'s own + * enumerable properties. + * + * `.deep` and `.own` can be combined. + * + * expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}}); + * + * Add `.nested` earlier in the chain to enable dot- and bracket-notation when + * referencing nested properties. + * + * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2}); + * + * `.deep` and `.nested` can be combined. + * + * expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}}); + * + * `.own` and `.nested` cannot be combined. + * + * Add `.not` earlier in the chain to negate `.include`. + * + * expect('foobar').to.not.include('taco'); + * expect([1, 2, 3]).to.not.include(4); + * + * However, it's dangerous to negate `.include` when the target is an object. + * The problem is that it creates uncertain expectations by asserting that the + * target object doesn't have all of `val`'s key/value pairs but may or may + * not have some of them. It's often best to identify the exact output that's + * expected, and then write an assertion that only accepts that exact output. + * + * When the target object isn't even expected to have `val`'s keys, it's + * often best to assert exactly that. + * + * expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended + * expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended + * + * When the target object is expected to have `val`'s keys, it's often best to + * assert that each of the properties has its expected value, rather than + * asserting that each property doesn't have one of many unexpected values. + * + * expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended + * expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended + * + * `.include` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2, 3]).to.include(4, 'nooo why fail??'); + * expect([1, 2, 3], 'nooo why fail??').to.include(4); + * + * `.include` can also be used as a language chain, causing all `.members` and + * `.keys` assertions that follow in the chain to require the target to be a + * superset of the expected set, rather than an identical set. Note that + * `.members` ignores duplicates in the subset when `.include` is added. + * + * // Target object's keys are a superset of ['a', 'b'] but not identical + * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b'); + * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b'); + * + * // Target array is a superset of [1, 2] but not identical + * expect([1, 2, 3]).to.include.members([1, 2]); + * expect([1, 2, 3]).to.not.have.members([1, 2]); + * + * // Duplicates in the subset are ignored + * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]); + * + * Note that adding `.any` earlier in the chain causes the `.keys` assertion + * to ignore `.include`. + * + * // Both assertions are identical + * expect({a: 1}).to.include.any.keys('a', 'b'); + * expect({a: 1}).to.have.any.keys('a', 'b'); + * + * The aliases `.includes`, `.contain`, and `.contains` can be used + * interchangeably with `.include`. + * + * @name include + * @alias contain + * @alias includes + * @alias contains + * @param {Mixed} val + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function SameValueZero(a,b){return _.isNaN(a)&&_.isNaN(b)||a===b;}function includeChainingBehavior(){flag(this,'contains',true);}function include(val,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),objType=_.type(obj).toLowerCase(),flagMsg=flag(this,'message'),negate=flag(this,'negate'),ssfi=flag(this,'ssfi'),isDeep=flag(this,'deep'),descriptor=isDeep?'deep ':'';flagMsg=flagMsg?flagMsg+': ':'';var included=false;switch(objType){case'string':included=obj.indexOf(val)!==-1;break;case'weakset':if(isDeep){throw new AssertionError(flagMsg+'unable to use .deep.include with WeakSet',undefined,ssfi);}included=obj.has(val);break;case'map':var isEql=isDeep?_.eql:SameValueZero;obj.forEach(function(item){included=included||isEql(item,val);});break;case'set':if(isDeep){obj.forEach(function(item){included=included||_.eql(item,val);});}else {included=obj.has(val);}break;case'array':if(isDeep){included=obj.some(function(item){return _.eql(item,val);});}else {included=obj.indexOf(val)!==-1;}break;default:// This block is for asserting a subset of properties in an object. + // `_.expectTypes` isn't used here because `.include` should work with + // objects with a custom `@@toStringTag`. + if(val!==Object(val)){throw new AssertionError(flagMsg+'the given combination of arguments ('+objType+' and '+_.type(val).toLowerCase()+')'+' is invalid for this assertion. '+'You can use an array, a map, an object, a set, a string, '+'or a weakset instead of a '+_.type(val).toLowerCase(),undefined,ssfi);}var props=Object.keys(val),firstErr=null,numErrs=0;props.forEach(function(prop){var propAssertion=new Assertion(obj);_.transferFlags(this,propAssertion,true);flag(propAssertion,'lockSsfi',true);if(!negate||props.length===1){propAssertion.property(prop,val[prop]);return;}try{propAssertion.property(prop,val[prop]);}catch(err){if(!_.checkError.compatibleConstructor(err,AssertionError)){throw err;}if(firstErr===null)firstErr=err;numErrs++;}},this);// When validating .not.include with multiple properties, we only want + // to throw an assertion error if all of the properties are included, + // in which case we throw the first property assertion error that we + // encountered. + if(negate&&props.length>1&&numErrs===props.length){throw firstErr;}return;}// Assert inclusion in collection or substring in a string. + this.assert(included,'expected #{this} to '+descriptor+'include '+_.inspect(val),'expected #{this} to not '+descriptor+'include '+_.inspect(val));}Assertion.addChainableMethod('include',include,includeChainingBehavior);Assertion.addChainableMethod('contain',include,includeChainingBehavior);Assertion.addChainableMethod('contains',include,includeChainingBehavior);Assertion.addChainableMethod('includes',include,includeChainingBehavior);/** + * ### .ok + * + * Asserts that the target is a truthy value (considered `true` in boolean context). + * However, it's often best to assert that the target is strictly (`===`) or + * deeply equal to its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.ok; // Not recommended + * + * expect(true).to.be.true; // Recommended + * expect(true).to.be.ok; // Not recommended + * + * Add `.not` earlier in the chain to negate `.ok`. + * + * expect(0).to.equal(0); // Recommended + * expect(0).to.not.be.ok; // Not recommended + * + * expect(false).to.be.false; // Recommended + * expect(false).to.not.be.ok; // Not recommended + * + * expect(null).to.be.null; // Recommended + * expect(null).to.not.be.ok; // Not recommended + * + * expect(undefined).to.be.undefined; // Recommended + * expect(undefined).to.not.be.ok; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(false, 'nooo why fail??').to.be.ok; + * + * @name ok + * @namespace BDD + * @api public + */Assertion.addProperty('ok',function(){this.assert(flag(this,'object'),'expected #{this} to be truthy','expected #{this} to be falsy');});/** + * ### .true + * + * Asserts that the target is strictly (`===`) equal to `true`. + * + * expect(true).to.be.true; + * + * Add `.not` earlier in the chain to negate `.true`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `true`. + * + * expect(false).to.be.false; // Recommended + * expect(false).to.not.be.true; // Not recommended + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.true; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(false, 'nooo why fail??').to.be.true; + * + * @name true + * @namespace BDD + * @api public + */Assertion.addProperty('true',function(){this.assert(true===flag(this,'object'),'expected #{this} to be true','expected #{this} to be false',flag(this,'negate')?false:true);});/** + * ### .false + * + * Asserts that the target is strictly (`===`) equal to `false`. + * + * expect(false).to.be.false; + * + * Add `.not` earlier in the chain to negate `.false`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to `false`. + * + * expect(true).to.be.true; // Recommended + * expect(true).to.not.be.false; // Not recommended + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.false; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(true, 'nooo why fail??').to.be.false; + * + * @name false + * @namespace BDD + * @api public + */Assertion.addProperty('false',function(){this.assert(false===flag(this,'object'),'expected #{this} to be false','expected #{this} to be true',flag(this,'negate')?true:false);});/** + * ### .null + * + * Asserts that the target is strictly (`===`) equal to `null`. + * + * expect(null).to.be.null; + * + * Add `.not` earlier in the chain to negate `.null`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `null`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.null; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.null; + * + * @name null + * @namespace BDD + * @api public + */Assertion.addProperty('null',function(){this.assert(null===flag(this,'object'),'expected #{this} to be null','expected #{this} not to be null');});/** + * ### .undefined + * + * Asserts that the target is strictly (`===`) equal to `undefined`. + * + * expect(undefined).to.be.undefined; + * + * Add `.not` earlier in the chain to negate `.undefined`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to `undefined`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.undefined; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.undefined; + * + * @name undefined + * @namespace BDD + * @api public + */Assertion.addProperty('undefined',function(){this.assert(undefined===flag(this,'object'),'expected #{this} to be undefined','expected #{this} not to be undefined');});/** + * ### .NaN + * + * Asserts that the target is exactly `NaN`. + * + * expect(NaN).to.be.NaN; + * + * Add `.not` earlier in the chain to negate `.NaN`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `NaN`. + * + * expect('foo').to.equal('foo'); // Recommended + * expect('foo').to.not.be.NaN; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.NaN; + * + * @name NaN + * @namespace BDD + * @api public + */Assertion.addProperty('NaN',function(){this.assert(_.isNaN(flag(this,'object')),'expected #{this} to be NaN','expected #{this} not to be NaN');});/** + * ### .exist + * + * Asserts that the target is not strictly (`===`) equal to either `null` or + * `undefined`. However, it's often best to assert that the target is equal to + * its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.exist; // Not recommended + * + * expect(0).to.equal(0); // Recommended + * expect(0).to.exist; // Not recommended + * + * Add `.not` earlier in the chain to negate `.exist`. + * + * expect(null).to.be.null; // Recommended + * expect(null).to.not.exist; // Not recommended + * + * expect(undefined).to.be.undefined; // Recommended + * expect(undefined).to.not.exist; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(null, 'nooo why fail??').to.exist; + * + * The alias `.exists` can be used interchangeably with `.exist`. + * + * @name exist + * @alias exists + * @namespace BDD + * @api public + */function assertExist(){var val=flag(this,'object');this.assert(val!==null&&val!==undefined,'expected #{this} to exist','expected #{this} to not exist');}Assertion.addProperty('exist',assertExist);Assertion.addProperty('exists',assertExist);/** + * ### .empty + * + * When the target is a string or array, `.empty` asserts that the target's + * `length` property is strictly (`===`) equal to `0`. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * + * When the target is a map or set, `.empty` asserts that the target's `size` + * property is strictly equal to `0`. + * + * expect(new Set()).to.be.empty; + * expect(new Map()).to.be.empty; + * + * When the target is a non-function object, `.empty` asserts that the target + * doesn't have any own enumerable properties. Properties with Symbol-based + * keys are excluded from the count. + * + * expect({}).to.be.empty; + * + * Because `.empty` does different things based on the target's type, it's + * important to check the target's type before using `.empty`. See the `.a` + * doc for info on testing a target's type. + * + * expect([]).to.be.an('array').that.is.empty; + * + * Add `.not` earlier in the chain to negate `.empty`. However, it's often + * best to assert that the target contains its expected number of values, + * rather than asserting that it's not empty. + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.not.be.empty; // Not recommended + * + * expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended + * expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended + * + * expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended + * expect({a: 1}).to.not.be.empty; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect([1, 2, 3], 'nooo why fail??').to.be.empty; + * + * @name empty + * @namespace BDD + * @api public + */Assertion.addProperty('empty',function(){var val=flag(this,'object'),ssfi=flag(this,'ssfi'),flagMsg=flag(this,'message'),itemsCount;flagMsg=flagMsg?flagMsg+': ':'';switch(_.type(val).toLowerCase()){case'array':case'string':itemsCount=val.length;break;case'map':case'set':itemsCount=val.size;break;case'weakmap':case'weakset':throw new AssertionError(flagMsg+'.empty was passed a weak collection',undefined,ssfi);case'function':var msg=flagMsg+'.empty was passed a function '+_.getName(val);throw new AssertionError(msg.trim(),undefined,ssfi);default:if(val!==Object(val)){throw new AssertionError(flagMsg+'.empty was passed non-string primitive '+_.inspect(val),undefined,ssfi);}itemsCount=Object.keys(val).length;}this.assert(0===itemsCount,'expected #{this} to be empty','expected #{this} not to be empty');});/** + * ### .arguments + * + * Asserts that the target is an `arguments` object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * test(); + * + * Add `.not` earlier in the chain to negate `.arguments`. However, it's often + * best to assert which type the target is expected to be, rather than + * asserting that it’s not an `arguments` object. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.arguments; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({}, 'nooo why fail??').to.be.arguments; + * + * The alias `.Arguments` can be used interchangeably with `.arguments`. + * + * @name arguments + * @alias Arguments + * @namespace BDD + * @api public + */function checkArguments(){var obj=flag(this,'object'),type=_.type(obj);this.assert('Arguments'===type,'expected #{this} to be arguments but got '+type,'expected #{this} to not be arguments');}Assertion.addProperty('arguments',checkArguments);Assertion.addProperty('Arguments',checkArguments);/** + * ### .equal(val[, msg]) + * + * Asserts that the target is strictly (`===`) equal to the given `val`. + * + * expect(1).to.equal(1); + * expect('foo').to.equal('foo'); + * + * Add `.deep` earlier in the chain to use deep equality instead. See the + * `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) equals `{a: 1}` + * expect({a: 1}).to.deep.equal({a: 1}); + * expect({a: 1}).to.not.equal({a: 1}); + * + * // Target array deeply (but not strictly) equals `[1, 2]` + * expect([1, 2]).to.deep.equal([1, 2]); + * expect([1, 2]).to.not.equal([1, 2]); + * + * Add `.not` earlier in the chain to negate `.equal`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to one of countless unexpected values. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.equal(2); // Not recommended + * + * `.equal` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.equal(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.equal(2); + * + * The aliases `.equals` and `eq` can be used interchangeably with `.equal`. + * + * @name equal + * @alias equals + * @alias eq + * @param {Mixed} val + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertEqual(val,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object');if(flag(this,'deep')){var prevLockSsfi=flag(this,'lockSsfi');flag(this,'lockSsfi',true);this.eql(val);flag(this,'lockSsfi',prevLockSsfi);}else {this.assert(val===obj,'expected #{this} to equal #{exp}','expected #{this} to not equal #{exp}',val,this._obj,true);}}Assertion.addMethod('equal',assertEqual);Assertion.addMethod('equals',assertEqual);Assertion.addMethod('eq',assertEqual);/** + * ### .eql(obj[, msg]) + * + * Asserts that the target is deeply equal to the given `obj`. See the + * `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target object is deeply (but not strictly) equal to {a: 1} + * expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1}); + * + * // Target array is deeply (but not strictly) equal to [1, 2] + * expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]); + * + * Add `.not` earlier in the chain to negate `.eql`. However, it's often best + * to assert that the target is deeply equal to its expected value, rather + * than not deeply equal to one of countless unexpected values. + * + * expect({a: 1}).to.eql({a: 1}); // Recommended + * expect({a: 1}).to.not.eql({b: 2}); // Not recommended + * + * `.eql` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect({a: 1}).to.eql({b: 2}, 'nooo why fail??'); + * expect({a: 1}, 'nooo why fail??').to.eql({b: 2}); + * + * The alias `.eqls` can be used interchangeably with `.eql`. + * + * The `.deep.equal` assertion is almost identical to `.eql` but with one + * difference: `.deep.equal` causes deep equality comparisons to also be used + * for any other assertions that follow in the chain. + * + * @name eql + * @alias eqls + * @param {Mixed} obj + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertEql(obj,msg){if(msg)flag(this,'message',msg);this.assert(_.eql(obj,flag(this,'object')),'expected #{this} to deeply equal #{exp}','expected #{this} to not deeply equal #{exp}',obj,this._obj,true);}Assertion.addMethod('eql',assertEql);Assertion.addMethod('eqls',assertEql);/** + * ### .above(n[, msg]) + * + * Asserts that the target is a number or a date greater than the given number or date `n` respectively. + * However, it's often best to assert that the target is equal to its expected + * value. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.be.above(1); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is greater than the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.above(2); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.above(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.above`. + * + * expect(2).to.equal(2); // Recommended + * expect(1).to.not.be.above(2); // Not recommended + * + * `.above` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.above(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.above(2); + * + * The aliases `.gt` and `.greaterThan` can be used interchangeably with + * `.above`. + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertAbove(n,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),doLength=flag(this,'doLength'),flagMsg=flag(this,'message'),msgPrefix=flagMsg?flagMsg+': ':'',ssfi=flag(this,'ssfi'),objType=_.type(obj).toLowerCase(),nType=_.type(n).toLowerCase(),errorMessage,shouldThrow=true;if(doLength&&objType!=='map'&&objType!=='set'){new Assertion(obj,flagMsg,ssfi,true).to.have.property('length');}if(!doLength&&objType==='date'&&nType!=='date'){errorMessage=msgPrefix+'the argument to above must be a date';}else if(nType!=='number'&&(doLength||objType==='number')){errorMessage=msgPrefix+'the argument to above must be a number';}else if(!doLength&&objType!=='date'&&objType!=='number'){var printObj=objType==='string'?"'"+obj+"'":obj;errorMessage=msgPrefix+'expected '+printObj+' to be a number or a date';}else {shouldThrow=false;}if(shouldThrow){throw new AssertionError(errorMessage,undefined,ssfi);}if(doLength){var descriptor='length',itemsCount;if(objType==='map'||objType==='set'){descriptor='size';itemsCount=obj.size;}else {itemsCount=obj.length;}this.assert(itemsCount>n,'expected #{this} to have a '+descriptor+' above #{exp} but got #{act}','expected #{this} to not have a '+descriptor+' above #{exp}',n,itemsCount);}else {this.assert(obj>n,'expected #{this} to be above #{exp}','expected #{this} to be at most #{exp}',n);}}Assertion.addMethod('above',assertAbove);Assertion.addMethod('gt',assertAbove);Assertion.addMethod('greaterThan',assertAbove);/** + * ### .least(n[, msg]) + * + * Asserts that the target is a number or a date greater than or equal to the given + * number or date `n` respectively. However, it's often best to assert that the target is equal to + * its expected value. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.be.at.least(1); // Not recommended + * expect(2).to.be.at.least(2); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is greater than or equal to the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.at.least(2); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.at.least(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.least`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.at.least(2); // Not recommended + * + * `.least` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.at.least(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.at.least(2); + * + * The aliases `.gte` and `.greaterThanOrEqual` can be used interchangeably with + * `.least`. + * + * @name least + * @alias gte + * @alias greaterThanOrEqual + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertLeast(n,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),doLength=flag(this,'doLength'),flagMsg=flag(this,'message'),msgPrefix=flagMsg?flagMsg+': ':'',ssfi=flag(this,'ssfi'),objType=_.type(obj).toLowerCase(),nType=_.type(n).toLowerCase(),errorMessage,shouldThrow=true;if(doLength&&objType!=='map'&&objType!=='set'){new Assertion(obj,flagMsg,ssfi,true).to.have.property('length');}if(!doLength&&objType==='date'&&nType!=='date'){errorMessage=msgPrefix+'the argument to least must be a date';}else if(nType!=='number'&&(doLength||objType==='number')){errorMessage=msgPrefix+'the argument to least must be a number';}else if(!doLength&&objType!=='date'&&objType!=='number'){var printObj=objType==='string'?"'"+obj+"'":obj;errorMessage=msgPrefix+'expected '+printObj+' to be a number or a date';}else {shouldThrow=false;}if(shouldThrow){throw new AssertionError(errorMessage,undefined,ssfi);}if(doLength){var descriptor='length',itemsCount;if(objType==='map'||objType==='set'){descriptor='size';itemsCount=obj.size;}else {itemsCount=obj.length;}this.assert(itemsCount>=n,'expected #{this} to have a '+descriptor+' at least #{exp} but got #{act}','expected #{this} to have a '+descriptor+' below #{exp}',n,itemsCount);}else {this.assert(obj>=n,'expected #{this} to be at least #{exp}','expected #{this} to be below #{exp}',n);}}Assertion.addMethod('least',assertLeast);Assertion.addMethod('gte',assertLeast);Assertion.addMethod('greaterThanOrEqual',assertLeast);/** + * ### .below(n[, msg]) + * + * Asserts that the target is a number or a date less than the given number or date `n` respectively. + * However, it's often best to assert that the target is equal to its expected + * value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.below(2); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is less than the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.below(4); // Not recommended + * + * expect([1, 2, 3]).to.have.length(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.below(4); // Not recommended + * + * Add `.not` earlier in the chain to negate `.below`. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.not.be.below(1); // Not recommended + * + * `.below` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(2).to.be.below(1, 'nooo why fail??'); + * expect(2, 'nooo why fail??').to.be.below(1); + * + * The aliases `.lt` and `.lessThan` can be used interchangeably with + * `.below`. + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertBelow(n,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),doLength=flag(this,'doLength'),flagMsg=flag(this,'message'),msgPrefix=flagMsg?flagMsg+': ':'',ssfi=flag(this,'ssfi'),objType=_.type(obj).toLowerCase(),nType=_.type(n).toLowerCase(),errorMessage,shouldThrow=true;if(doLength&&objType!=='map'&&objType!=='set'){new Assertion(obj,flagMsg,ssfi,true).to.have.property('length');}if(!doLength&&objType==='date'&&nType!=='date'){errorMessage=msgPrefix+'the argument to below must be a date';}else if(nType!=='number'&&(doLength||objType==='number')){errorMessage=msgPrefix+'the argument to below must be a number';}else if(!doLength&&objType!=='date'&&objType!=='number'){var printObj=objType==='string'?"'"+obj+"'":obj;errorMessage=msgPrefix+'expected '+printObj+' to be a number or a date';}else {shouldThrow=false;}if(shouldThrow){throw new AssertionError(errorMessage,undefined,ssfi);}if(doLength){var descriptor='length',itemsCount;if(objType==='map'||objType==='set'){descriptor='size';itemsCount=obj.size;}else {itemsCount=obj.length;}this.assert(itemsCount=start&&itemsCount<=finish,'expected #{this} to have a '+descriptor+' within '+range,'expected #{this} to not have a '+descriptor+' within '+range);}else {this.assert(obj>=start&&obj<=finish,'expected #{this} to be within '+range,'expected #{this} to not be within '+range);}});/** + * ### .instanceof(constructor[, msg]) + * + * Asserts that the target is an instance of the given `constructor`. + * + * function Cat () { } + * + * expect(new Cat()).to.be.an.instanceof(Cat); + * expect([1, 2]).to.be.an.instanceof(Array); + * + * Add `.not` earlier in the chain to negate `.instanceof`. + * + * expect({a: 1}).to.not.be.an.instanceof(Array); + * + * `.instanceof` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1).to.be.an.instanceof(Array, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.an.instanceof(Array); + * + * Due to limitations in ES5, `.instanceof` may not always work as expected + * when using a transpiler such as Babel or TypeScript. In particular, it may + * produce unexpected results when subclassing built-in object such as + * `Array`, `Error`, and `Map`. See your transpiler's docs for details: + * + * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes)) + * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work)) + * + * The alias `.instanceOf` can be used interchangeably with `.instanceof`. + * + * @name instanceof + * @param {Constructor} constructor + * @param {String} msg _optional_ + * @alias instanceOf + * @namespace BDD + * @api public + */function assertInstanceOf(constructor,msg){if(msg)flag(this,'message',msg);var target=flag(this,'object');var ssfi=flag(this,'ssfi');var flagMsg=flag(this,'message');try{var isInstanceOf=target instanceof constructor;}catch(err){if(err instanceof TypeError){flagMsg=flagMsg?flagMsg+': ':'';throw new AssertionError(flagMsg+'The instanceof assertion needs a constructor but '+_.type(constructor)+' was given.',undefined,ssfi);}throw err;}var name=_.getName(constructor);if(name===null){name='an unnamed constructor';}this.assert(isInstanceOf,'expected #{this} to be an instance of '+name,'expected #{this} to not be an instance of '+name);}Assertion.addMethod('instanceof',assertInstanceOf);Assertion.addMethod('instanceOf',assertInstanceOf);/** + * ### .property(name[, val[, msg]]) + * + * Asserts that the target has a property with the given key `name`. + * + * expect({a: 1}).to.have.property('a'); + * + * When `val` is provided, `.property` also asserts that the property's value + * is equal to the given `val`. + * + * expect({a: 1}).to.have.property('a', 1); + * + * By default, strict (`===`) equality is used. Add `.deep` earlier in the + * chain to use deep equality instead. See the `deep-eql` project page for + * info on the deep equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) has property `x: {a: 1}` + * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); + * expect({x: {a: 1}}).to.not.have.property('x', {a: 1}); + * + * The target's enumerable and non-enumerable properties are always included + * in the search. By default, both own and inherited properties are included. + * Add `.own` earlier in the chain to exclude inherited properties from the + * search. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.have.own.property('a'); + * expect({a: 1}).to.have.own.property('a', 1); + * expect({a: 1}).to.have.property('b'); + * expect({a: 1}).to.not.have.own.property('b'); + * + * `.deep` and `.own` can be combined. + * + * expect({x: {a: 1}}).to.have.deep.own.property('x', {a: 1}); + * + * Add `.nested` earlier in the chain to enable dot- and bracket-notation when + * referencing nested properties. + * + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]'); + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]', 'y'); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]'); + * + * `.deep` and `.nested` can be combined. + * + * expect({a: {b: [{c: 3}]}}) + * .to.have.deep.nested.property('a.b[0]', {c: 3}); + * + * `.own` and `.nested` cannot be combined. + * + * Add `.not` earlier in the chain to negate `.property`. + * + * expect({a: 1}).to.not.have.property('b'); + * + * However, it's dangerous to negate `.property` when providing `val`. The + * problem is that it creates uncertain expectations by asserting that the + * target either doesn't have a property with the given key `name`, or that it + * does have a property with the given key `name` but its value isn't equal to + * the given `val`. It's often best to identify the exact output that's + * expected, and then write an assertion that only accepts that exact output. + * + * When the target isn't expected to have a property with the given key + * `name`, it's often best to assert exactly that. + * + * expect({b: 2}).to.not.have.property('a'); // Recommended + * expect({b: 2}).to.not.have.property('a', 1); // Not recommended + * + * When the target is expected to have a property with the given key `name`, + * it's often best to assert that the property has its expected value, rather + * than asserting that it doesn't have one of many unexpected values. + * + * expect({a: 3}).to.have.property('a', 3); // Recommended + * expect({a: 3}).to.not.have.property('a', 1); // Not recommended + * + * `.property` changes the target of any assertions that follow in the chain + * to be the value of the property from the original target object. + * + * expect({a: 1}).to.have.property('a').that.is.a('number'); + * + * `.property` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing `val`, only use the + * second form. + * + * // Recommended + * expect({a: 1}).to.have.property('a', 2, 'nooo why fail??'); + * expect({a: 1}, 'nooo why fail??').to.have.property('a', 2); + * expect({a: 1}, 'nooo why fail??').to.have.property('b'); + * + * // Not recommended + * expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??'); + * + * The above assertion isn't the same thing as not providing `val`. Instead, + * it's asserting that the target object has a `b` property that's equal to + * `undefined`. + * + * The assertions `.ownProperty` and `.haveOwnProperty` can be used + * interchangeably with `.own.property`. + * + * @name property + * @param {String} name + * @param {Mixed} val (optional) + * @param {String} msg _optional_ + * @returns value of property for chaining + * @namespace BDD + * @api public + */function assertProperty(name,val,msg){if(msg)flag(this,'message',msg);var isNested=flag(this,'nested'),isOwn=flag(this,'own'),flagMsg=flag(this,'message'),obj=flag(this,'object'),ssfi=flag(this,'ssfi'),nameType=_typeof$1(name);flagMsg=flagMsg?flagMsg+': ':'';if(isNested){if(nameType!=='string'){throw new AssertionError(flagMsg+'the argument to property must be a string when using nested syntax',undefined,ssfi);}}else {if(nameType!=='string'&&nameType!=='number'&&nameType!=='symbol'){throw new AssertionError(flagMsg+'the argument to property must be a string, number, or symbol',undefined,ssfi);}}if(isNested&&isOwn){throw new AssertionError(flagMsg+'The "nested" and "own" flags cannot be combined.',undefined,ssfi);}if(obj===null||obj===undefined){throw new AssertionError(flagMsg+'Target cannot be null or undefined.',undefined,ssfi);}var isDeep=flag(this,'deep'),negate=flag(this,'negate'),pathInfo=isNested?_.getPathInfo(obj,name):null,value=isNested?pathInfo.value:obj[name];var descriptor='';if(isDeep)descriptor+='deep ';if(isOwn)descriptor+='own ';if(isNested)descriptor+='nested ';descriptor+='property ';var hasProperty;if(isOwn)hasProperty=Object.prototype.hasOwnProperty.call(obj,name);else if(isNested)hasProperty=pathInfo.exists;else hasProperty=_.hasProperty(obj,name);// When performing a negated assertion for both name and val, merely having + // a property with the given name isn't enough to cause the assertion to + // fail. It must both have a property with the given name, and the value of + // that property must equal the given val. Therefore, skip this assertion in + // favor of the next. + if(!negate||arguments.length===1){this.assert(hasProperty,'expected #{this} to have '+descriptor+_.inspect(name),'expected #{this} to not have '+descriptor+_.inspect(name));}if(arguments.length>1){this.assert(hasProperty&&(isDeep?_.eql(val,value):val===value),'expected #{this} to have '+descriptor+_.inspect(name)+' of #{exp}, but got #{act}','expected #{this} to not have '+descriptor+_.inspect(name)+' of #{act}',val,value);}flag(this,'object',value);}Assertion.addMethod('property',assertProperty);function assertOwnProperty(name,value,msg){flag(this,'own',true);assertProperty.apply(this,arguments);}Assertion.addMethod('ownProperty',assertOwnProperty);Assertion.addMethod('haveOwnProperty',assertOwnProperty);/** + * ### .ownPropertyDescriptor(name[, descriptor[, msg]]) + * + * Asserts that the target has its own property descriptor with the given key + * `name`. Enumerable and non-enumerable properties are included in the + * search. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a'); + * + * When `descriptor` is provided, `.ownPropertyDescriptor` also asserts that + * the property's descriptor is deeply equal to the given `descriptor`. See + * the `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`. + * + * expect({a: 1}).to.not.have.ownPropertyDescriptor('b'); + * + * However, it's dangerous to negate `.ownPropertyDescriptor` when providing + * a `descriptor`. The problem is that it creates uncertain expectations by + * asserting that the target either doesn't have a property descriptor with + * the given key `name`, or that it does have a property descriptor with the + * given key `name` but it’s not deeply equal to the given `descriptor`. It's + * often best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to have a property descriptor with the given + * key `name`, it's often best to assert exactly that. + * + * // Recommended + * expect({b: 2}).to.not.have.ownPropertyDescriptor('a'); + * + * // Not recommended + * expect({b: 2}).to.not.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * When the target is expected to have a property descriptor with the given + * key `name`, it's often best to assert that the property has its expected + * descriptor, rather than asserting that it doesn't have one of many + * unexpected descriptors. + * + * // Recommended + * expect({a: 3}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 3, + * }); + * + * // Not recommended + * expect({a: 3}).to.not.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * `.ownPropertyDescriptor` changes the target of any assertions that follow + * in the chain to be the value of the property descriptor from the original + * target object. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a') + * .that.has.property('enumerable', true); + * + * `.ownPropertyDescriptor` accepts an optional `msg` argument which is a + * custom error message to show when the assertion fails. The message can also + * be given as the second argument to `expect`. When not providing + * `descriptor`, only use the second form. + * + * // Recommended + * expect({a: 1}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 2, + * }, 'nooo why fail??'); + * + * // Recommended + * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 2, + * }); + * + * // Recommended + * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b'); + * + * // Not recommended + * expect({a: 1}) + * .to.have.ownPropertyDescriptor('b', undefined, 'nooo why fail??'); + * + * The above assertion isn't the same thing as not providing `descriptor`. + * Instead, it's asserting that the target object has a `b` property + * descriptor that's deeply equal to `undefined`. + * + * The alias `.haveOwnPropertyDescriptor` can be used interchangeably with + * `.ownPropertyDescriptor`. + * + * @name ownPropertyDescriptor + * @alias haveOwnPropertyDescriptor + * @param {String} name + * @param {Object} descriptor _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertOwnPropertyDescriptor(name,descriptor,msg){if(typeof descriptor==='string'){msg=descriptor;descriptor=null;}if(msg)flag(this,'message',msg);var obj=flag(this,'object');var actualDescriptor=Object.getOwnPropertyDescriptor(Object(obj),name);if(actualDescriptor&&descriptor){this.assert(_.eql(descriptor,actualDescriptor),'expected the own property descriptor for '+_.inspect(name)+' on #{this} to match '+_.inspect(descriptor)+', got '+_.inspect(actualDescriptor),'expected the own property descriptor for '+_.inspect(name)+' on #{this} to not match '+_.inspect(descriptor),descriptor,actualDescriptor,true);}else {this.assert(actualDescriptor,'expected #{this} to have an own property descriptor for '+_.inspect(name),'expected #{this} to not have an own property descriptor for '+_.inspect(name));}flag(this,'object',actualDescriptor);}Assertion.addMethod('ownPropertyDescriptor',assertOwnPropertyDescriptor);Assertion.addMethod('haveOwnPropertyDescriptor',assertOwnPropertyDescriptor);/** + * ### .lengthOf(n[, msg]) + * + * Asserts that the target's `length` or `size` is equal to the given number + * `n`. + * + * expect([1, 2, 3]).to.have.lengthOf(3); + * expect('foo').to.have.lengthOf(3); + * expect(new Set([1, 2, 3])).to.have.lengthOf(3); + * expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3); + * + * Add `.not` earlier in the chain to negate `.lengthOf`. However, it's often + * best to assert that the target's `length` property is equal to its expected + * value, rather than not equal to one of many unexpected values. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.not.have.lengthOf(4); // Not recommended + * + * `.lengthOf` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2, 3]).to.have.lengthOf(2, 'nooo why fail??'); + * expect([1, 2, 3], 'nooo why fail??').to.have.lengthOf(2); + * + * `.lengthOf` can also be used as a language chain, causing all `.above`, + * `.below`, `.least`, `.most`, and `.within` assertions that follow in the + * chain to use the target's `length` property as the target. However, it's + * often best to assert that the target's `length` property is equal to its + * expected length, rather than asserting that its `length` property falls + * within some range of values. + * + * // Recommended + * expect([1, 2, 3]).to.have.lengthOf(3); + * + * // Not recommended + * expect([1, 2, 3]).to.have.lengthOf.above(2); + * expect([1, 2, 3]).to.have.lengthOf.below(4); + * expect([1, 2, 3]).to.have.lengthOf.at.least(3); + * expect([1, 2, 3]).to.have.lengthOf.at.most(3); + * expect([1, 2, 3]).to.have.lengthOf.within(2,4); + * + * Due to a compatibility issue, the alias `.length` can't be chained directly + * off of an uninvoked method such as `.a`. Therefore, `.length` can't be used + * interchangeably with `.lengthOf` in every situation. It's recommended to + * always use `.lengthOf` instead of `.length`. + * + * expect([1, 2, 3]).to.have.a.length(3); // incompatible; throws error + * expect([1, 2, 3]).to.have.a.lengthOf(3); // passes as expected + * + * @name lengthOf + * @alias length + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertLengthChain(){flag(this,'doLength',true);}function assertLength(n,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),objType=_.type(obj).toLowerCase(),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi'),descriptor='length',itemsCount;switch(objType){case'map':case'set':descriptor='size';itemsCount=obj.size;break;default:new Assertion(obj,flagMsg,ssfi,true).to.have.property('length');itemsCount=obj.length;}this.assert(itemsCount==n,'expected #{this} to have a '+descriptor+' of #{exp} but got #{act}','expected #{this} to not have a '+descriptor+' of #{act}',n,itemsCount);}Assertion.addChainableMethod('length',assertLength,assertLengthChain);Assertion.addChainableMethod('lengthOf',assertLength,assertLengthChain);/** + * ### .match(re[, msg]) + * + * Asserts that the target matches the given regular expression `re`. + * + * expect('foobar').to.match(/^foo/); + * + * Add `.not` earlier in the chain to negate `.match`. + * + * expect('foobar').to.not.match(/taco/); + * + * `.match` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect('foobar').to.match(/taco/, 'nooo why fail??'); + * expect('foobar', 'nooo why fail??').to.match(/taco/); + * + * The alias `.matches` can be used interchangeably with `.match`. + * + * @name match + * @alias matches + * @param {RegExp} re + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertMatch(re,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object');this.assert(re.exec(obj),'expected #{this} to match '+re,'expected #{this} not to match '+re);}Assertion.addMethod('match',assertMatch);Assertion.addMethod('matches',assertMatch);/** + * ### .string(str[, msg]) + * + * Asserts that the target string contains the given substring `str`. + * + * expect('foobar').to.have.string('bar'); + * + * Add `.not` earlier in the chain to negate `.string`. + * + * expect('foobar').to.not.have.string('taco'); + * + * `.string` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect('foobar').to.have.string('taco', 'nooo why fail??'); + * expect('foobar', 'nooo why fail??').to.have.string('taco'); + * + * @name string + * @param {String} str + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */Assertion.addMethod('string',function(str,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(obj,flagMsg,ssfi,true).is.a('string');this.assert(~obj.indexOf(str),'expected #{this} to contain '+_.inspect(str),'expected #{this} to not contain '+_.inspect(str));});/** + * ### .keys(key1[, key2[, ...]]) + * + * Asserts that the target object, array, map, or set has the given keys. Only + * the target's own inherited properties are included in the search. + * + * When the target is an object or array, keys can be provided as one or more + * string arguments, a single array argument, or a single object argument. In + * the latter case, only the keys in the given object matter; the values are + * ignored. + * + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * expect(['x', 'y']).to.have.all.keys(0, 1); + * + * expect({a: 1, b: 2}).to.have.all.keys(['a', 'b']); + * expect(['x', 'y']).to.have.all.keys([0, 1]); + * + * expect({a: 1, b: 2}).to.have.all.keys({a: 4, b: 5}); // ignore 4 and 5 + * expect(['x', 'y']).to.have.all.keys({0: 4, 1: 5}); // ignore 4 and 5 + * + * When the target is a map or set, each key must be provided as a separate + * argument. + * + * expect(new Map([['a', 1], ['b', 2]])).to.have.all.keys('a', 'b'); + * expect(new Set(['a', 'b'])).to.have.all.keys('a', 'b'); + * + * Because `.keys` does different things based on the target's type, it's + * important to check the target's type before using `.keys`. See the `.a` doc + * for info on testing a target's type. + * + * expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b'); + * + * By default, strict (`===`) equality is used to compare keys of maps and + * sets. Add `.deep` earlier in the chain to use deep equality instead. See + * the `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target set deeply (but not strictly) has key `{a: 1}` + * expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]); + * expect(new Set([{a: 1}])).to.not.have.all.keys([{a: 1}]); + * + * By default, the target must have all of the given keys and no more. Add + * `.any` earlier in the chain to only require that the target have at least + * one of the given keys. Also, add `.not` earlier in the chain to negate + * `.keys`. It's often best to add `.any` when negating `.keys`, and to use + * `.all` when asserting `.keys` without negation. + * + * When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts + * exactly what's expected of the output, whereas `.not.all.keys` creates + * uncertain expectations. + * + * // Recommended; asserts that target doesn't have any of the given keys + * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd'); + * + * // Not recommended; asserts that target doesn't have all of the given + * // keys but may or may not have some of them + * expect({a: 1, b: 2}).to.not.have.all.keys('c', 'd'); + * + * When asserting `.keys` without negation, `.all` is preferred because + * `.all.keys` asserts exactly what's expected of the output, whereas + * `.any.keys` creates uncertain expectations. + * + * // Recommended; asserts that target has all the given keys + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * + * // Not recommended; asserts that target has at least one of the given + * // keys but may or may not have more of them + * expect({a: 1, b: 2}).to.have.any.keys('a', 'b'); + * + * Note that `.all` is used by default when neither `.all` nor `.any` appear + * earlier in the chain. However, it's often best to add `.all` anyway because + * it improves readability. + * + * // Both assertions are identical + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); // Recommended + * expect({a: 1, b: 2}).to.have.keys('a', 'b'); // Not recommended + * + * Add `.include` earlier in the chain to require that the target's keys be a + * superset of the expected keys, rather than identical sets. + * + * // Target object's keys are a superset of ['a', 'b'] but not identical + * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b'); + * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b'); + * + * However, if `.any` and `.include` are combined, only the `.any` takes + * effect. The `.include` is ignored in this case. + * + * // Both assertions are identical + * expect({a: 1}).to.have.any.keys('a', 'b'); + * expect({a: 1}).to.include.any.keys('a', 'b'); + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.have.key('b'); + * + * The alias `.key` can be used interchangeably with `.keys`. + * + * @name keys + * @alias key + * @param {...String|Array|Object} keys + * @namespace BDD + * @api public + */function assertKeys(keys){var obj=flag(this,'object'),objType=_.type(obj),keysType=_.type(keys),ssfi=flag(this,'ssfi'),isDeep=flag(this,'deep'),str,deepStr='',actual,ok=true,flagMsg=flag(this,'message');flagMsg=flagMsg?flagMsg+': ':'';var mixedArgsMsg=flagMsg+'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments';if(objType==='Map'||objType==='Set'){deepStr=isDeep?'deeply ':'';actual=[];// Map and Set '.keys' aren't supported in IE 11. Therefore, use .forEach. + obj.forEach(function(val,key){actual.push(key);});if(keysType!=='Array'){keys=Array.prototype.slice.call(arguments);}}else {actual=_.getOwnEnumerableProperties(obj);switch(keysType){case'Array':if(arguments.length>1){throw new AssertionError(mixedArgsMsg,undefined,ssfi);}break;case'Object':if(arguments.length>1){throw new AssertionError(mixedArgsMsg,undefined,ssfi);}keys=Object.keys(keys);break;default:keys=Array.prototype.slice.call(arguments);}// Only stringify non-Symbols because Symbols would become "Symbol()" + keys=keys.map(function(val){return _typeof$1(val)==='symbol'?val:String(val);});}if(!keys.length){throw new AssertionError(flagMsg+'keys required',undefined,ssfi);}var len=keys.length,any=flag(this,'any'),all=flag(this,'all'),expected=keys;if(!any&&!all){all=true;}// Has any + if(any){ok=expected.some(function(expectedKey){return actual.some(function(actualKey){if(isDeep){return _.eql(expectedKey,actualKey);}else {return expectedKey===actualKey;}});});}// Has all + if(all){ok=expected.every(function(expectedKey){return actual.some(function(actualKey){if(isDeep){return _.eql(expectedKey,actualKey);}else {return expectedKey===actualKey;}});});if(!flag(this,'contains')){ok=ok&&keys.length==actual.length;}}// Key string + if(len>1){keys=keys.map(function(key){return _.inspect(key);});var last=keys.pop();if(all){str=keys.join(', ')+', and '+last;}if(any){str=keys.join(', ')+', or '+last;}}else {str=_.inspect(keys[0]);}// Form + str=(len>1?'keys ':'key ')+str;// Have / include + str=(flag(this,'contains')?'contain ':'have ')+str;// Assertion + this.assert(ok,'expected #{this} to '+deepStr+str,'expected #{this} to not '+deepStr+str,expected.slice(0).sort(_.compareByInspect),actual.sort(_.compareByInspect),true);}Assertion.addMethod('keys',assertKeys);Assertion.addMethod('key',assertKeys);/** + * ### .throw([errorLike], [errMsgMatcher], [msg]) + * + * When no arguments are provided, `.throw` invokes the target function and + * asserts that an error is thrown. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(); + * + * When one argument is provided, and it's an error constructor, `.throw` + * invokes the target function and asserts that an error is thrown that's an + * instance of that error constructor. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(TypeError); + * + * When one argument is provided, and it's an error instance, `.throw` invokes + * the target function and asserts that an error is thrown that's strictly + * (`===`) equal to that error instance. + * + * var err = new TypeError('Illegal salmon!'); + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(err); + * + * When one argument is provided, and it's a string, `.throw` invokes the + * target function and asserts that an error is thrown with a message that + * contains that string. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw('salmon'); + * + * When one argument is provided, and it's a regular expression, `.throw` + * invokes the target function and asserts that an error is thrown with a + * message that matches that regular expression. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(/salmon/); + * + * When two arguments are provided, and the first is an error instance or + * constructor, and the second is a string or regular expression, `.throw` + * invokes the function and asserts that an error is thrown that fulfills both + * conditions as described above. + * + * var err = new TypeError('Illegal salmon!'); + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(TypeError, 'salmon'); + * expect(badFn).to.throw(TypeError, /salmon/); + * expect(badFn).to.throw(err, 'salmon'); + * expect(badFn).to.throw(err, /salmon/); + * + * Add `.not` earlier in the chain to negate `.throw`. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.not.throw(); + * + * However, it's dangerous to negate `.throw` when providing any arguments. + * The problem is that it creates uncertain expectations by asserting that the + * target either doesn't throw an error, or that it throws an error but of a + * different type than the given type, or that it throws an error of the given + * type but with a message that doesn't include the given string. It's often + * best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to throw an error, it's often best to assert + * exactly that. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.not.throw(); // Recommended + * expect(goodFn).to.not.throw(ReferenceError, 'x'); // Not recommended + * + * When the target is expected to throw an error, it's often best to assert + * that the error is of its expected type, and has a message that includes an + * expected string, rather than asserting that it doesn't have one of many + * unexpected types, and doesn't have a message that includes some string. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(TypeError, 'salmon'); // Recommended + * expect(badFn).to.not.throw(ReferenceError, 'x'); // Not recommended + * + * `.throw` changes the target of any assertions that follow in the chain to + * be the error object that's thrown. + * + * var err = new TypeError('Illegal salmon!'); + * err.code = 42; + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(TypeError).with.property('code', 42); + * + * `.throw` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. When not providing two arguments, always use + * the second form. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.throw(TypeError, 'x', 'nooo why fail??'); + * expect(goodFn, 'nooo why fail??').to.throw(); + * + * Due to limitations in ES5, `.throw` may not always work as expected when + * using a transpiler such as Babel or TypeScript. In particular, it may + * produce unexpected results when subclassing the built-in `Error` object and + * then passing the subclassed constructor to `.throw`. See your transpiler's + * docs for details: + * + * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes)) + * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work)) + * + * Beware of some common mistakes when using the `throw` assertion. One common + * mistake is to accidentally invoke the function yourself instead of letting + * the `throw` assertion invoke the function for you. For example, when + * testing if a function named `fn` throws, provide `fn` instead of `fn()` as + * the target for the assertion. + * + * expect(fn).to.throw(); // Good! Tests `fn` as desired + * expect(fn()).to.throw(); // Bad! Tests result of `fn()`, not `fn` + * + * If you need to assert that your function `fn` throws when passed certain + * arguments, then wrap a call to `fn` inside of another function. + * + * expect(function () { fn(42); }).to.throw(); // Function expression + * expect(() => fn(42)).to.throw(); // ES6 arrow function + * + * Another common mistake is to provide an object method (or any stand-alone + * function that relies on `this`) as the target of the assertion. Doing so is + * problematic because the `this` context will be lost when the function is + * invoked by `.throw`; there's no way for it to know what `this` is supposed + * to be. There are two ways around this problem. One solution is to wrap the + * method or function call inside of another function. Another solution is to + * use `bind`. + * + * expect(function () { cat.meow(); }).to.throw(); // Function expression + * expect(() => cat.meow()).to.throw(); // ES6 arrow function + * expect(cat.meow.bind(cat)).to.throw(); // Bind + * + * Finally, it's worth mentioning that it's a best practice in JavaScript to + * only throw `Error` and derivatives of `Error` such as `ReferenceError`, + * `TypeError`, and user-defined objects that extend `Error`. No other type of + * value will generate a stack trace when initialized. With that said, the + * `throw` assertion does technically support any type of value being thrown, + * not just `Error` and its derivatives. + * + * The aliases `.throws` and `.Throw` can be used interchangeably with + * `.throw`. + * + * @name throw + * @alias throws + * @alias Throw + * @param {Error|ErrorConstructor} errorLike + * @param {String|RegExp} errMsgMatcher error message + * @param {String} msg _optional_ + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @returns error for chaining (null if no error) + * @namespace BDD + * @api public + */function assertThrows(errorLike,errMsgMatcher,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),ssfi=flag(this,'ssfi'),flagMsg=flag(this,'message'),negate=flag(this,'negate')||false;new Assertion(obj,flagMsg,ssfi,true).is.a('function');if(errorLike instanceof RegExp||typeof errorLike==='string'){errMsgMatcher=errorLike;errorLike=null;}var caughtErr;try{obj();}catch(err){caughtErr=err;}// If we have the negate flag enabled and at least one valid argument it means we do expect an error + // but we want it to match a given set of criteria + var everyArgIsUndefined=errorLike===undefined&&errMsgMatcher===undefined;// If we've got the negate flag enabled and both args, we should only fail if both aren't compatible + // See Issue #551 and PR #683@GitHub + var everyArgIsDefined=Boolean(errorLike&&errMsgMatcher);var errorLikeFail=false;var errMsgMatcherFail=false;// Checking if error was thrown + if(everyArgIsUndefined||!everyArgIsUndefined&&!negate){// We need this to display results correctly according to their types + var errorLikeString='an error';if(errorLike instanceof Error){errorLikeString='#{exp}';}else if(errorLike){errorLikeString=_.checkError.getConstructorName(errorLike);}this.assert(caughtErr,'expected #{this} to throw '+errorLikeString,'expected #{this} to not throw an error but #{act} was thrown',errorLike&&errorLike.toString(),caughtErr instanceof Error?caughtErr.toString():typeof caughtErr==='string'?caughtErr:caughtErr&&_.checkError.getConstructorName(caughtErr));}if(errorLike&&caughtErr){// We should compare instances only if `errorLike` is an instance of `Error` + if(errorLike instanceof Error){var isCompatibleInstance=_.checkError.compatibleInstance(caughtErr,errorLike);if(isCompatibleInstance===negate){// These checks were created to ensure we won't fail too soon when we've got both args and a negate + // See Issue #551 and PR #683@GitHub + if(everyArgIsDefined&&negate){errorLikeFail=true;}else {this.assert(negate,'expected #{this} to throw #{exp} but #{act} was thrown','expected #{this} to not throw #{exp}'+(caughtErr&&!negate?' but #{act} was thrown':''),errorLike.toString(),caughtErr.toString());}}}var isCompatibleConstructor=_.checkError.compatibleConstructor(caughtErr,errorLike);if(isCompatibleConstructor===negate){if(everyArgIsDefined&&negate){errorLikeFail=true;}else {this.assert(negate,'expected #{this} to throw #{exp} but #{act} was thrown','expected #{this} to not throw #{exp}'+(caughtErr?' but #{act} was thrown':''),errorLike instanceof Error?errorLike.toString():errorLike&&_.checkError.getConstructorName(errorLike),caughtErr instanceof Error?caughtErr.toString():caughtErr&&_.checkError.getConstructorName(caughtErr));}}}if(caughtErr&&errMsgMatcher!==undefined&&errMsgMatcher!==null){// Here we check compatible messages + var placeholder='including';if(errMsgMatcher instanceof RegExp){placeholder='matching';}var isCompatibleMessage=_.checkError.compatibleMessage(caughtErr,errMsgMatcher);if(isCompatibleMessage===negate){if(everyArgIsDefined&&negate){errMsgMatcherFail=true;}else {this.assert(negate,'expected #{this} to throw error '+placeholder+' #{exp} but got #{act}','expected #{this} to throw error not '+placeholder+' #{exp}',errMsgMatcher,_.checkError.getMessage(caughtErr));}}}// If both assertions failed and both should've matched we throw an error + if(errorLikeFail&&errMsgMatcherFail){this.assert(negate,'expected #{this} to throw #{exp} but #{act} was thrown','expected #{this} to not throw #{exp}'+(caughtErr?' but #{act} was thrown':''),errorLike instanceof Error?errorLike.toString():errorLike&&_.checkError.getConstructorName(errorLike),caughtErr instanceof Error?caughtErr.toString():caughtErr&&_.checkError.getConstructorName(caughtErr));}flag(this,'object',caughtErr);}Assertion.addMethod('throw',assertThrows);Assertion.addMethod('throws',assertThrows);Assertion.addMethod('Throw',assertThrows);/** + * ### .respondTo(method[, msg]) + * + * When the target is a non-function object, `.respondTo` asserts that the + * target has a method with the given name `method`. The method can be own or + * inherited, and it can be enumerable or non-enumerable. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(new Cat()).to.respondTo('meow'); + * + * When the target is a function, `.respondTo` asserts that the target's + * `prototype` property has a method with the given name `method`. Again, the + * method can be own or inherited, and it can be enumerable or non-enumerable. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(Cat).to.respondTo('meow'); + * + * Add `.itself` earlier in the chain to force `.respondTo` to treat the + * target as a non-function object, even if it's a function. Thus, it asserts + * that the target has a method with the given name `method`, rather than + * asserting that the target's `prototype` property has a method with the + * given name `method`. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * Cat.hiss = function () {}; + * + * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow'); + * + * When not adding `.itself`, it's important to check the target's type before + * using `.respondTo`. See the `.a` doc for info on checking a target's type. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(new Cat()).to.be.an('object').that.respondsTo('meow'); + * + * Add `.not` earlier in the chain to negate `.respondTo`. + * + * function Dog () {} + * Dog.prototype.bark = function () {}; + * + * expect(new Dog()).to.not.respondTo('meow'); + * + * `.respondTo` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect({}).to.respondTo('meow', 'nooo why fail??'); + * expect({}, 'nooo why fail??').to.respondTo('meow'); + * + * The alias `.respondsTo` can be used interchangeably with `.respondTo`. + * + * @name respondTo + * @alias respondsTo + * @param {String} method + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function respondTo(method,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),itself=flag(this,'itself'),context='function'===typeof obj&&!itself?obj.prototype[method]:obj[method];this.assert('function'===typeof context,'expected #{this} to respond to '+_.inspect(method),'expected #{this} to not respond to '+_.inspect(method));}Assertion.addMethod('respondTo',respondTo);Assertion.addMethod('respondsTo',respondTo);/** + * ### .itself + * + * Forces all `.respondTo` assertions that follow in the chain to behave as if + * the target is a non-function object, even if it's a function. Thus, it + * causes `.respondTo` to assert that the target has a method with the given + * name, rather than asserting that the target's `prototype` property has a + * method with the given name. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * Cat.hiss = function () {}; + * + * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow'); + * + * @name itself + * @namespace BDD + * @api public + */Assertion.addProperty('itself',function(){flag(this,'itself',true);});/** + * ### .satisfy(matcher[, msg]) + * + * Invokes the given `matcher` function with the target being passed as the + * first argument, and asserts that the value returned is truthy. + * + * expect(1).to.satisfy(function(num) { + * return num > 0; + * }); + * + * Add `.not` earlier in the chain to negate `.satisfy`. + * + * expect(1).to.not.satisfy(function(num) { + * return num > 2; + * }); + * + * `.satisfy` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1).to.satisfy(function(num) { + * return num > 2; + * }, 'nooo why fail??'); + * + * expect(1, 'nooo why fail??').to.satisfy(function(num) { + * return num > 2; + * }); + * + * The alias `.satisfies` can be used interchangeably with `.satisfy`. + * + * @name satisfy + * @alias satisfies + * @param {Function} matcher + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function satisfy(matcher,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object');var result=matcher(obj);this.assert(result,'expected #{this} to satisfy '+_.objDisplay(matcher),'expected #{this} to not satisfy'+_.objDisplay(matcher),flag(this,'negate')?false:true,result);}Assertion.addMethod('satisfy',satisfy);Assertion.addMethod('satisfies',satisfy);/** + * ### .closeTo(expected, delta[, msg]) + * + * Asserts that the target is a number that's within a given +/- `delta` range + * of the given number `expected`. However, it's often best to assert that the + * target is equal to its expected value. + * + * // Recommended + * expect(1.5).to.equal(1.5); + * + * // Not recommended + * expect(1.5).to.be.closeTo(1, 0.5); + * expect(1.5).to.be.closeTo(2, 0.5); + * expect(1.5).to.be.closeTo(1, 1); + * + * Add `.not` earlier in the chain to negate `.closeTo`. + * + * expect(1.5).to.equal(1.5); // Recommended + * expect(1.5).to.not.be.closeTo(3, 1); // Not recommended + * + * `.closeTo` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1.5).to.be.closeTo(3, 1, 'nooo why fail??'); + * expect(1.5, 'nooo why fail??').to.be.closeTo(3, 1); + * + * The alias `.approximately` can be used interchangeably with `.closeTo`. + * + * @name closeTo + * @alias approximately + * @param {Number} expected + * @param {Number} delta + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function closeTo(expected,delta,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(obj,flagMsg,ssfi,true).is.a('number');if(typeof expected!=='number'||typeof delta!=='number'){flagMsg=flagMsg?flagMsg+': ':'';var deltaMessage=delta===undefined?", and a delta is required":"";throw new AssertionError(flagMsg+'the arguments to closeTo or approximately must be numbers'+deltaMessage,undefined,ssfi);}this.assert(Math.abs(obj-expected)<=delta,'expected #{this} to be close to '+expected+' +/- '+delta,'expected #{this} not to be close to '+expected+' +/- '+delta);}Assertion.addMethod('closeTo',closeTo);Assertion.addMethod('approximately',closeTo);// Note: Duplicates are ignored if testing for inclusion instead of sameness. + function isSubsetOf(subset,superset,cmp,contains,ordered){if(!contains){if(subset.length!==superset.length)return false;superset=superset.slice();}return subset.every(function(elem,idx){if(ordered)return cmp?cmp(elem,superset[idx]):elem===superset[idx];if(!cmp){var matchIdx=superset.indexOf(elem);if(matchIdx===-1)return false;// Remove match from superset so not counted twice if duplicate in subset. + if(!contains)superset.splice(matchIdx,1);return true;}return superset.some(function(elem2,matchIdx){if(!cmp(elem,elem2))return false;// Remove match from superset so not counted twice if duplicate in subset. + if(!contains)superset.splice(matchIdx,1);return true;});});}/** + * ### .members(set[, msg]) + * + * Asserts that the target array has the same members as the given array + * `set`. + * + * expect([1, 2, 3]).to.have.members([2, 1, 3]); + * expect([1, 2, 2]).to.have.members([2, 1, 2]); + * + * By default, members are compared using strict (`===`) equality. Add `.deep` + * earlier in the chain to use deep equality instead. See the `deep-eql` + * project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target array deeply (but not strictly) has member `{a: 1}` + * expect([{a: 1}]).to.have.deep.members([{a: 1}]); + * expect([{a: 1}]).to.not.have.members([{a: 1}]); + * + * By default, order doesn't matter. Add `.ordered` earlier in the chain to + * require that members appear in the same order. + * + * expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]); + * expect([1, 2, 3]).to.have.members([2, 1, 3]) + * .but.not.ordered.members([2, 1, 3]); + * + * By default, both arrays must be the same size. Add `.include` earlier in + * the chain to require that the target's members be a superset of the + * expected members. Note that duplicates are ignored in the subset when + * `.include` is added. + * + * // Target array is a superset of [1, 2] but not identical + * expect([1, 2, 3]).to.include.members([1, 2]); + * expect([1, 2, 3]).to.not.have.members([1, 2]); + * + * // Duplicates in the subset are ignored + * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]); + * + * `.deep`, `.ordered`, and `.include` can all be combined. However, if + * `.include` and `.ordered` are combined, the ordering begins at the start of + * both arrays. + * + * expect([{a: 1}, {b: 2}, {c: 3}]) + * .to.include.deep.ordered.members([{a: 1}, {b: 2}]) + * .but.not.include.deep.ordered.members([{b: 2}, {c: 3}]); + * + * Add `.not` earlier in the chain to negate `.members`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the target array doesn't have all of the same members as + * the given array `set` but may or may not have some of them. It's often best + * to identify the exact output that's expected, and then write an assertion + * that only accepts that exact output. + * + * expect([1, 2]).to.not.include(3).and.not.include(4); // Recommended + * expect([1, 2]).to.not.have.members([3, 4]); // Not recommended + * + * `.members` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2]).to.have.members([1, 2, 3], 'nooo why fail??'); + * expect([1, 2], 'nooo why fail??').to.have.members([1, 2, 3]); + * + * @name members + * @param {Array} set + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */Assertion.addMethod('members',function(subset,msg){if(msg)flag(this,'message',msg);var obj=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(obj,flagMsg,ssfi,true).to.be.an('array');new Assertion(subset,flagMsg,ssfi,true).to.be.an('array');var contains=flag(this,'contains');var ordered=flag(this,'ordered');var subject,failMsg,failNegateMsg;if(contains){subject=ordered?'an ordered superset':'a superset';failMsg='expected #{this} to be '+subject+' of #{exp}';failNegateMsg='expected #{this} to not be '+subject+' of #{exp}';}else {subject=ordered?'ordered members':'members';failMsg='expected #{this} to have the same '+subject+' as #{exp}';failNegateMsg='expected #{this} to not have the same '+subject+' as #{exp}';}var cmp=flag(this,'deep')?_.eql:undefined;this.assert(isSubsetOf(subset,obj,cmp,contains,ordered),failMsg,failNegateMsg,subset,obj,true);});/** + * ### .oneOf(list[, msg]) + * + * Asserts that the target is a member of the given array `list`. However, + * it's often best to assert that the target is equal to its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.oneOf([1, 2, 3]); // Not recommended + * + * Comparisons are performed using strict (`===`) equality. + * + * Add `.not` earlier in the chain to negate `.oneOf`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.oneOf([2, 3, 4]); // Not recommended + * + * It can also be chained with `.contain` or `.include`, which will work with + * both arrays and strings: + * + * expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy']) + * expect('Today is rainy').to.not.contain.oneOf(['sunny', 'cloudy']) + * expect([1,2,3]).to.contain.oneOf([3,4,5]) + * expect([1,2,3]).to.not.contain.oneOf([4,5,6]) + * + * `.oneOf` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.oneOf([2, 3, 4], 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.oneOf([2, 3, 4]); + * + * @name oneOf + * @param {Array<*>} list + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function oneOf(list,msg){if(msg)flag(this,'message',msg);var expected=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi'),contains=flag(this,'contains'),isDeep=flag(this,'deep');new Assertion(list,flagMsg,ssfi,true).to.be.an('array');if(contains){this.assert(list.some(function(possibility){return expected.indexOf(possibility)>-1;}),'expected #{this} to contain one of #{exp}','expected #{this} to not contain one of #{exp}',list,expected);}else {if(isDeep){this.assert(list.some(function(possibility){return _.eql(expected,possibility);}),'expected #{this} to deeply equal one of #{exp}','expected #{this} to deeply equal one of #{exp}',list,expected);}else {this.assert(list.indexOf(expected)>-1,'expected #{this} to be one of #{exp}','expected #{this} to not be one of #{exp}',list,expected);}}}Assertion.addMethod('oneOf',oneOf);/** + * ### .change(subject[, prop[, msg]]) + * + * When one argument is provided, `.change` asserts that the given function + * `subject` returns a different value when it's invoked before the target + * function compared to when it's invoked afterward. However, it's often best + * to assert that `subject` is equal to its expected value. + * + * var dots = '' + * , addDot = function () { dots += '.'; } + * , getDots = function () { return dots; }; + * + * // Recommended + * expect(getDots()).to.equal(''); + * addDot(); + * expect(getDots()).to.equal('.'); + * + * // Not recommended + * expect(addDot).to.change(getDots); + * + * When two arguments are provided, `.change` asserts that the value of the + * given object `subject`'s `prop` property is different before invoking the + * target function compared to afterward. + * + * var myObj = {dots: ''} + * , addDot = function () { myObj.dots += '.'; }; + * + * // Recommended + * expect(myObj).to.have.property('dots', ''); + * addDot(); + * expect(myObj).to.have.property('dots', '.'); + * + * // Not recommended + * expect(addDot).to.change(myObj, 'dots'); + * + * Strict (`===`) equality is used to compare before and after values. + * + * Add `.not` earlier in the chain to negate `.change`. + * + * var dots = '' + * , noop = function () {} + * , getDots = function () { return dots; }; + * + * expect(noop).to.not.change(getDots); + * + * var myObj = {dots: ''} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'dots'); + * + * `.change` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {dots: ''} + * , addDot = function () { myObj.dots += '.'; }; + * + * expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??'); + * + * var dots = '' + * , addDot = function () { dots += '.'; } + * , getDots = function () { return dots; }; + * + * expect(addDot, 'nooo why fail??').to.not.change(getDots); + * + * `.change` also causes all `.by` assertions that follow in the chain to + * assert how much a numeric subject was increased or decreased by. However, + * it's dangerous to use `.change.by`. The problem is that it creates + * uncertain expectations by asserting that the subject either increases by + * the given delta, or that it decreases by the given delta. It's often best + * to identify the exact output that's expected, and then write an assertion + * that only accepts that exact output. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; } + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * The alias `.changes` can be used interchangeably with `.change`. + * + * @name change + * @alias changes + * @param {String} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertChanges(subject,prop,msg){if(msg)flag(this,'message',msg);var fn=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(fn,flagMsg,ssfi,true).is.a('function');var initial;if(!prop){new Assertion(subject,flagMsg,ssfi,true).is.a('function');initial=subject();}else {new Assertion(subject,flagMsg,ssfi,true).to.have.property(prop);initial=subject[prop];}fn();var _final=prop===undefined||prop===null?subject():subject[prop];var msgObj=prop===undefined||prop===null?initial:'.'+prop;// This gets flagged because of the .by(delta) assertion + flag(this,'deltaMsgObj',msgObj);flag(this,'initialDeltaValue',initial);flag(this,'finalDeltaValue',_final);flag(this,'deltaBehavior','change');flag(this,'realDelta',_final!==initial);this.assert(initial!==_final,'expected '+msgObj+' to change','expected '+msgObj+' to not change');}Assertion.addMethod('change',assertChanges);Assertion.addMethod('changes',assertChanges);/** + * ### .increase(subject[, prop[, msg]]) + * + * When one argument is provided, `.increase` asserts that the given function + * `subject` returns a greater number when it's invoked after invoking the + * target function compared to when it's invoked beforehand. `.increase` also + * causes all `.by` assertions that follow in the chain to assert how much + * greater of a number is returned. It's often best to assert that the return + * value increased by the expected amount, rather than asserting it increased + * by any amount. + * + * var val = 1 + * , addTwo = function () { val += 2; } + * , getVal = function () { return val; }; + * + * expect(addTwo).to.increase(getVal).by(2); // Recommended + * expect(addTwo).to.increase(getVal); // Not recommended + * + * When two arguments are provided, `.increase` asserts that the value of the + * given object `subject`'s `prop` property is greater after invoking the + * target function compared to beforehand. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.increase(myObj, 'val'); // Not recommended + * + * Add `.not` earlier in the chain to negate `.increase`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either decreases, or that it stays the same. + * It's often best to identify the exact output that's expected, and then + * write an assertion that only accepts that exact output. + * + * When the subject is expected to decrease, it's often best to assert that it + * decreased by the expected amount. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended + * + * When the subject is expected to stay the same, it's often best to assert + * exactly that. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'val'); // Recommended + * expect(noop).to.not.increase(myObj, 'val'); // Not recommended + * + * `.increase` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.increase(myObj, 'val', 'nooo why fail??'); + * + * var val = 1 + * , noop = function () {} + * , getVal = function () { return val; }; + * + * expect(noop, 'nooo why fail??').to.increase(getVal); + * + * The alias `.increases` can be used interchangeably with `.increase`. + * + * @name increase + * @alias increases + * @param {String|Function} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertIncreases(subject,prop,msg){if(msg)flag(this,'message',msg);var fn=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(fn,flagMsg,ssfi,true).is.a('function');var initial;if(!prop){new Assertion(subject,flagMsg,ssfi,true).is.a('function');initial=subject();}else {new Assertion(subject,flagMsg,ssfi,true).to.have.property(prop);initial=subject[prop];}// Make sure that the target is a number + new Assertion(initial,flagMsg,ssfi,true).is.a('number');fn();var _final2=prop===undefined||prop===null?subject():subject[prop];var msgObj=prop===undefined||prop===null?initial:'.'+prop;flag(this,'deltaMsgObj',msgObj);flag(this,'initialDeltaValue',initial);flag(this,'finalDeltaValue',_final2);flag(this,'deltaBehavior','increase');flag(this,'realDelta',_final2-initial);this.assert(_final2-initial>0,'expected '+msgObj+' to increase','expected '+msgObj+' to not increase');}Assertion.addMethod('increase',assertIncreases);Assertion.addMethod('increases',assertIncreases);/** + * ### .decrease(subject[, prop[, msg]]) + * + * When one argument is provided, `.decrease` asserts that the given function + * `subject` returns a lesser number when it's invoked after invoking the + * target function compared to when it's invoked beforehand. `.decrease` also + * causes all `.by` assertions that follow in the chain to assert how much + * lesser of a number is returned. It's often best to assert that the return + * value decreased by the expected amount, rather than asserting it decreased + * by any amount. + * + * var val = 1 + * , subtractTwo = function () { val -= 2; } + * , getVal = function () { return val; }; + * + * expect(subtractTwo).to.decrease(getVal).by(2); // Recommended + * expect(subtractTwo).to.decrease(getVal); // Not recommended + * + * When two arguments are provided, `.decrease` asserts that the value of the + * given object `subject`'s `prop` property is lesser after invoking the + * target function compared to beforehand. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.decrease(myObj, 'val'); // Not recommended + * + * Add `.not` earlier in the chain to negate `.decrease`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either increases, or that it stays the same. + * It's often best to identify the exact output that's expected, and then + * write an assertion that only accepts that exact output. + * + * When the subject is expected to increase, it's often best to assert that it + * increased by the expected amount. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.not.decrease(myObj, 'val'); // Not recommended + * + * When the subject is expected to stay the same, it's often best to assert + * exactly that. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'val'); // Recommended + * expect(noop).to.not.decrease(myObj, 'val'); // Not recommended + * + * `.decrease` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.decrease(myObj, 'val', 'nooo why fail??'); + * + * var val = 1 + * , noop = function () {} + * , getVal = function () { return val; }; + * + * expect(noop, 'nooo why fail??').to.decrease(getVal); + * + * The alias `.decreases` can be used interchangeably with `.decrease`. + * + * @name decrease + * @alias decreases + * @param {String|Function} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertDecreases(subject,prop,msg){if(msg)flag(this,'message',msg);var fn=flag(this,'object'),flagMsg=flag(this,'message'),ssfi=flag(this,'ssfi');new Assertion(fn,flagMsg,ssfi,true).is.a('function');var initial;if(!prop){new Assertion(subject,flagMsg,ssfi,true).is.a('function');initial=subject();}else {new Assertion(subject,flagMsg,ssfi,true).to.have.property(prop);initial=subject[prop];}// Make sure that the target is a number + new Assertion(initial,flagMsg,ssfi,true).is.a('number');fn();var _final3=prop===undefined||prop===null?subject():subject[prop];var msgObj=prop===undefined||prop===null?initial:'.'+prop;flag(this,'deltaMsgObj',msgObj);flag(this,'initialDeltaValue',initial);flag(this,'finalDeltaValue',_final3);flag(this,'deltaBehavior','decrease');flag(this,'realDelta',initial-_final3);this.assert(_final3-initial<0,'expected '+msgObj+' to decrease','expected '+msgObj+' to not decrease');}Assertion.addMethod('decrease',assertDecreases);Assertion.addMethod('decreases',assertDecreases);/** + * ### .by(delta[, msg]) + * + * When following an `.increase` assertion in the chain, `.by` asserts that + * the subject of the `.increase` assertion increased by the given `delta`. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); + * + * When following a `.decrease` assertion in the chain, `.by` asserts that the + * subject of the `.decrease` assertion decreased by the given `delta`. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); + * + * When following a `.change` assertion in the chain, `.by` asserts that the + * subject of the `.change` assertion either increased or decreased by the + * given `delta`. However, it's dangerous to use `.change.by`. The problem is + * that it creates uncertain expectations. It's often best to identify the + * exact output that's expected, and then write an assertion that only accepts + * that exact output. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; } + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.by`. However, it's often best + * to assert that the subject changed by its expected delta, rather than + * asserting that it didn't change by one of countless unexpected deltas. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * // Recommended + * expect(addTwo).to.increase(myObj, 'val').by(2); + * + * // Not recommended + * expect(addTwo).to.increase(myObj, 'val').but.not.by(3); + * + * `.by` accepts an optional `msg` argument which is a custom error message to + * show when the assertion fails. The message can also be given as the second + * argument to `expect`. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(3, 'nooo why fail??'); + * expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3); + * + * @name by + * @param {Number} delta + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */function assertDelta(delta,msg){if(msg)flag(this,'message',msg);var msgObj=flag(this,'deltaMsgObj');var initial=flag(this,'initialDeltaValue');var _final4=flag(this,'finalDeltaValue');var behavior=flag(this,'deltaBehavior');var realDelta=flag(this,'realDelta');var expression;if(behavior==='change'){expression=Math.abs(_final4-initial)===Math.abs(delta);}else {expression=realDelta===Math.abs(delta);}this.assert(expression,'expected '+msgObj+' to '+behavior+' by '+delta,'expected '+msgObj+' to not '+behavior+' by '+delta);}Assertion.addMethod('by',assertDelta);/** + * ### .extensible + * + * Asserts that the target is extensible, which means that new properties can + * be added to it. Primitives are never extensible. + * + * expect({a: 1}).to.be.extensible; + * + * Add `.not` earlier in the chain to negate `.extensible`. + * + * var nonExtensibleObject = Object.preventExtensions({}) + * , sealedObject = Object.seal({}) + * , frozenObject = Object.freeze({}); + * + * expect(nonExtensibleObject).to.not.be.extensible; + * expect(sealedObject).to.not.be.extensible; + * expect(frozenObject).to.not.be.extensible; + * expect(1).to.not.be.extensible; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(1, 'nooo why fail??').to.be.extensible; + * + * @name extensible + * @namespace BDD + * @api public + */Assertion.addProperty('extensible',function(){var obj=flag(this,'object');// In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible + // The following provides ES6 behavior for ES5 environments. + var isExtensible=obj===Object(obj)&&Object.isExtensible(obj);this.assert(isExtensible,'expected #{this} to be extensible','expected #{this} to not be extensible');});/** + * ### .sealed + * + * Asserts that the target is sealed, which means that new properties can't be + * added to it, and its existing properties can't be reconfigured or deleted. + * However, it's possible that its existing properties can still be reassigned + * to different values. Primitives are always sealed. + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * expect(sealedObject).to.be.sealed; + * expect(frozenObject).to.be.sealed; + * expect(1).to.be.sealed; + * + * Add `.not` earlier in the chain to negate `.sealed`. + * + * expect({a: 1}).to.not.be.sealed; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.be.sealed; + * + * @name sealed + * @namespace BDD + * @api public + */Assertion.addProperty('sealed',function(){var obj=flag(this,'object');// In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed + // The following provides ES6 behavior for ES5 environments. + var isSealed=obj===Object(obj)?Object.isSealed(obj):true;this.assert(isSealed,'expected #{this} to be sealed','expected #{this} to not be sealed');});/** + * ### .frozen + * + * Asserts that the target is frozen, which means that new properties can't be + * added to it, and its existing properties can't be reassigned to different + * values, reconfigured, or deleted. Primitives are always frozen. + * + * var frozenObject = Object.freeze({}); + * + * expect(frozenObject).to.be.frozen; + * expect(1).to.be.frozen; + * + * Add `.not` earlier in the chain to negate `.frozen`. + * + * expect({a: 1}).to.not.be.frozen; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.be.frozen; + * + * @name frozen + * @namespace BDD + * @api public + */Assertion.addProperty('frozen',function(){var obj=flag(this,'object');// In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen + // The following provides ES6 behavior for ES5 environments. + var isFrozen=obj===Object(obj)?Object.isFrozen(obj):true;this.assert(isFrozen,'expected #{this} to be frozen','expected #{this} to not be frozen');});/** + * ### .finite + * + * Asserts that the target is a number, and isn't `NaN` or positive/negative + * `Infinity`. + * + * expect(1).to.be.finite; + * + * Add `.not` earlier in the chain to negate `.finite`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either isn't a number, or that it's `NaN`, or + * that it's positive `Infinity`, or that it's negative `Infinity`. It's often + * best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to be a number, it's often best to assert + * that it's the expected type, rather than asserting that it isn't one of + * many unexpected types. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.finite; // Not recommended + * + * When the target is expected to be `NaN`, it's often best to assert exactly + * that. + * + * expect(NaN).to.be.NaN; // Recommended + * expect(NaN).to.not.be.finite; // Not recommended + * + * When the target is expected to be positive infinity, it's often best to + * assert exactly that. + * + * expect(Infinity).to.equal(Infinity); // Recommended + * expect(Infinity).to.not.be.finite; // Not recommended + * + * When the target is expected to be negative infinity, it's often best to + * assert exactly that. + * + * expect(-Infinity).to.equal(-Infinity); // Recommended + * expect(-Infinity).to.not.be.finite; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect('foo', 'nooo why fail??').to.be.finite; + * + * @name finite + * @namespace BDD + * @api public + */Assertion.addProperty('finite',function(msg){var obj=flag(this,'object');this.assert(typeof obj==='number'&&isFinite(obj),'expected #{this} to be a finite number','expected #{this} to not be a finite number');});};/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */var expect$1=function expect$1(chai,util){chai.expect=function(val,message){return new chai.Assertion(val,message);};/** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * expect.fail(); + * expect.fail("custom error message"); + * expect.fail(1, 2); + * expect.fail(1, 2, "custom error message"); + * expect.fail(1, 2, "custom error message", ">"); + * expect.fail(1, 2, undefined, ">"); + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace BDD + * @api public + */chai.expect.fail=function(actual,expected,message,operator){if(arguments.length<2){message=actual;actual=undefined;}message=message||'expect.fail()';throw new chai.AssertionError(message,{actual:actual,expected:expected,operator:operator},chai.expect.fail);};};/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */var should=function should(chai,util){var Assertion=chai.Assertion;function loadShould(){// explicitly define this method as function as to have it's name to include as `ssfi` + function shouldGetter(){if(this instanceof String||this instanceof Number||this instanceof Boolean||typeof Symbol==='function'&&this instanceof Symbol||typeof BigInt==='function'&&this instanceof BigInt){return new Assertion(this.valueOf(),null,shouldGetter);}return new Assertion(this,null,shouldGetter);}function shouldSetter(value){// See https://github.com/chaijs/chai/issues/86: this makes + // `whatever.should = someValue` actually set `someValue`, which is + // especially useful for `global.should = require('chai').should()`. // - // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] - // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] - // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] - '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'].join('|'),'g');/** - * Parse a string for the raw tokens. - * - * @param {string} str - * @param {Object=} options - * @return {!Array} - */function parse(str,options){var tokens=[];var key=0;var index=0;var path='';var defaultDelimiter=options&&options.delimiter||'/';var res;while((res=PATH_REGEXP.exec(str))!=null){var m=res[0];var escaped=res[1];var offset=res.index;path+=str.slice(index,offset);index=offset+m.length;// Ignore already escaped sequences. - if(escaped){path+=escaped[1];continue;}var next=str[index];var prefix=res[2];var name=res[3];var capture=res[4];var group=res[5];var modifier=res[6];var asterisk=res[7];// Push the current path onto the tokens. - if(path){tokens.push(path);path='';}var partial=prefix!=null&&next!=null&&next!==prefix;var repeat=modifier==='+'||modifier==='*';var optional=modifier==='?'||modifier==='*';var delimiter=res[2]||defaultDelimiter;var pattern=capture||group;tokens.push({name:name||key++,prefix:prefix||'',delimiter:delimiter,optional:optional,repeat:repeat,partial:partial,asterisk:!!asterisk,pattern:pattern?escapeGroup(pattern):asterisk?'.*':'[^'+escapeString(delimiter)+']+?'});}// Match any characters still remaining. - if(index + // Note that we have to use [[DefineProperty]] instead of [[Put]] + // since otherwise we would trigger this very setter! + Object.defineProperty(this,'should',{value:value,enumerable:true,configurable:true,writable:true});}// modify Object.prototype to have `should` + Object.defineProperty(Object.prototype,'should',{set:shouldSetter,get:shouldGetter,configurable:true});var should={};/** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * should.fail(); + * should.fail("custom error message"); + * should.fail(1, 2); + * should.fail(1, 2, "custom error message"); + * should.fail(1, 2, "custom error message", ">"); + * should.fail(1, 2, undefined, ">"); + * + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace BDD + * @api public + */should.fail=function(actual,expected,message,operator){if(arguments.length<2){message=actual;actual=undefined;}message=message||'should.fail()';throw new chai.AssertionError(message,{actual:actual,expected:expected,operator:operator},should.fail);};/** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * should.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */should.equal=function(val1,val2,msg){new Assertion(val1,msg).to.equal(val2);};/** + * ### .throw(function, [constructor/string/regexp], [string/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * should.throw(fn, 'function throws a reference error'); + * should.throw(fn, /function throws a reference error/); + * should.throw(fn, ReferenceError); + * should.throw(fn, ReferenceError, 'function throws a reference error'); + * should.throw(fn, ReferenceError, /function throws a reference error/); + * + * @name throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */should.Throw=function(fn,errt,errs,msg){new Assertion(fn,msg).to.Throw(errt,errs);};/** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi'; + * + * should.exist(foo, 'foo exists'); + * + * @name exist + * @namespace Should + * @api public + */should.exist=function(val,msg){new Assertion(val,msg).to.exist;};// negation + should.not={};/** + * ### .not.equal(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * should.not.equal(3, 4, 'these numbers are not equal'); + * + * @name not.equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */should.not.equal=function(val1,val2,msg){new Assertion(val1,msg).to.not.equal(val2);};/** + * ### .throw(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * should.not.throw(fn, Error, 'function does not throw'); + * + * @name not.throw + * @alias not.Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */should.not.Throw=function(fn,errt,errs,msg){new Assertion(fn,msg).to.not.Throw(errt,errs);};/** + * ### .not.exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var bar = null; + * + * should.not.exist(bar, 'bar does not exist'); + * + * @name not.exist + * @namespace Should + * @api public + */should.not.exist=function(val,msg){new Assertion(val,msg).to.not.exist;};should['throw']=should['Throw'];should.not['throw']=should.not['Throw'];return should;}chai.should=loadShould;chai.Should=loadShould;};/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */var assert=function assert(chai,util){/*! + * Chai dependencies. + */var Assertion=chai.Assertion,flag=util.flag;/*! + * Module export. + */ /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @namespace Assert + * @api public + */var assert=chai.assert=function(express,errmsg){var test=new Assertion(null,null,chai.assert,true);test.assert(express,errmsg,'[ negation message unavailable ]');};/** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * assert.fail(); + * assert.fail("custom error message"); + * assert.fail(1, 2); + * assert.fail(1, 2, "custom error message"); + * assert.fail(1, 2, "custom error message", ">"); + * assert.fail(1, 2, undefined, ">"); + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace Assert + * @api public + */assert.fail=function(actual,expected,message,operator){if(arguments.length<2){// Comply with Node's fail([message]) interface + message=actual;actual=undefined;}message=message||'assert.fail()';throw new chai.AssertionError(message,{actual:actual,expected:expected,operator:operator},assert.fail);};/** + * ### .isOk(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.isOk('everything', 'everything is ok'); + * assert.isOk(false, 'this will fail'); + * + * @name isOk + * @alias ok + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */assert.isOk=function(val,msg){new Assertion(val,msg,assert.isOk,true).is.ok;};/** + * ### .isNotOk(object, [message]) + * + * Asserts that `object` is falsy. + * + * assert.isNotOk('everything', 'this will fail'); + * assert.isNotOk(false, 'this will pass'); + * + * @name isNotOk + * @alias notOk + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotOk=function(val,msg){new Assertion(val,msg,assert.isNotOk,true).is.not.ok;};/** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */assert.equal=function(act,exp,msg){var test=new Assertion(act,msg,assert.equal,true);test.assert(exp==flag(test,'object'),'expected #{this} to equal #{exp}','expected #{this} to not equal #{act}',exp,act,true);};/** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */assert.notEqual=function(act,exp,msg){var test=new Assertion(act,msg,assert.notEqual,true);test.assert(exp!=flag(test,'object'),'expected #{this} to not equal #{exp}','expected #{this} to equal #{act}',exp,act,true);};/** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */assert.strictEqual=function(act,exp,msg){new Assertion(act,msg,assert.strictEqual,true).to.equal(exp);};/** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */assert.notStrictEqual=function(act,exp,msg){new Assertion(act,msg,assert.notStrictEqual,true).to.not.equal(exp);};/** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @alias deepStrictEqual + * @namespace Assert + * @api public + */assert.deepEqual=assert.deepStrictEqual=function(act,exp,msg){new Assertion(act,msg,assert.deepEqual,true).to.eql(exp);};/** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepEqual=function(act,exp,msg){new Assertion(act,msg,assert.notDeepEqual,true).to.not.eql(exp);};/** + * ### .isAbove(valueToCheck, valueToBeAbove, [message]) + * + * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`. + * + * assert.isAbove(5, 2, '5 is strictly greater than 2'); + * + * @name isAbove + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAbove + * @param {String} message + * @namespace Assert + * @api public + */assert.isAbove=function(val,abv,msg){new Assertion(val,msg,assert.isAbove,true).to.be.above(abv);};/** + * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message]) + * + * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`. + * + * assert.isAtLeast(5, 2, '5 is greater or equal to 2'); + * assert.isAtLeast(3, 3, '3 is greater or equal to 3'); + * + * @name isAtLeast + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtLeast + * @param {String} message + * @namespace Assert + * @api public + */assert.isAtLeast=function(val,atlst,msg){new Assertion(val,msg,assert.isAtLeast,true).to.be.least(atlst);};/** + * ### .isBelow(valueToCheck, valueToBeBelow, [message]) + * + * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`. + * + * assert.isBelow(3, 6, '3 is strictly less than 6'); + * + * @name isBelow + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeBelow + * @param {String} message + * @namespace Assert + * @api public + */assert.isBelow=function(val,blw,msg){new Assertion(val,msg,assert.isBelow,true).to.be.below(blw);};/** + * ### .isAtMost(valueToCheck, valueToBeAtMost, [message]) + * + * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`. + * + * assert.isAtMost(3, 6, '3 is less than or equal to 6'); + * assert.isAtMost(4, 4, '4 is less than or equal to 4'); + * + * @name isAtMost + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtMost + * @param {String} message + * @namespace Assert + * @api public + */assert.isAtMost=function(val,atmst,msg){new Assertion(val,msg,assert.isAtMost,true).to.be.most(atmst);};/** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isTrue=function(val,msg){new Assertion(val,msg,assert.isTrue,true).is['true'];};/** + * ### .isNotTrue(value, [message]) + * + * Asserts that `value` is not true. + * + * var tea = 'tasty chai'; + * assert.isNotTrue(tea, 'great, time for tea!'); + * + * @name isNotTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotTrue=function(val,msg){new Assertion(val,msg,assert.isNotTrue,true).to.not.equal(true);};/** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isFalse=function(val,msg){new Assertion(val,msg,assert.isFalse,true).is['false'];};/** + * ### .isNotFalse(value, [message]) + * + * Asserts that `value` is not false. + * + * var tea = 'tasty chai'; + * assert.isNotFalse(tea, 'great, time for tea!'); + * + * @name isNotFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotFalse=function(val,msg){new Assertion(val,msg,assert.isNotFalse,true).to.not.equal(false);};/** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNull=function(val,msg){new Assertion(val,msg,assert.isNull,true).to.equal(null);};/** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotNull=function(val,msg){new Assertion(val,msg,assert.isNotNull,true).to.not.equal(null);};/** + * ### .isNaN + * + * Asserts that value is NaN. + * + * assert.isNaN(NaN, 'NaN is NaN'); + * + * @name isNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNaN=function(val,msg){new Assertion(val,msg,assert.isNaN,true).to.be.NaN;};/** + * ### .isNotNaN + * + * Asserts that value is not NaN. + * + * assert.isNotNaN(4, '4 is not NaN'); + * + * @name isNotNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotNaN=function(val,msg){new Assertion(val,msg,assert.isNotNaN,true).not.to.be.NaN;};/** + * ### .exists + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi'; + * + * assert.exists(foo, 'foo is neither `null` nor `undefined`'); + * + * @name exists + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.exists=function(val,msg){new Assertion(val,msg,assert.exists,true).to.exist;};/** + * ### .notExists + * + * Asserts that the target is either `null` or `undefined`. + * + * var bar = null + * , baz; + * + * assert.notExists(bar); + * assert.notExists(baz, 'baz is either null or undefined'); + * + * @name notExists + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.notExists=function(val,msg){new Assertion(val,msg,assert.notExists,true).to.not.exist;};/** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isUndefined=function(val,msg){new Assertion(val,msg,assert.isUndefined,true).to.equal(undefined);};/** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isDefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isDefined=function(val,msg){new Assertion(val,msg,assert.isDefined,true).to.not.equal(undefined);};/** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isFunction=function(val,msg){new Assertion(val,msg,assert.isFunction,true).to.be.a('function');};/** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotFunction=function(val,msg){new Assertion(val,msg,assert.isNotFunction,true).to.not.be.a('function');};/** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`). + * _The assertion does not match subclassed objects._ + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isObject=function(val,msg){new Assertion(val,msg,assert.isObject,true).to.be.a('object');};/** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`). + * + * var selection = 'chai' + * assert.isNotObject(selection, 'tea selection is not an object'); + * assert.isNotObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotObject=function(val,msg){new Assertion(val,msg,assert.isNotObject,true).to.not.be.a('object');};/** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isArray=function(val,msg){new Assertion(val,msg,assert.isArray,true).to.be.an('array');};/** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotArray=function(val,msg){new Assertion(val,msg,assert.isNotArray,true).to.not.be.an('array');};/** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isString=function(val,msg){new Assertion(val,msg,assert.isString,true).to.be.a('string');};/** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotString=function(val,msg){new Assertion(val,msg,assert.isNotString,true).to.not.be.a('string');};/** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNumber=function(val,msg){new Assertion(val,msg,assert.isNumber,true).to.be.a('number');};/** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotNumber=function(val,msg){new Assertion(val,msg,assert.isNotNumber,true).to.not.be.a('number');};/** + * ### .isFinite(value, [message]) + * + * Asserts that `value` is a finite number. Unlike `.isNumber`, this will fail for `NaN` and `Infinity`. + * + * var cups = 2; + * assert.isFinite(cups, 'how many cups'); + * + * assert.isFinite(NaN); // throws + * + * @name isFinite + * @param {Number} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isFinite=function(val,msg){new Assertion(val,msg,assert.isFinite,true).to.be.finite;};/** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isBoolean=function(val,msg){new Assertion(val,msg,assert.isBoolean,true).to.be.a('boolean');};/** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.isNotBoolean=function(val,msg){new Assertion(val,msg,assert.isNotBoolean,true).to.not.be.a('boolean');};/** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @namespace Assert + * @api public + */assert.typeOf=function(val,type,msg){new Assertion(val,msg,assert.typeOf,true).to.be.a(type);};/** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @namespace Assert + * @api public + */assert.notTypeOf=function(val,type,msg){new Assertion(val,msg,assert.notTypeOf,true).to.not.be.a(type);};/** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */assert.instanceOf=function(val,type,msg){new Assertion(val,msg,assert.instanceOf,true).to.be.instanceOf(type);};/** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */assert.notInstanceOf=function(val,type,msg){new Assertion(val,msg,assert.notInstanceOf,true).to.not.be.instanceOf(type);};/** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Can be used to assert the + * inclusion of a value in an array, a substring in a string, or a subset of + * properties in an object. + * + * assert.include([1,2,3], 2, 'array contains value'); + * assert.include('foobar', 'foo', 'string contains substring'); + * assert.include({ foo: 'bar', hello: 'universe' }, { foo: 'bar' }, 'object contains property'); + * + * Strict equality (===) is used. When asserting the inclusion of a value in + * an array, the array is searched for an element that's strictly equal to the + * given value. When asserting a subset of properties in an object, the object + * is searched for the given property keys, checking that each one is present + * and strictly equal to the given property value. For instance: + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.include([obj1, obj2], obj1); + * assert.include({foo: obj1, bar: obj2}, {foo: obj1}); + * assert.include({foo: obj1, bar: obj2}, {foo: obj1, bar: obj2}); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.include=function(exp,inc,msg){new Assertion(exp,msg,assert.include,true).include(inc);};/** + * ### .notInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Can be used to assert + * the absence of a value in an array, a substring in a string, or a subset of + * properties in an object. + * + * assert.notInclude([1,2,3], 4, "array doesn't contain value"); + * assert.notInclude('foobar', 'baz', "string doesn't contain substring"); + * assert.notInclude({ foo: 'bar', hello: 'universe' }, { foo: 'baz' }, 'object doesn't contain property'); + * + * Strict equality (===) is used. When asserting the absence of a value in an + * array, the array is searched to confirm the absence of an element that's + * strictly equal to the given value. When asserting a subset of properties in + * an object, the object is searched to confirm that at least one of the given + * property keys is either not present or not strictly equal to the given + * property value. For instance: + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.notInclude([obj1, obj2], {a: 1}); + * assert.notInclude({foo: obj1, bar: obj2}, {foo: {a: 1}}); + * assert.notInclude({foo: obj1, bar: obj2}, {foo: obj1, bar: {b: 2}}); + * + * @name notInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notInclude,true).not.include(inc);};/** + * ### .deepInclude(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Can be used to assert the + * inclusion of a value in an array or a subset of properties in an object. + * Deep equality is used. + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.deepInclude([obj1, obj2], {a: 1}); + * assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}}); + * assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}}); + * + * @name deepInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.deepInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.deepInclude,true).deep.include(inc);};/** + * ### .notDeepInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Can be used to assert + * the absence of a value in an array or a subset of properties in an object. + * Deep equality is used. + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.notDeepInclude([obj1, obj2], {a: 9}); + * assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 9}}); + * assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 9}}); + * + * @name notDeepInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notDeepInclude,true).not.deep.include(inc);};/** + * ### .nestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.nestedInclude({'.a': {'b': 'x'}}, {'\\.a.[b]': 'x'}); + * assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'x'}); + * + * @name nestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.nestedInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.nestedInclude,true).nested.include(inc);};/** + * ### .notNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' does not include 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\.a.b': 'y'}); + * assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'y'}); + * + * @name notNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notNestedInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notNestedInclude,true).not.nested.include(inc);};/** + * ### .deepNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while checking for deep equality. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}}); + * assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}}); + * + * @name deepNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.deepNestedInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.deepNestedInclude,true).deep.nested.include(inc);};/** + * ### .notDeepNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' does not include 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while checking for deep equality. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}}) + * assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}}); + * + * @name notDeepNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepNestedInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notDeepNestedInclude,true).not.deep.nested.include(inc);};/** + * ### .ownInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while ignoring inherited properties. + * + * assert.ownInclude({ a: 1 }, { a: 1 }); + * + * @name ownInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.ownInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.ownInclude,true).own.include(inc);};/** + * ### .notOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while ignoring inherited properties. + * + * Object.prototype.b = 2; + * + * assert.notOwnInclude({ a: 1 }, { b: 2 }); + * + * @name notOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notOwnInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notOwnInclude,true).not.own.include(inc);};/** + * ### .deepOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while ignoring inherited properties and checking for deep equality. + * + * assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}}); + * + * @name deepOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.deepOwnInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.deepOwnInclude,true).deep.own.include(inc);};/** + * ### .notDeepOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while ignoring inherited properties and checking for deep equality. + * + * assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}}); + * + * @name notDeepOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepOwnInclude=function(exp,inc,msg){new Assertion(exp,msg,assert.notDeepOwnInclude,true).not.deep.own.include(inc);};/** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */assert.match=function(exp,re,msg){new Assertion(exp,msg,assert.match,true).to.match(re);};/** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */assert.notMatch=function(exp,re,msg){new Assertion(exp,msg,assert.notMatch,true).to.not.match(re);};/** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * assert.property({ tea: { green: 'matcha' }}, 'toString'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */assert.property=function(obj,prop,msg){new Assertion(obj,msg,assert.property,true).to.have.property(prop);};/** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */assert.notProperty=function(obj,prop,msg){new Assertion(obj,msg,assert.notProperty,true).to.not.have.property(prop);};/** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property` with a value given by `value`. Uses a strict equality check + * (===). + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.propertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.propertyVal,true).to.have.property(prop,val);};/** + * ### .notPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property` with value given by `value`. Uses a strict equality check + * (===). + * + * assert.notPropertyVal({ tea: 'is good' }, 'tea', 'is bad'); + * assert.notPropertyVal({ tea: 'is good' }, 'coffee', 'is good'); + * + * @name notPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.notPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.notPropertyVal,true).to.not.have.property(prop,val);};/** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property` with a value given by `value`. Uses a deep equality check. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' }); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.deepPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.deepPropertyVal,true).to.have.deep.property(prop,val);};/** + * ### .notDeepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property` with value given by `value`. Uses a deep equality check. + * + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' }); + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' }); + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' }); + * + * @name notDeepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.notDeepPropertyVal,true).to.not.have.deep.property(prop,val);};/** + * ### .ownProperty(object, property, [message]) + * + * Asserts that `object` has a direct property named by `property`. Inherited + * properties aren't checked. + * + * assert.ownProperty({ tea: { green: 'matcha' }}, 'tea'); + * + * @name ownProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */assert.ownProperty=function(obj,prop,msg){new Assertion(obj,msg,assert.ownProperty,true).to.have.own.property(prop);};/** + * ### .notOwnProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a direct property named by + * `property`. Inherited properties aren't checked. + * + * assert.notOwnProperty({ tea: { green: 'matcha' }}, 'coffee'); + * assert.notOwnProperty({}, 'toString'); + * + * @name notOwnProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */assert.notOwnProperty=function(obj,prop,msg){new Assertion(obj,msg,assert.notOwnProperty,true).to.not.have.own.property(prop);};/** + * ### .ownPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct property named by `property` and a value + * equal to the provided `value`. Uses a strict equality check (===). + * Inherited properties aren't checked. + * + * assert.ownPropertyVal({ coffee: 'is good'}, 'coffee', 'is good'); + * + * @name ownPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */assert.ownPropertyVal=function(obj,prop,value,msg){new Assertion(obj,msg,assert.ownPropertyVal,true).to.have.own.property(prop,value);};/** + * ### .notOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct property named by `property` + * with a value equal to the provided `value`. Uses a strict equality check + * (===). Inherited properties aren't checked. + * + * assert.notOwnPropertyVal({ tea: 'is better'}, 'tea', 'is worse'); + * assert.notOwnPropertyVal({}, 'toString', Object.prototype.toString); + * + * @name notOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */assert.notOwnPropertyVal=function(obj,prop,value,msg){new Assertion(obj,msg,assert.notOwnPropertyVal,true).to.not.have.own.property(prop,value);};/** + * ### .deepOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct property named by `property` and a value + * equal to the provided `value`. Uses a deep equality check. Inherited + * properties aren't checked. + * + * assert.deepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' }); + * + * @name deepOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */assert.deepOwnPropertyVal=function(obj,prop,value,msg){new Assertion(obj,msg,assert.deepOwnPropertyVal,true).to.have.deep.own.property(prop,value);};/** + * ### .notDeepOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct property named by `property` + * with a value equal to the provided `value`. Uses a deep equality check. + * Inherited properties aren't checked. + * + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' }); + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' }); + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' }); + * assert.notDeepOwnPropertyVal({}, 'toString', Object.prototype.toString); + * + * @name notDeepOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */assert.notDeepOwnPropertyVal=function(obj,prop,value,msg){new Assertion(obj,msg,assert.notDeepOwnPropertyVal,true).to.not.have.deep.own.property(prop,value);};/** + * ### .nestedProperty(object, property, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property`, which can be a string using dot- and bracket-notation for + * nested reference. + * + * assert.nestedProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name nestedProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */assert.nestedProperty=function(obj,prop,msg){new Assertion(obj,msg,assert.nestedProperty,true).to.have.nested.property(prop);};/** + * ### .notNestedProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for nested reference. The + * property cannot exist on the object nor anywhere in its prototype chain. + * + * assert.notNestedProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notNestedProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */assert.notNestedProperty=function(obj,prop,msg){new Assertion(obj,msg,assert.notNestedProperty,true).to.not.have.nested.property(prop);};/** + * ### .nestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for nested + * reference. Uses a strict equality check (===). + * + * assert.nestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name nestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.nestedPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.nestedPropertyVal,true).to.have.nested.property(prop,val);};/** + * ### .notNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a property named by `property` with + * value given by `value`. `property` can use dot- and bracket-notation for + * nested reference. Uses a strict equality check (===). + * + * assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'coffee.green', 'matcha'); + * + * @name notNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.notNestedPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.notNestedPropertyVal,true).to.not.have.nested.property(prop,val);};/** + * ### .deepNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with a value given + * by `value`. `property` can use dot- and bracket-notation for nested + * reference. Uses a deep equality check. + * + * assert.deepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yum' }); + * + * @name deepNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.deepNestedPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.deepNestedPropertyVal,true).to.have.deep.nested.property(prop,val);};/** + * ### .notDeepNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a property named by `property` with + * value given by `value`. `property` can use dot- and bracket-notation for + * nested reference. Uses a deep equality check. + * + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { oolong: 'yum' }); + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yuck' }); + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.black', { matcha: 'yum' }); + * + * @name notDeepNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */assert.notDeepNestedPropertyVal=function(obj,prop,val,msg){new Assertion(obj,msg,assert.notDeepNestedPropertyVal,true).to.not.have.deep.nested.property(prop,val);};/** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` or `size` with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 6, 'string has length of 6'); + * assert.lengthOf(new Set([1,2,3]), 3, 'set has size of 3'); + * assert.lengthOf(new Map([['a',1],['b',2],['c',3]]), 3, 'map has size of 3'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @namespace Assert + * @api public + */assert.lengthOf=function(exp,len,msg){new Assertion(exp,msg,assert.lengthOf,true).to.have.lengthOf(len);};/** + * ### .hasAnyKeys(object, [keys], [message]) + * + * Asserts that `object` has at least one of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'iDontExist', 'baz']); + * assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, iDontExist: 99, baz: 1337}); + * assert.hasAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.hasAnyKeys(new Set([{foo: 'bar'}, 'anotherKey']), [{foo: 'bar'}, 'anotherKey']); + * + * @name hasAnyKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.hasAnyKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.hasAnyKeys,true).to.have.any.keys(keys);};/** + * ### .hasAllKeys(object, [keys], [message]) + * + * Asserts that `object` has all and only all of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']); + * assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337]); + * assert.hasAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.hasAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']); + * + * @name hasAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.hasAllKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.hasAllKeys,true).to.have.all.keys(keys);};/** + * ### .containsAllKeys(object, [keys], [message]) + * + * Asserts that `object` has all of the `keys` provided but may have more keys not listed. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'baz']); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, baz: 1337}); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337}); + * assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}]); + * assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}]); + * assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']); + * + * @name containsAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.containsAllKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.containsAllKeys,true).to.contain.all.keys(keys);};/** + * ### .doesNotHaveAnyKeys(object, [keys], [message]) + * + * Asserts that `object` has none of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']); + * assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'}); + * assert.doesNotHaveAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']); + * assert.doesNotHaveAnyKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']); + * + * @name doesNotHaveAnyKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.doesNotHaveAnyKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.doesNotHaveAnyKeys,true).to.not.have.any.keys(keys);};/** + * ### .doesNotHaveAllKeys(object, [keys], [message]) + * + * Asserts that `object` does not have at least one of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']); + * assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'}); + * assert.doesNotHaveAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']); + * assert.doesNotHaveAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']); + * + * @name doesNotHaveAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.doesNotHaveAllKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.doesNotHaveAllKeys,true).to.not.have.all.keys(keys);};/** + * ### .hasAnyDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has at least one of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'}); + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'}); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {three: 'three'}]); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name hasAnyDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.hasAnyDeepKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.hasAnyDeepKeys,true).to.have.any.deep.keys(keys);};/** + * ### .hasAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has all and only all of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne']]), {one: 'one'}); + * assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAllDeepKeys(new Set([{one: 'one'}]), {one: 'one'}); + * assert.hasAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name hasAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.hasAllDeepKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.hasAllDeepKeys,true).to.have.all.deep.keys(keys);};/** + * ### .containsAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` contains all of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'}); + * assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'}); + * assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name containsAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.containsAllDeepKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.containsAllDeepKeys,true).to.contain.all.deep.keys(keys);};/** + * ### .doesNotHaveAnyDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has none of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'}); + * assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {fifty: 'fifty'}]); + * assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'}); + * assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{twenty: 'twenty'}, {fifty: 'fifty'}]); + * + * @name doesNotHaveAnyDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.doesNotHaveAnyDeepKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.doesNotHaveAnyDeepKeys,true).to.not.have.any.deep.keys(keys);};/** + * ### .doesNotHaveAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` does not have at least one of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'}); + * assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {one: 'one'}]); + * assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'}); + * assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {fifty: 'fifty'}]); + * + * @name doesNotHaveAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */assert.doesNotHaveAllDeepKeys=function(obj,keys,msg){new Assertion(obj,msg,assert.doesNotHaveAllDeepKeys,true).to.not.have.all.deep.keys(keys);};/** + * ### .throws(fn, [errorLike/string/regexp], [string/regexp], [message]) + * + * If `errorLike` is an `Error` constructor, asserts that `fn` will throw an error that is an + * instance of `errorLike`. + * If `errorLike` is an `Error` instance, asserts that the error thrown is the same + * instance as `errorLike`. + * If `errMsgMatcher` is provided, it also asserts that the error thrown will have a + * message matching `errMsgMatcher`. + * + * assert.throws(fn, 'Error thrown must have this msg'); + * assert.throws(fn, /Error thrown must have a msg that matches this/); + * assert.throws(fn, ReferenceError); + * assert.throws(fn, errorInstance); + * assert.throws(fn, ReferenceError, 'Error thrown must be a ReferenceError and have this msg'); + * assert.throws(fn, errorInstance, 'Error thrown must be the same errorInstance and have this msg'); + * assert.throws(fn, ReferenceError, /Error thrown must be a ReferenceError and match this/); + * assert.throws(fn, errorInstance, /Error thrown must be the same errorInstance and match this/); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} fn + * @param {ErrorConstructor|Error} errorLike + * @param {RegExp|String} errMsgMatcher + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */assert["throws"]=function(fn,errorLike,errMsgMatcher,msg){if('string'===typeof errorLike||errorLike instanceof RegExp){errMsgMatcher=errorLike;errorLike=null;}var assertErr=new Assertion(fn,msg,assert["throws"],true).to["throw"](errorLike,errMsgMatcher);return flag(assertErr,'object');};/** + * ### .doesNotThrow(fn, [errorLike/string/regexp], [string/regexp], [message]) + * + * If `errorLike` is an `Error` constructor, asserts that `fn` will _not_ throw an error that is an + * instance of `errorLike`. + * If `errorLike` is an `Error` instance, asserts that the error thrown is _not_ the same + * instance as `errorLike`. + * If `errMsgMatcher` is provided, it also asserts that the error thrown will _not_ have a + * message matching `errMsgMatcher`. + * + * assert.doesNotThrow(fn, 'Any Error thrown must not have this message'); + * assert.doesNotThrow(fn, /Any Error thrown must not match this/); + * assert.doesNotThrow(fn, Error); + * assert.doesNotThrow(fn, errorInstance); + * assert.doesNotThrow(fn, Error, 'Error must not have this message'); + * assert.doesNotThrow(fn, errorInstance, 'Error must not have this message'); + * assert.doesNotThrow(fn, Error, /Error must not match this/); + * assert.doesNotThrow(fn, errorInstance, /Error must not match this/); + * + * @name doesNotThrow + * @param {Function} fn + * @param {ErrorConstructor} errorLike + * @param {RegExp|String} errMsgMatcher + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */assert.doesNotThrow=function(fn,errorLike,errMsgMatcher,msg){if('string'===typeof errorLike||errorLike instanceof RegExp){errMsgMatcher=errorLike;errorLike=null;}new Assertion(fn,msg,assert.doesNotThrow,true).to.not["throw"](errorLike,errMsgMatcher);};/** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @namespace Assert + * @api public + */assert.operator=function(val,operator,val2,msg){var ok;switch(operator){case'==':ok=val==val2;break;case'===':ok=val===val2;break;case'>':ok=val>val2;break;case'>=':ok=val>=val2;break;case'<':ok=val} list + * @param {String} message + * @namespace Assert + * @api public + */assert.oneOf=function(inList,list,msg){new Assertion(inList,msg,assert.oneOf,true).to.be.oneOf(list);};/** + * ### .changes(function, object, property, [message]) + * + * Asserts that a function changes the value of a property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 22 }; + * assert.changes(fn, obj, 'val'); + * + * @name changes + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.changes=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}new Assertion(fn,msg,assert.changes,true).to.change(obj,prop);};/** + * ### .changesBy(function, object, property, delta, [message]) + * + * Asserts that a function changes the value of a property by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 2 }; + * assert.changesBy(fn, obj, 'val', 2); + * + * @name changesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.changesBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.changesBy,true).to.change(obj,prop).by(delta);};/** + * ### .doesNotChange(function, object, property, [message]) + * + * Asserts that a function does not change the value of a property. + * + * var obj = { val: 10 }; + * var fn = function() { console.log('foo'); }; + * assert.doesNotChange(fn, obj, 'val'); + * + * @name doesNotChange + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.doesNotChange=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}return new Assertion(fn,msg,assert.doesNotChange,true).to.not.change(obj,prop);};/** + * ### .changesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not change the value of a property or of a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 10 }; + * assert.changesButNotBy(fn, obj, 'val', 5); + * + * @name changesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.changesButNotBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.changesButNotBy,true).to.change(obj,prop).but.not.by(delta);};/** + * ### .increases(function, object, property, [message]) + * + * Asserts that a function increases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 13 }; + * assert.increases(fn, obj, 'val'); + * + * @name increases + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.increases=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}return new Assertion(fn,msg,assert.increases,true).to.increase(obj,prop);};/** + * ### .increasesBy(function, object, property, delta, [message]) + * + * Asserts that a function increases a numeric object property or a function's return value by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 10 }; + * assert.increasesBy(fn, obj, 'val', 10); + * + * @name increasesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.increasesBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.increasesBy,true).to.increase(obj,prop).by(delta);};/** + * ### .doesNotIncrease(function, object, property, [message]) + * + * Asserts that a function does not increase a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 8 }; + * assert.doesNotIncrease(fn, obj, 'val'); + * + * @name doesNotIncrease + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.doesNotIncrease=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}return new Assertion(fn,msg,assert.doesNotIncrease,true).to.not.increase(obj,prop);};/** + * ### .increasesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not increase a numeric object property or function's return value by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.increasesButNotBy(fn, obj, 'val', 10); + * + * @name increasesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.increasesButNotBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.increasesButNotBy,true).to.increase(obj,prop).but.not.by(delta);};/** + * ### .decreases(function, object, property, [message]) + * + * Asserts that a function decreases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreases(fn, obj, 'val'); + * + * @name decreases + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.decreases=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}return new Assertion(fn,msg,assert.decreases,true).to.decrease(obj,prop);};/** + * ### .decreasesBy(function, object, property, delta, [message]) + * + * Asserts that a function decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val -= 5 }; + * assert.decreasesBy(fn, obj, 'val', 5); + * + * @name decreasesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.decreasesBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.decreasesBy,true).to.decrease(obj,prop).by(delta);};/** + * ### .doesNotDecrease(function, object, property, [message]) + * + * Asserts that a function does not decreases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.doesNotDecrease(fn, obj, 'val'); + * + * @name doesNotDecrease + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.doesNotDecrease=function(fn,obj,prop,msg){if(arguments.length===3&&typeof obj==='function'){msg=prop;prop=null;}return new Assertion(fn,msg,assert.doesNotDecrease,true).to.not.decrease(obj,prop);};/** + * ### .doesNotDecreaseBy(function, object, property, delta, [message]) + * + * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.doesNotDecreaseBy(fn, obj, 'val', 1); + * + * @name doesNotDecreaseBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.doesNotDecreaseBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}return new Assertion(fn,msg,assert.doesNotDecreaseBy,true).to.not.decrease(obj,prop).by(delta);};/** + * ### .decreasesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreasesButNotBy(fn, obj, 'val', 1); + * + * @name decreasesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.decreasesButNotBy=function(fn,obj,prop,delta,msg){if(arguments.length===4&&typeof obj==='function'){var tmpMsg=delta;delta=prop;msg=tmpMsg;}else if(arguments.length===3){delta=prop;prop=null;}new Assertion(fn,msg,assert.decreasesButNotBy,true).to.decrease(obj,prop).but.not.by(delta);};/*! + * ### .ifError(object) + * + * Asserts if value is not a false value, and throws if it is a true value. + * This is added to allow for chai to be a drop-in replacement for Node's + * assert class. + * + * var err = new Error('I am a custom error'); + * assert.ifError(err); // Rethrows err! + * + * @name ifError + * @param {Object} object + * @namespace Assert + * @api public + */assert.ifError=function(val){if(val){throw val;}};/** + * ### .isExtensible(object) + * + * Asserts that `object` is extensible (can have new properties added to it). + * + * assert.isExtensible({}); + * + * @name isExtensible + * @alias extensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isExtensible=function(obj,msg){new Assertion(obj,msg,assert.isExtensible,true).to.be.extensible;};/** + * ### .isNotExtensible(object) + * + * Asserts that `object` is _not_ extensible. + * + * var nonExtensibleObject = Object.preventExtensions({}); + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * assert.isNotExtensible(nonExtensibleObject); + * assert.isNotExtensible(sealedObject); + * assert.isNotExtensible(frozenObject); + * + * @name isNotExtensible + * @alias notExtensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isNotExtensible=function(obj,msg){new Assertion(obj,msg,assert.isNotExtensible,true).to.not.be.extensible;};/** + * ### .isSealed(object) + * + * Asserts that `object` is sealed (cannot have new properties added to it + * and its existing properties cannot be removed). + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.seal({}); + * + * assert.isSealed(sealedObject); + * assert.isSealed(frozenObject); + * + * @name isSealed + * @alias sealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isSealed=function(obj,msg){new Assertion(obj,msg,assert.isSealed,true).to.be.sealed;};/** + * ### .isNotSealed(object) + * + * Asserts that `object` is _not_ sealed. + * + * assert.isNotSealed({}); + * + * @name isNotSealed + * @alias notSealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isNotSealed=function(obj,msg){new Assertion(obj,msg,assert.isNotSealed,true).to.not.be.sealed;};/** + * ### .isFrozen(object) + * + * Asserts that `object` is frozen (cannot have new properties added to it + * and its existing properties cannot be modified). + * + * var frozenObject = Object.freeze({}); + * assert.frozen(frozenObject); + * + * @name isFrozen + * @alias frozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isFrozen=function(obj,msg){new Assertion(obj,msg,assert.isFrozen,true).to.be.frozen;};/** + * ### .isNotFrozen(object) + * + * Asserts that `object` is _not_ frozen. + * + * assert.isNotFrozen({}); + * + * @name isNotFrozen + * @alias notFrozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isNotFrozen=function(obj,msg){new Assertion(obj,msg,assert.isNotFrozen,true).to.not.be.frozen;};/** + * ### .isEmpty(target) + * + * Asserts that the target does not contain any values. + * For arrays and strings, it checks the `length` property. + * For `Map` and `Set` instances, it checks the `size` property. + * For non-function objects, it gets the count of own + * enumerable string keys. + * + * assert.isEmpty([]); + * assert.isEmpty(''); + * assert.isEmpty(new Map); + * assert.isEmpty({}); + * + * @name isEmpty + * @alias empty + * @param {Object|Array|String|Map|Set} target + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isEmpty=function(val,msg){new Assertion(val,msg,assert.isEmpty,true).to.be.empty;};/** + * ### .isNotEmpty(target) + * + * Asserts that the target contains values. + * For arrays and strings, it checks the `length` property. + * For `Map` and `Set` instances, it checks the `size` property. + * For non-function objects, it gets the count of own + * enumerable string keys. + * + * assert.isNotEmpty([1, 2]); + * assert.isNotEmpty('34'); + * assert.isNotEmpty(new Set([5, 6])); + * assert.isNotEmpty({ key: 7 }); + * + * @name isNotEmpty + * @alias notEmpty + * @param {Object|Array|String|Map|Set} target + * @param {String} message _optional_ + * @namespace Assert + * @api public + */assert.isNotEmpty=function(val,msg){new Assertion(val,msg,assert.isNotEmpty,true).to.not.be.empty;};/*! + * Aliases. + */(function alias(name,as){assert[as]=assert[name];return alias;})('isOk','ok')('isNotOk','notOk')('throws','throw')('throws','Throw')('isExtensible','extensible')('isNotExtensible','notExtensible')('isSealed','sealed')('isNotSealed','notSealed')('isFrozen','frozen')('isNotFrozen','notFrozen')('isEmpty','empty')('isNotEmpty','notEmpty');};/*! + * chai + * Copyright(c) 2011-2014 Jake Luer * MIT Licensed - */var promiseExists=typeof Promise==='function';/* eslint-disable no-undef */var globalObject=(typeof self==="undefined"?"undefined":_typeof(self))==='object'?self:commonjsGlobal;// eslint-disable-line id-blacklist - var symbolExists=typeof Symbol!=='undefined';var mapExists=typeof Map!=='undefined';var setExists=typeof Set!=='undefined';var weakMapExists=typeof WeakMap!=='undefined';var weakSetExists=typeof WeakSet!=='undefined';var dataViewExists=typeof DataView!=='undefined';var symbolIteratorExists=symbolExists&&typeof Symbol.iterator!=='undefined';var symbolToStringTagExists=symbolExists&&typeof Symbol.toStringTag!=='undefined';var setEntriesExists=setExists&&typeof Set.prototype.entries==='function';var mapEntriesExists=mapExists&&typeof Map.prototype.entries==='function';var setIteratorPrototype=setEntriesExists&&Object.getPrototypeOf(new Set().entries());var mapIteratorPrototype=mapEntriesExists&&Object.getPrototypeOf(new Map().entries());var arrayIteratorExists=symbolIteratorExists&&typeof Array.prototype[Symbol.iterator]==='function';var arrayIteratorPrototype=arrayIteratorExists&&Object.getPrototypeOf([][Symbol.iterator]());var stringIteratorExists=symbolIteratorExists&&typeof String.prototype[Symbol.iterator]==='function';var stringIteratorPrototype=stringIteratorExists&&Object.getPrototypeOf(''[Symbol.iterator]());var toStringLeftSliceLength=8;var toStringRightSliceLength=-1;/** - * ### typeOf (obj) - * - * Uses `Object.prototype.toString` to determine the type of an object, - * normalising behaviour across engine versions & well optimised. - * - * @param {Mixed} object - * @return {String} object type - * @api public - */function typeDetect(obj){/* ! Speed optimisation - * Pre: - * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) - * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) - * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) - * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) - * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) - * Post: - * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) - * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) - * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) - * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) - * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) - */var typeofObj=_typeof(obj);if(typeofObj!=='object'){return typeofObj;}/* ! Speed optimisation - * Pre: - * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) - * Post: - * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) - */if(obj===null){return 'null';}/* ! Spec Conformance - * Test: `Object.prototype.toString.call(window)`` - * - Node === "[object global]" - * - Chrome === "[object global]" - * - Firefox === "[object Window]" - * - PhantomJS === "[object Window]" - * - Safari === "[object Window]" - * - IE 11 === "[object Window]" - * - IE Edge === "[object Window]" - * Test: `Object.prototype.toString.call(this)`` - * - Chrome Worker === "[object global]" - * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" - * - Safari Worker === "[object DedicatedWorkerGlobalScope]" - * - IE 11 Worker === "[object WorkerGlobalScope]" - * - IE Edge Worker === "[object WorkerGlobalScope]" - */if(obj===globalObject){return 'global';}/* ! Speed optimisation - * Pre: - * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) - * Post: - * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) - */if(Array.isArray(obj)&&(symbolToStringTagExists===false||!(Symbol.toStringTag in obj))){return 'Array';}// Not caching existence of `window` and related properties due to potential - // for `window` to be unset before tests in quasi-browser environments. - if((typeof window==="undefined"?"undefined":_typeof(window))==='object'&&window!==null){/* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/browsers.html#location) - * WhatWG HTML$7.7.3 - The `Location` interface - * Test: `Object.prototype.toString.call(window.location)`` - * - IE <=11 === "[object Object]" - * - IE Edge <=13 === "[object Object]" - */if(_typeof(window.location)==='object'&&obj===window.location){return 'Location';}/* ! Spec Conformance - * (https://html.spec.whatwg.org/#document) - * WhatWG HTML$3.1.1 - The `Document` object - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * WhatWG HTML states: - * > For historical reasons, Window objects must also have a - * > writable, configurable, non-enumerable property named - * > HTMLDocument whose value is the Document interface object. - * Test: `Object.prototype.toString.call(document)`` - * - Chrome === "[object HTMLDocument]" - * - Firefox === "[object HTMLDocument]" - * - Safari === "[object HTMLDocument]" - * - IE <=10 === "[object Document]" - * - IE 11 === "[object HTMLDocument]" - * - IE Edge <=13 === "[object HTMLDocument]" - */if(_typeof(window.document)==='object'&&obj===window.document){return 'Document';}if(_typeof(window.navigator)==='object'){/* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) - * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray - * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` - * - IE <=10 === "[object MSMimeTypesCollection]" - */if(_typeof(window.navigator.mimeTypes)==='object'&&obj===window.navigator.mimeTypes){return 'MimeTypeArray';}/* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) - * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray - * Test: `Object.prototype.toString.call(navigator.plugins)`` - * - IE <=10 === "[object MSPluginsCollection]" - */if(_typeof(window.navigator.plugins)==='object'&&obj===window.navigator.plugins){return 'PluginArray';}}if((typeof window.HTMLElement==='function'||_typeof(window.HTMLElement)==='object')&&obj instanceof window.HTMLElement){/* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) - * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` - * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` - * - IE <=10 === "[object HTMLBlockElement]" - */if(obj.tagName==='BLOCKQUOTE'){return 'HTMLQuoteElement';}/* ! Spec Conformance - * (https://html.spec.whatwg.org/#htmltabledatacellelement) - * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * Test: Object.prototype.toString.call(document.createElement('td')) - * - Chrome === "[object HTMLTableCellElement]" - * - Firefox === "[object HTMLTableCellElement]" - * - Safari === "[object HTMLTableCellElement]" - */if(obj.tagName==='TD'){return 'HTMLTableDataCellElement';}/* ! Spec Conformance - * (https://html.spec.whatwg.org/#htmltableheadercellelement) - * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * Test: Object.prototype.toString.call(document.createElement('th')) - * - Chrome === "[object HTMLTableCellElement]" - * - Firefox === "[object HTMLTableCellElement]" - * - Safari === "[object HTMLTableCellElement]" - */if(obj.tagName==='TH'){return 'HTMLTableHeaderCellElement';}}}/* ! Speed optimisation - * Pre: - * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) - * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) - * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) - * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) - * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) - * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) - * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) - * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) - * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) - * Post: - * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) - * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) - * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) - * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) - * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) - * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) - * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) - * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) - * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) - */var stringTag=symbolToStringTagExists&&obj[Symbol.toStringTag];if(typeof stringTag==='string'){return stringTag;}var objPrototype=Object.getPrototypeOf(obj);/* ! Speed optimisation - * Pre: - * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) - * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) - * Post: - * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) - * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) - */if(objPrototype===RegExp.prototype){return 'RegExp';}/* ! Speed optimisation - * Pre: - * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) - * Post: - * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) - */if(objPrototype===Date.prototype){return 'Date';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) - * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": - * Test: `Object.prototype.toString.call(Promise.resolve())`` - * - Chrome <=47 === "[object Object]" - * - Edge <=20 === "[object Object]" - * - Firefox 29-Latest === "[object Promise]" - * - Safari 7.1-Latest === "[object Promise]" - */if(promiseExists&&objPrototype===Promise.prototype){return 'Promise';}/* ! Speed optimisation - * Pre: - * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) - * Post: - * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) - */if(setExists&&objPrototype===Set.prototype){return 'Set';}/* ! Speed optimisation - * Pre: - * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) - * Post: - * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) - */if(mapExists&&objPrototype===Map.prototype){return 'Map';}/* ! Speed optimisation - * Pre: - * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) - * Post: - * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) - */if(weakSetExists&&objPrototype===WeakSet.prototype){return 'WeakSet';}/* ! Speed optimisation - * Pre: - * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) - * Post: - * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) - */if(weakMapExists&&objPrototype===WeakMap.prototype){return 'WeakMap';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) - * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": - * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` - * - Edge <=13 === "[object Object]" - */if(dataViewExists&&objPrototype===DataView.prototype){return 'DataView';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) - * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": - * Test: `Object.prototype.toString.call(new Map().entries())`` - * - Edge <=13 === "[object Object]" - */if(mapExists&&objPrototype===mapIteratorPrototype){return 'Map Iterator';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) - * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": - * Test: `Object.prototype.toString.call(new Set().entries())`` - * - Edge <=13 === "[object Object]" - */if(setExists&&objPrototype===setIteratorPrototype){return 'Set Iterator';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) - * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": - * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` - * - Edge <=13 === "[object Object]" - */if(arrayIteratorExists&&objPrototype===arrayIteratorPrototype){return 'Array Iterator';}/* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) - * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": - * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` - * - Edge <=13 === "[object Object]" - */if(stringIteratorExists&&objPrototype===stringIteratorPrototype){return 'String Iterator';}/* ! Speed optimisation - * Pre: - * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) - * Post: - * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) - */if(objPrototype===null){return 'Object';}return Object.prototype.toString.call(obj).slice(toStringLeftSliceLength,toStringRightSliceLength);}return typeDetect;});},{}]},{},[1]);var sinon$1=sinon;sinon.leakThreshold;sinon.assert;sinon.serverPrototype;sinon.getFakes;sinon.createStubInstance;sinon.inject;sinon.mock;sinon.reset;sinon.resetBehavior;sinon.resetHistory;sinon.restore;sinon.restoreContext;sinon.replace;sinon.define;sinon.replaceGetter;sinon.replaceSetter;sinon.spy;sinon.stub;sinon.fake;sinon.useFakeTimers;sinon.verify;sinon.verifyAndRestore;sinon.useFakeServer;sinon.useFakeXMLHttpRequest;sinon.usingPromise;sinon.createSandbox;sinon.match;sinon.restoreObject;sinon.expectation;sinon.defaultConfig;sinon.timers;sinon.xhr;sinon.FakeXMLHttpRequest;sinon.fakeServer;sinon.fakeServerWithClock;sinon.createFakeServer;sinon.createFakeServerWithClock;sinon.addBehavior;sinon.promise;describe('helpers',function(){beforeEach(function(){mParticle.init(apiKey,window.mParticle.config);});it('should correctly validate an attribute value',function(done){var validatedString=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue('testValue1');var validatedNumber=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(1);var validatedNull=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(null);var validatedObject=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue({});var validatedArray=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue([]);var validatedUndefined=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(undefined);validatedString.should.be.ok();validatedNumber.should.be.ok();validatedNull.should.be.ok();validatedObject.should.not.be.ok();validatedArray.should.not.be.ok();validatedUndefined.should.not.be.ok();done();});it('should return event name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.logEvent('eventName',mParticle.EventType.Location,{invalidValue:{}});bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'eventName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should return product name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.eCommerce.createProduct('productName','sku',1,1,'variant','category','brand','position','couponCode',{invalidValue:{}});bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'productName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should return commerce event name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');var product1=mParticle.eCommerce.createProduct('prod1','prod1sku',999);var product2=mParticle.eCommerce.createProduct('prod2','prod2sku',799);var customAttributes={invalidValue:{}};mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart,[product1,product2],customAttributes);bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'eCommerce - AddToCart', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should correctly validate an identity request with copyUserAttribute as a key using any identify method',function(done){var identityApiData={userIdentities:{customerid:'123'},copyUserAttributes:true};var identifyResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'identify');var logoutResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'logout');var loginResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'login');var modifyResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'modify');identifyResult.valid.should.equal(true);logoutResult.valid.should.equal(true);loginResult.valid.should.equal(true);modifyResult.valid.should.equal(true);done();});it('should correctly parse string or number',function(done){var string='abc';var number=123;var object={};var array=[];var stringResult=mParticle.getInstance()._Helpers.parseStringOrNumber(string);var numberResult=mParticle.getInstance()._Helpers.parseStringOrNumber(number);var objectResult=mParticle.getInstance()._Helpers.parseStringOrNumber(object);var arrayResult=mParticle.getInstance()._Helpers.parseStringOrNumber(array);var nullResult=mParticle.getInstance()._Helpers.parseStringOrNumber(null);stringResult.should.equal(string);numberResult.should.equal(number);Should(objectResult).not.be.ok();Should(arrayResult).not.be.ok();Should(nullResult).not.be.ok();done();});it('should filterUserIdentities and include customerId as first in the array',function(done){var filterList=[2,4,6,8];var userIdentitiesObject={email:'test@gmail.com',other:'abc',customerid:'123',facebook:'facebook123',google:'google123',yahoo:'yahoo123'};var filteredIdentities=mParticle.getInstance()._Helpers.filterUserIdentities(userIdentitiesObject,filterList);filteredIdentities.length.should.equal(3);filteredIdentities[0].should.have.property('Identity','123');filteredIdentities[0].should.have.property('Type',1);filteredIdentities[1].should.have.property('Identity','test@gmail.com');filteredIdentities[1].should.have.property('Type',7);filteredIdentities[2].should.have.property('Identity','abc');filteredIdentities[2].should.have.property('Type',0);done();});it('should return the appropriate boolean for if events should be delayed by an integration',function(done){var integrationDelays1={128:false,20:false,10:true};var integrationDelays2={128:true};var integrationDelays3={128:false};var integrationDelays4={128:false,20:false,10:false};var result1=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays1);var result2=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays2);var result3=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays3);var result4=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays4);result1.should.equal(true);result2.should.equal(true);result3.should.equal(false);result4.should.equal(false);done();});it('should return false if integration delay object is empty',function(done){var emptyIntegrationDelays={};var result1=mParticle.getInstance()._Helpers.isDelayedByIntegration(emptyIntegrationDelays);result1.should.equal(false);done();});it('should return expected boolean value when strings are passed',function(done){mParticle.getInstance()._Helpers.returnConvertedBoolean('false').should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(false).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('randomstring').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean(0).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(1).should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('0').should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('1').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean(null).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(undefined).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('').should.equal(false);done();});it('should return 0 when hashing undefined or null',function(done){mParticle.generateHash(undefined).should.equal(0);mParticle.generateHash(null).should.equal(0);_typeof$1(mParticle.generateHash(false)).should.equal('number');mParticle.generateHash(false).should.not.equal(0);done();});it('should generate random value',function(done){var randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();window.crypto.getRandomValues=undefined;randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();//old browsers may return undefined despite + */var hasRequiredChai;function requireChai(){if(hasRequiredChai)return chai$2;hasRequiredChai=1;(function(exports){var used=[];/*! + * Chai version + */exports.version='4.3.8';/*! + * Assertion Error + */exports.AssertionError=assertionError;/*! + * Utils for plugins (not exported) + */var util=requireUtils();/** + * # .use(function) + * + * Provides a way to extend the internals of Chai. + * + * @param {Function} + * @returns {this} for chaining + * @api public + */exports.use=function(fn){if(!~used.indexOf(fn)){fn(exports,util);used.push(fn);}return exports;};/*! + * Utility Functions + */exports.util=util;/*! + * Configuration + */var config=config$5;exports.config=config;/*! + * Primary `Assertion` prototype + */var assertion$1=assertion;exports.use(assertion$1);/*! + * Core Assertions + */var core=assertions;exports.use(core);/*! + * Expect interface + */var expect=expect$1;exports.use(expect);/*! + * Should interface + */var should$1=should;exports.use(should$1);/*! + * Assert interface + */var assert$1=assert;exports.use(assert$1);})(chai$2);return chai$2;}var chai=requireChai();var chai$1=/*@__PURE__*/getDefaultExportFromCjs(chai);var expect=chai$1.expect;chai$1.version;chai$1.Assertion;chai$1.AssertionError;chai$1.util;chai$1.config;chai$1.use;chai$1.should;chai$1.assert;chai$1.core;// TODO: This file is no longer the server model because the web SDK payload + var MessageType=Types.MessageType;var ApplicationTransitionType=Types.ApplicationTransitionType;// TODO: Make this a pure function that returns a new object + function convertCustomFlags(event,dto){var valueArray=[];dto.flags={};for(var prop in event.CustomFlags){valueArray=[];if(event.CustomFlags.hasOwnProperty(prop)){if(Array.isArray(event.CustomFlags[prop])){event.CustomFlags[prop].forEach(function(customFlagProperty){// TODO: Can we use our utility functions here? + if(typeof customFlagProperty==='number'||typeof customFlagProperty==='string'||typeof customFlagProperty==='boolean'){valueArray.push(customFlagProperty.toString());}});}else if(// TODO: Can we use our utility functions here? + typeof event.CustomFlags[prop]==='number'||typeof event.CustomFlags[prop]==='string'||typeof event.CustomFlags[prop]==='boolean'){valueArray.push(event.CustomFlags[prop].toString());}if(valueArray.length){dto.flags[prop]=valueArray;}}}}function convertProductToV2DTO(product){return {id:parseStringOrNumber(product.Sku),nm:parseStringOrNumber(product.Name),pr:parseNumber(product.Price),qt:parseNumber(product.Quantity),br:parseStringOrNumber(product.Brand),va:parseStringOrNumber(product.Variant),ca:parseStringOrNumber(product.Category),ps:parseNumber(product.Position),cc:parseStringOrNumber(product.CouponCode),tpa:parseNumber(product.TotalAmount),attrs:product.Attributes};}function convertProductListToV2DTO(productList){if(!productList){return [];}return productList.map(function(product){return convertProductToV2DTO(product);});}function ServerModel$1(mpInstance){var self=this;// TODO: Can we refactor this to not mutate the event? + this.appendUserInfo=function(user,event){if(!event){return;}if(!user){event.MPID=null;event.ConsentState=null;event.UserAttributes=null;event.UserIdentities=null;return;}if(event.MPID&&event.MPID===user.getMPID()){return;}event.MPID=user.getMPID();event.ConsentState=user.getConsentState();event.UserAttributes=user.getAllUserAttributes();var userIdentities=user.getUserIdentities().userIdentities;var dtoUserIdentities={};for(var identityKey in userIdentities){var identityType=Types.IdentityType.getIdentityType(identityKey);if(identityType!==false){dtoUserIdentities[identityType]=userIdentities[identityKey];}}var validUserIdentities=[];if(mpInstance._Helpers.isObject(dtoUserIdentities)){if(Object.keys(dtoUserIdentities).length){for(var key in dtoUserIdentities){var userIdentity={};userIdentity.Identity=dtoUserIdentities[key];userIdentity.Type=mpInstance._Helpers.parseNumber(key);validUserIdentities.push(userIdentity);}}}event.UserIdentities=validUserIdentities;};this.convertToConsentStateV2DTO=function(state){if(!state){return null;}var jsonObject={};var gdprConsentState=state.getGDPRConsentState();if(gdprConsentState){var gdpr={};jsonObject.gdpr=gdpr;for(var purpose in gdprConsentState){if(gdprConsentState.hasOwnProperty(purpose)){var gdprConsent=gdprConsentState[purpose];jsonObject.gdpr[purpose]={};if(typeof gdprConsent.Consented==='boolean'){gdpr[purpose].c=gdprConsent.Consented;}if(typeof gdprConsent.Timestamp==='number'){gdpr[purpose].ts=gdprConsent.Timestamp;}if(typeof gdprConsent.ConsentDocument==='string'){gdpr[purpose].d=gdprConsent.ConsentDocument;}if(typeof gdprConsent.Location==='string'){gdpr[purpose].l=gdprConsent.Location;}if(typeof gdprConsent.HardwareId==='string'){gdpr[purpose].h=gdprConsent.HardwareId;}}}}var ccpaConsentState=state.getCCPAConsentState();if(ccpaConsentState){jsonObject.ccpa={data_sale_opt_out:{c:ccpaConsentState.Consented,ts:ccpaConsentState.Timestamp,d:ccpaConsentState.ConsentDocument,l:ccpaConsentState.Location,h:ccpaConsentState.HardwareId}};}return jsonObject;};this.createEventObject=function(event,user){var uploadObject={};var eventObject={};// The `optOut` variable is passed later in this method to the `uploadObject` + // so that it can be used to denote whether or not a user has "opted out" of being + // tracked. If this is an `optOut` Event, we set `optOut` to the inverse of the SDK's + // `isEnabled` boolean which is controlled via `MPInstanceManager.setOptOut`. + var optOut=event.messageType===Types.MessageType.OptOut?!mpInstance._Store.isEnabled:null;// TODO: Why is Webview Bridge Enabled or Opt Out necessary here? + if(mpInstance._Store.sessionId||event.messageType===Types.MessageType.OptOut||mpInstance._Store.webviewBridgeEnabled){if(event.hasOwnProperty('toEventAPIObject')){eventObject=event.toEventAPIObject();}else {eventObject={// This is an artifact from v2 events where SessionStart/End and AST event + // names are numbers (1, 2, or 10), but going forward with v3, these lifecycle + // events do not have names, but are denoted by their `event_type` + EventName:event.name||event.messageType,EventCategory:event.eventType,EventAttributes:mpInstance._Helpers.sanitizeAttributes(event.data,event.name),SourceMessageId:event.sourceMessageId||mpInstance._Helpers.generateUniqueId(),EventDataType:event.messageType,CustomFlags:event.customFlags||{},UserAttributeChanges:event.userAttributeChanges,UserIdentityChanges:event.userIdentityChanges};}// TODO: Should we move this side effect outside of this method? + if(event.messageType!==Types.MessageType.SessionEnd){mpInstance._Store.dateLastEventSent=new Date();}uploadObject={// FIXME: Deprecate when we get rid of V2 + Store:mpInstance._Store.serverSettings,SDKVersion:Constants.sdkVersion,SessionId:mpInstance._Store.sessionId,SessionStartDate:mpInstance._Store.sessionStartDate?mpInstance._Store.sessionStartDate.getTime():0,Debug:mpInstance._Store.SDKConfig.isDevelopmentMode,Location:mpInstance._Store.currentPosition,OptOut:optOut,ExpandedEventCount:0,AppVersion:mpInstance.getAppVersion(),AppName:mpInstance.getAppName(),Package:mpInstance._Store.SDKConfig["package"],ClientGeneratedId:mpInstance._Store.clientId,DeviceId:mpInstance._Store.deviceId,IntegrationAttributes:mpInstance._Store.integrationAttributes,CurrencyCode:mpInstance._Store.currencyCode,DataPlan:mpInstance._Store.SDKConfig.dataPlan?mpInstance._Store.SDKConfig.dataPlan:{}};if(eventObject.EventDataType===MessageType.AppStateTransition){eventObject.IsFirstRun=mpInstance._Store.isFirstRun;eventObject.LaunchReferral=window.location.href||null;}// FIXME: Remove duplicate occurence + eventObject.CurrencyCode=mpInstance._Store.currencyCode;var currentUser=user||mpInstance.Identity.getCurrentUser();self.appendUserInfo(currentUser,eventObject);if(event.messageType===Types.MessageType.SessionEnd){eventObject.SessionLength=mpInstance._Store.dateLastEventSent.getTime()-mpInstance._Store.sessionStartDate.getTime();eventObject.currentSessionMPIDs=mpInstance._Store.currentSessionMPIDs;// Session attributes are assigned on a session level, but only uploaded + // when a session ends. As there is no way to attach event attributes to + // a `SessionEnd` event, we are uploading the session level attributes + // as event level attributes in a `SessionEnd` event. + eventObject.EventAttributes=mpInstance._Store.sessionAttributes;// TODO: We should move this out of here to avoid side effects + mpInstance._Store.currentSessionMPIDs=[];mpInstance._Store.sessionStartDate=null;}uploadObject.Timestamp=mpInstance._Store.dateLastEventSent.getTime();return mpInstance._Helpers.extend({},eventObject,uploadObject);}return null;};this.convertEventToV2DTO=function(event){var dto={n:event.EventName,et:event.EventCategory,ua:event.UserAttributes,ui:event.UserIdentities,ia:event.IntegrationAttributes,str:event.Store,attrs:event.EventAttributes,sdk:event.SDKVersion,sid:event.SessionId,sl:event.SessionLength,ssd:event.SessionStartDate,dt:event.EventDataType,dbg:event.Debug,ct:event.Timestamp,lc:event.Location,o:event.OptOut,eec:event.ExpandedEventCount,av:event.AppVersion,cgid:event.ClientGeneratedId,das:event.DeviceId,mpid:event.MPID,smpids:event.currentSessionMPIDs};if(event.DataPlan&&event.DataPlan.PlanId){dto.dp_id=event.DataPlan.PlanId;if(event.DataPlan.PlanVersion){dto.dp_v=event.DataPlan.PlanVersion;}}var consent=self.convertToConsentStateV2DTO(event.ConsentState);if(consent){dto.con=consent;}if(event.EventDataType===MessageType.AppStateTransition){dto.fr=event.IsFirstRun;dto.iu=false;dto.at=ApplicationTransitionType.AppInit;dto.lr=event.LaunchReferral;// Nullify Attributes in case AST Was logged manually or + // via logBaseEvent. AST should not have any attributes + dto.attrs=null;}if(event.CustomFlags){convertCustomFlags(event,dto);}if(event.EventDataType===MessageType.Commerce){dto.cu=event.CurrencyCode;// TODO: If Cart is deprecated, we should deprecate this too + if(event.ShoppingCart){dto.sc={pl:convertProductListToV2DTO(event.ShoppingCart.ProductList)};}if(event.ProductAction){dto.pd={an:event.ProductAction.ProductActionType,cs:mpInstance._Helpers.parseNumber(event.ProductAction.CheckoutStep),co:event.ProductAction.CheckoutOptions,pl:convertProductListToV2DTO(event.ProductAction.ProductList),ti:event.ProductAction.TransactionId,ta:event.ProductAction.Affiliation,tcc:event.ProductAction.CouponCode,tr:mpInstance._Helpers.parseNumber(event.ProductAction.TotalAmount),ts:mpInstance._Helpers.parseNumber(event.ProductAction.ShippingAmount),tt:mpInstance._Helpers.parseNumber(event.ProductAction.TaxAmount)};}else if(event.PromotionAction){dto.pm={an:event.PromotionAction.PromotionActionType,pl:event.PromotionAction.PromotionList.map(function(promotion){return {id:promotion.Id,nm:promotion.Name,cr:promotion.Creative,ps:promotion.Position?promotion.Position:0};})};}else if(event.ProductImpressions){dto.pi=event.ProductImpressions.map(function(impression){return {pil:impression.ProductImpressionList,pl:convertProductListToV2DTO(impression.ProductList)};});}}else if(event.EventDataType===MessageType.Profile){dto.pet=event.ProfileMessageType;}return dto;};}// This file is used ONLY for the mParticle ESLint plugin. It should NOT be used otherwise! + var mockFunction=function mockFunction(){return null;};var _BatchValidator=/** @class */function(){function _BatchValidator(){}_BatchValidator.prototype.getMPInstance=function(){return {// Certain Helper, Store, and Identity properties need to be mocked to be used in the `returnBatch` method + _Helpers:{sanitizeAttributes:window.mParticle.getInstance()._Helpers.sanitizeAttributes,generateHash:function generateHash(){return 'mockHash';},generateUniqueId:function generateUniqueId(){return 'mockId';},extend:window.mParticle.getInstance()._Helpers.extend,createServiceUrl:mockFunction,parseNumber:mockFunction,isObject:mockFunction,returnConvertedBoolean:mockFunction,Validators:null},_resetForTests:mockFunction,_APIClient:null,MPSideloadedKit:null,_Consent:null,_Events:null,_Forwarders:null,_NativeSdkHelpers:null,_Persistence:null,_preInit:null,Consent:null,_ServerModel:null,_SessionManager:null,_Store:{sessionId:'mockSessionId',sideloadedKits:[],devToken:'test_dev_token',isFirstRun:true,isEnabled:true,sessionAttributes:{},currentSessionMPIDs:[],consentState:null,clientId:null,deviceId:null,serverSettings:{},dateLastEventSent:null,sessionStartDate:null,currentPosition:null,isTracking:false,watchPositionId:null,cartProducts:[],eventQueue:[],currencyCode:null,globalTimer:null,context:null,configurationLoaded:false,identityCallInFlight:false,nonCurrentUserMPIDs:{},identifyCalled:false,isLoggedIn:false,cookieSyncDates:{},integrationAttributes:{},requireDelay:true,isLocalStorageAvailable:null,integrationDelayTimeoutStart:null,storageName:null,prodStorageName:null,activeForwarders:[],kits:{},configuredForwarders:[],pixelConfigurations:[],wrapperSDKInfo:{name:'none',version:null,isInfoSet:false},SDKConfig:{isDevelopmentMode:false,onCreateBatch:mockFunction}},config:null,eCommerce:null,Identity:{getCurrentUser:mockFunction,IdentityAPI:{},identify:mockFunction,login:mockFunction,logout:mockFunction,modify:mockFunction},Logger:{verbose:mockFunction,error:mockFunction,warning:mockFunction},ProductActionType:null,ServerModel:null,addForwarder:mockFunction,generateHash:mockFunction,getAppVersion:mockFunction,getAppName:mockFunction,getInstance:mockFunction,getDeviceId:mockFunction,init:mockFunction,logBaseEvent:mockFunction,logEvent:mockFunction,logLevel:'none',setPosition:mockFunction,upload:mockFunction};};_BatchValidator.prototype.createSDKEventFunction=function(event){return new ServerModel$1(this.getMPInstance()).createEventObject(event);};_BatchValidator.prototype.returnBatch=function(events){var _this=this;var mpInstance=this.getMPInstance();var sdkEvents=Array.isArray(events)?events.map(function(event){return _this.createSDKEventFunction(event);}):[this.createSDKEventFunction(events)];var batch=convertEvents('0',sdkEvents,mpInstance);return batch;};return _BatchValidator;}();function Logger(config){var self=this;var logLevel=config.logLevel||'warning';if(config.hasOwnProperty('logger')){this.logger=config.logger;}else {this.logger=new ConsoleLogger();}this.verbose=function(msg){if(logLevel!=='none'){if(self.logger.verbose&&logLevel==='verbose'){self.logger.verbose(msg);}}};this.warning=function(msg){if(logLevel!=='none'){if(self.logger.warning&&(logLevel==='verbose'||logLevel==='warning')){self.logger.warning(msg);}}};this.error=function(msg){if(logLevel!=='none'){if(self.logger.error){self.logger.error(msg);}}};this.setLogLevel=function(newLogLevel){logLevel=newLogLevel;};}function ConsoleLogger(){this.verbose=function(msg){if(console&&console.info){console.info(msg);}};this.error=function(msg){if(console&&console.error){console.error(msg);}};this.warning=function(msg){if(console&&console.warn){console.warn(msg);}};}var event0={EventName:'Test Event 0',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};var event1={EventName:'Test Event 1',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};var event2={EventName:'Test Event 2',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};var event3={EventName:'Test Event 3',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};var enableBatchingConfigFlags={eventBatchingIntervalMillis:1000};describe('batch uploader',function(){var mockServer;var clock;beforeEach(function(){client.restore();mockServer=sinon$1.createFakeServer();mockServer.respondImmediately=true;mockServer.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);});afterEach(function(){mockServer.reset();client.restore();window.localStorage.clear();});describe('Unit Tests',function(){describe('#queueEvent',function(){it('should add events to the Pending Events Queue',function(){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=new BatchUploader(mpInstance,1000);var event={EventName:'Test Event',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};uploader.queueEvent(event);expect(uploader.eventsQueuedForProcessing.length).to.eql(1);});it('should reject batches without events',function(){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=new BatchUploader(mpInstance,1000);uploader.queueEvent(null);uploader.queueEvent({});expect(uploader.eventsQueuedForProcessing).to.eql([]);expect(uploader.batchesQueuedForProcessing).to.eql([]);});it('should add events in the order they are received',function(){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=new BatchUploader(mpInstance,1000);uploader.queueEvent(event1);uploader.queueEvent(event2);uploader.queueEvent(event3);expect(uploader.eventsQueuedForProcessing.length).to.eql(3);expect(uploader.eventsQueuedForProcessing[0]).to.eql(event1);expect(uploader.eventsQueuedForProcessing[1]).to.eql(event2);expect(uploader.eventsQueuedForProcessing[2]).to.eql(event3);});});describe('#uploadBatches',function(){beforeEach(function(){window.mParticle.config.flags={eventBatchingIntervalMillis:1000};mockServer=sinon$1.createFakeServer();mockServer.respondImmediately=true;window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){client.restore();});it('should reject batches without events',function(){return __awaiter(void 0,void 0,void 0,function(){var newLogger,mpInstance,uploader,batchValidator,baseEvent,actualBatch,eventlessBatch,actualBatchResult;return __generator(this,function(_a){switch(_a.label){case 0:client.post(urls.events,200);newLogger=new Logger(window.mParticle.config);mpInstance=window.mParticle.getInstance();uploader=new BatchUploader(mpInstance,1000);batchValidator=new _BatchValidator();baseEvent={messageType:4,name:'testEvent'};actualBatch=batchValidator.returnBatch(baseEvent);eventlessBatch=batchValidator.returnBatch({});// HACK: Directly access uploader to Force an upload + return [4/*yield*/,uploader.uploadBatches(newLogger,[actualBatch,eventlessBatch],false)];case 1:// HACK: Directly access uploader to Force an upload + _a.sent();expect(client.calls().length).to.equal(1);actualBatchResult=JSON.parse(client.calls()[0][1].body);expect(actualBatchResult.events.length).to.equal(1);expect(actualBatchResult.events).to.eql(actualBatch.events);return [2/*return*/];}});});});it('should return batches that fail to upload with 500 errors',function(){return __awaiter(void 0,void 0,void 0,function(){var newLogger,mpInstance,uploader,batchValidator,batch1,batch2,batch3,batchesNotUploaded;return __generator(this,function(_a){switch(_a.label){case 0:client.post(urls.events,500);newLogger=new Logger(window.mParticle.config);mpInstance=window.mParticle.getInstance();uploader=new BatchUploader(mpInstance,1000);batchValidator=new _BatchValidator();batch1=batchValidator.returnBatch({messageType:4,name:'Test Event 1'});batch2=batchValidator.returnBatch({messageType:4,name:'Test Event 2'});batch3=batchValidator.returnBatch({messageType:4,name:'Test Event 3'});return [4/*yield*/,uploader.uploadBatches(newLogger,[batch1,batch2,batch3],false)];case 1:batchesNotUploaded=_a.sent();expect(batchesNotUploaded.length,'Should have 3 uploaded batches').to.equal(3);expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1');expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2');expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3');return [2/*return*/];}});});});it('should return batches that fail to upload with 429 errors',function(){return __awaiter(void 0,void 0,void 0,function(){var newLogger,mpInstance,uploader,batchValidator,batch1,batch2,batch3,batchesNotUploaded;return __generator(this,function(_a){switch(_a.label){case 0:client.post(urls.events,429);newLogger=new Logger(window.mParticle.config);mpInstance=window.mParticle.getInstance();uploader=new BatchUploader(mpInstance,1000);batchValidator=new _BatchValidator();batch1=batchValidator.returnBatch({messageType:4,name:'Test Event 1'});batch2=batchValidator.returnBatch({messageType:4,name:'Test Event 2'});batch3=batchValidator.returnBatch({messageType:4,name:'Test Event 3'});return [4/*yield*/,uploader.uploadBatches(newLogger,[batch1,batch2,batch3],false)];case 1:batchesNotUploaded=_a.sent();expect(batchesNotUploaded.length,'Should have 3 uploaded batches').to.equal(3);expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1');expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2');expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3');return [2/*return*/];}});});});it('should return null if batches fail to upload with 401 errors',function(){return __awaiter(void 0,void 0,void 0,function(){var newLogger,mpInstance,uploader,batchValidator,batch1,batch2,batch3,batchesNotUploaded;return __generator(this,function(_a){switch(_a.label){case 0:client.post(urls.events,401);newLogger=new Logger(window.mParticle.config);mpInstance=window.mParticle.getInstance();uploader=new BatchUploader(mpInstance,1000);batchValidator=new _BatchValidator();batch1=batchValidator.returnBatch({messageType:4,name:'Test Event 1'});batch2=batchValidator.returnBatch({messageType:4,name:'Test Event 2'});batch3=batchValidator.returnBatch({messageType:4,name:'Test Event 3'});return [4/*yield*/,uploader.uploadBatches(newLogger,[batch1,batch2,batch3],false)];case 1:batchesNotUploaded=_a.sent();expect(batchesNotUploaded===null).to.equal(true);return [2/*return*/];}});});});it('should return batches that fail to unknown HTTP errors',function(){return __awaiter(void 0,void 0,void 0,function(){var newLogger,mpInstance,uploader,batchValidator,batch1,batch2,batch3,batchesNotUploaded;return __generator(this,function(_a){switch(_a.label){case 0:client.post(urls.events,400);newLogger=new Logger(window.mParticle.config);mpInstance=window.mParticle.getInstance();uploader=new BatchUploader(mpInstance,1000);batchValidator=new _BatchValidator();batch1=batchValidator.returnBatch({messageType:4,name:'Test Event 1'});batch2=batchValidator.returnBatch({messageType:4,name:'Test Event 2'});batch3=batchValidator.returnBatch({messageType:4,name:'Test Event 3'});return [4/*yield*/,uploader.uploadBatches(newLogger,[batch1,batch2,batch3],false)];case 1:batchesNotUploaded=_a.sent();expect(batchesNotUploaded).to.be.ok;expect(batchesNotUploaded.length,'Should have 3 uploaded batches').to.equal(3);expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1');expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2');expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3');return [2/*return*/];}});});});});});describe('Offline Storage Feature Flag',function(){beforeEach(function(){sinon$1.restore();client.restore();mockServer.reset();window.localStorage.clear();window.sessionStorage.clear();});afterEach(function(){sinon$1.restore();client.restore();mockServer.reset();window.localStorage.clear();window.sessionStorage.clear();});it('should use local storage when enabled',function(done){window.mParticle.config.flags={offlineStorage:'100'};window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var getItemSpy=sinon$1.spy(Storage.prototype,'getItem');var setItemSpy=sinon$1.spy(Storage.prototype,'setItem');var mpInstance=window.mParticle.getInstance();var uploader=new BatchUploader(mpInstance,1000);var event={EventName:'Test Event',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};var expectedEvent=[event];uploader.queueEvent(event);expect(uploader.eventsQueuedForProcessing.length).to.eql(1);expect(setItemSpy.called).to.eq(true);expect(setItemSpy.getCall(0).lastArg).to.equal(JSON.stringify(expectedEvent));expect(getItemSpy.called).to.eq(true);expect(getItemSpy.getCall(0).lastArg).to.equal('mprtcl-v4_abcdef-events');done();});it('should not use local storage when disabled',function(){window.mParticle.config.flags={// offlineStorage: '0', // Defaults to 0, but test if not included, just in case + };window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var getItemSpy=sinon$1.spy(Storage.prototype,'getItem');var setItemSpy=sinon$1.spy(Storage.prototype,'setItem');var mpInstance=window.mParticle.getInstance();var uploader=new BatchUploader(mpInstance,1000);var event={EventName:'Test Event',EventAttributes:null,SourceMessageId:'test-smid',EventDataType:4,EventCategory:1,CustomFlags:{},IsFirstRun:false,CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],SDKVersion:'X.XX.XX',SessionId:'test-session-id',SessionStartDate:0,Debug:false,DeviceId:'test-device',Timestamp:0};uploader.queueEvent(event);expect(uploader.eventsQueuedForProcessing.length).to.eql(1);expect(uploader.eventsQueuedForProcessing[0]).to.eql(event);expect(setItemSpy.called).to.eq(false);expect(getItemSpy.called).to.eq(false);expect(window.localStorage.getItem('mprtcl-v4_abcdef-events')).to.equal(null);});});describe('Offline Storage Disabled',function(){beforeEach(function(){window.mParticle.config.flags=_assign({offlineStorage:'0'},enableBatchingConfigFlags);clock=sinon$1.useFakeTimers({now:new Date().getTime()});window.localStorage.clear();});afterEach(function(){sinon$1.restore();window.localStorage.clear();client.restore();clock.restore();});it('should not save events or batches in local storage',function(done){var eventStorageKey='mprtcl-v4_abcdef-events';var batchStorageKey='mprtcl-v4_abcdef-batches';window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);var eventQueue=uploader.eventsQueuedForProcessing;expect(eventQueue.length).to.equal(3);expect(window.localStorage.getItem(eventStorageKey),'Local Storage Events should be empty').to.equal(null);var batchQueue=uploader.batchesQueuedForProcessing;// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();expect(batchQueue.length).to.equal(2);expect(window.localStorage.getItem(batchStorageKey),'Local Storage Batches should be empty').to.equal(null);done();});});describe('Offline Storage Enabled',function(){beforeEach(function(){window.mParticle.config.flags=_assign({offlineStorage:'100'},enableBatchingConfigFlags);clock=sinon$1.useFakeTimers({now:new Date().getTime()});client.restore();window.sessionStorage.clear();window.localStorage.clear();});afterEach(function(){sinon$1.restore();client.restore();clock.restore();});it('should store events in Session Storage in order of creation',function(done){var eventStorageKey='mprtcl-v4_abcdef-events';window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);var eventQueue=uploader.eventsQueuedForProcessing;expect(eventQueue.length).to.equal(3);var storedEvents=JSON.parse(window.sessionStorage.getItem(eventStorageKey));expect(storedEvents.length,'Local Storage Events').to.equal(3);expect(storedEvents[0],'Local Storage: Session Start').to.eql(eventQueue[0]);expect(storedEvents[1],'Local Storage: AST').to.eql(eventQueue[1]);expect(storedEvents[2],'Local Storage: Test Event 0').to.eql(eventQueue[2]);done();});it('should purge events from Session Storage upon Batch Creation',function(done){var eventStorageKey='mprtcl-v4_abcdef-events';client.post(urls.events,200);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);expect(uploader.eventsQueuedForProcessing.length).to.equal(3);expect(uploader.batchesQueuedForProcessing.length).to.equal(0);expect(window.sessionStorage.getItem(eventStorageKey),'Queued Events should appear in Session Storage').to.be.ok;expect(JSON.parse(window.sessionStorage.getItem(eventStorageKey)).length).to.equal(3);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// If Session Storage is purged, it should return an empty string + expect(window.sessionStorage.getItem(eventStorageKey)).to.equal('');expect(uploader.eventsQueuedForProcessing.length).to.equal(0);// Batch Queue should be empty because batch successfully uploaded + expect(uploader.batchesQueuedForProcessing.length).to.equal(0);clock.restore();// Call a set timeout to catch the upload so that it does not + // collide with other tests. Unfortunately our setup/teardown + // does not catch async upload attempts + setTimeout(function(){console.warn('test 2 end');done();},0);});it('should save batches in sequence to Local Storage when an HTTP 500 error is encountered',function(done){var batchStorageKey='mprtcl-v4_abcdef-batches';client.post(urls.events,500);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();clock.restore();setTimeout(function(){expect(window.localStorage.getItem(batchStorageKey)).to.be.ok;var storedBatches=JSON.parse(window.localStorage.getItem(batchStorageKey));// Note: Events are usually are groupd together into a single batch + // However, in this case, since we are mocking a custom event (event0) + // our batching logic is grouping event0 into a separate batch from + // the Session Start + AST event from init as they have a different + // SessionID + expect(storedBatches.length).to.equal(2);expect(storedBatches[0].events[0].event_type,'Batch 1: Session Start').to.equal('session_start');expect(storedBatches[0].events[1].event_type,'Batch 1: AST').to.equal('application_state_transition');expect(storedBatches[1].events[0].event_type,'Batch 2: Custom Event Type').to.equal('custom_event');expect(storedBatches[1].events[0].data.event_name,'Batch 2: Custom Event Name').to.equal('Test Event 0');done();},0);});it('should save batches in sequence to Local Storage when an HTTP 429 error is encountered',function(done){var batchStorageKey='mprtcl-v4_abcdef-batches';client.post(urls.events,429);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();clock.restore();setTimeout(function(){expect(window.localStorage.getItem(batchStorageKey)).to.be.ok;var storedBatches=JSON.parse(window.localStorage.getItem(batchStorageKey));expect(storedBatches.length).to.equal(2);expect(storedBatches[0].events[0].event_type,'Batch 1: Session Start').to.equal('session_start');expect(storedBatches[0].events[1].event_type,'Batch 1: AST').to.equal('application_state_transition');expect(storedBatches[1].events[0].event_type,'Batch 2: Custom Event Type').to.equal('custom_event');expect(storedBatches[1].events[0].data.event_name,'Batch 2: Custom Event Name').to.equal('Test Event 0');done();},0);});it('should NOT save any batches to Local Storage when an HTTP 401 error is encountered',function(done){// When a 401 is encountered, we assume that the batch is bad so we clear those + // batches from the Upload Queue. Therefore, there should not be anything in + // Offline Storage afterwards + var batchStorageKey='mprtcl-v4_abcdef-batches';client.post(urls.events,401);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;// Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();clock.restore();setTimeout(function(){expect(window.localStorage.getItem(batchStorageKey)).to.equal('');done();},0);});it('should save batches in sequence to Local Storage when upload is interrupted',function(done){// Interruption in this context means that the first upload is successful, but + // the next upload in sequence is not. For example, on a mobile device on the + // subway or if a connection is rate limited. In this case, we should save + // batches in the order they were created for a future upload attempt + var batchStorageKey='mprtcl-v4_abcdef-batches';// First upload is successful + client.post(urls.events,200,{overwriteRoutes:false,repeat:1});// Second upload is rate limited + client.post(urls.events,429,{overwriteRoutes:false});// Set up SDK and Uploader + window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;var batchValidator=new _BatchValidator();// Create sample batches for testing + var batch1=batchValidator.returnBatch([{messageType:4,name:'Test Event 1'},{messageType:4,name:'Test Event 2'}]);var batch2=batchValidator.returnBatch([{messageType:4,name:'Test Event 3'},{messageType:4,name:'Test Event 4'}]);var batch3=batchValidator.returnBatch([{messageType:4,name:'Test Event 5'},{messageType:4,name:'Test Event 6'}]);// Init will generate a batch with Session Start and AST which normally comes first + // but for testing purposes the Session Start + AST batches will be the last batches + // as we are manually queueing additional batches to verify sequence + uploader.batchesQueuedForProcessing.push(batch1);uploader.batchesQueuedForProcessing.push(batch2);uploader.batchesQueuedForProcessing.push(batch3);// Manually initiate the upload process + // This will also turn the SessionStart + AST events into a batch and add it to the end of the queue + window.mParticle.upload();clock.restore();setTimeout(function(){expect(window.localStorage.getItem(batchStorageKey)).to.be.ok;var storedBatches=JSON.parse(window.localStorage.getItem(batchStorageKey));// We tried to upload 4 batches (3 unique batches + Session Start/AST from init) + expect(storedBatches.length).to.equal(3);// The following assertions should verify the sequence presented below + // - Batch 1: Test Event 1 and 2 - Should have been uploaded - No Longer in Offline Storage + // - Batch 2: Test Event 3 and 4 - Failed Upload - Saved to Offline Storage + // - Batch 3: Test Event 5 and 6 - Upload suspended - Saved to Offline Storage + // - Batch 4: Session Start and AST - Upload suspended - Saved to Offline Storage + // Because Batch 2 failed to upload, subsequent Batches should be suspended until Batch 2 succeeds + expect(storedBatches[0].events[0].event_type,'Batch 2: Test Event 3 Event Type').to.equal('custom_event');expect(storedBatches[0].events[0].data.event_name,'Batch 2: Test Event 3 Event Name').to.equal('Test Event 3');expect(storedBatches[0].events[1].event_type,'Batch 2: Test Event 4 Event Type').to.equal('custom_event');expect(storedBatches[0].events[1].data.event_name,'Batch 2: Test Event 4 Event Name').to.equal('Test Event 4');expect(storedBatches[1].events[0].event_type,'Batch 3: Test Event 5 Event Type').to.equal('custom_event');expect(storedBatches[1].events[0].data.event_name,'Batch 3: Test Event 5 Event Name').to.equal('Test Event 5');expect(storedBatches[1].events[1].event_type,'Batch 3: Test Event 6 Event Type').to.equal('custom_event');expect(storedBatches[1].events[1].data.event_name,'Batch 3: Test Event 6 Event Name').to.equal('Test Event 6');// These are the events that are generated by mParticle.init. Usually they + // come before any queued events, but we manually queued the previous + // batches increase the number of attempted uploads to verify that batches + // are retained in Offline Storage in order of creation + expect(storedBatches[2].events[0].event_type,'Batch 4: Session Start').to.equal('session_start');expect(storedBatches[2].events[1].event_type,'Batch 4: AST').to.equal('application_state_transition');done();},0);});it('should attempt to upload batches from Offline Storage before new batches',function(done){// This test should verify that batches read from Offline Storage are prepended + // to the upload queue before newly created batches. + var batchStorageKey='mprtcl-v4_abcdef-batches';client.post(urls.events,200);// Set up SDK and Uploader + window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();var uploader=mpInstance._APIClient.uploader;var batchValidator=new _BatchValidator();// Create sample batches for testing + var batch1=batchValidator.returnBatch([{messageType:4,name:'Test Event 1'},{messageType:4,name:'Test Event 2'}]);var batch2=batchValidator.returnBatch([{messageType:4,name:'Test Event 3'},{messageType:4,name:'Test Event 4'}]);var batch3=batchValidator.returnBatch([{messageType:4,name:'Test Event 5'},{messageType:4,name:'Test Event 6'}]);// Write batches to Offline Storage before queuing new events or batches + window.localStorage.setItem(batchStorageKey,JSON.stringify([batch1,batch2,batch3]));// Batch Queue should be empty before we upload + expect(uploader.batchesQueuedForProcessing.length).to.equal(0);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();clock.restore();setTimeout(function(){expect(window.localStorage.getItem(batchStorageKey),'Offline Batch Storage should be empty').to.equal('');// To verify the sequence, we should look at what has been uploaded + // as the upload queue and Offline Storage should be empty + expect(client.calls().length).to.equal(4);var uploadedBatch1=JSON.parse(client.calls()[0][1].body);var uploadedBatch2=JSON.parse(client.calls()[1][1].body);var uploadedBatch3=JSON.parse(client.calls()[2][1].body);var uploadedBatch4=JSON.parse(client.calls()[3][1].body);// The following assertions should verify the sequence presented below + // - Batch 1: Test Event 1 and 2 - Read from Offline Storage + // - Batch 2: Test Event 3 and 4 - Read from Offline Storage + // - Batch 3: Test Event 5 and 6 - Read from Offline Storage + // - Batch 4: Session Start and AST - (new) Created by Init + expect(uploadedBatch1.events[0].data.event_name,'Batch 1: Test Event 1 ').to.equal('Test Event 1');expect(uploadedBatch1.events[1].data.event_name,'Batch 1: Test Event 2').to.equal('Test Event 2');expect(uploadedBatch2.events[0].data.event_name,'Batch 2: Test Event 3 Event Name').to.equal('Test Event 3');expect(uploadedBatch2.events[1].data.event_name,'Batch 2: Test Event 4 Event Name').to.equal('Test Event 4');expect(uploadedBatch3.events[0].data.event_name,'Batch 2: Test Event 5 Event Name').to.equal('Test Event 5');expect(uploadedBatch3.events[1].data.event_name,'Batch 2: Test Event 6 Event Name').to.equal('Test Event 6');// These are the events that are generated by mParticle.init. Usually they + // come before any queued events, but we manually queued the previous + // batches increase the number of attempted uploads to verify that batches + // are retained in Offline Storage in order of creation + expect(uploadedBatch4.events[0].event_type,'Batch 4: Session Start').to.equal('session_start');expect(uploadedBatch4.events[1].event_type,'Batch 4: AST').to.equal('application_state_transition');done();},0);});});describe('Upload Workflow',function(){beforeEach(function(){clock=sinon$1.useFakeTimers({now:new Date().getTime()});});afterEach(function(){client.restore();clock.restore();});it('should organize events in the order they are processed and maintain that order when uploading',function(done){// Batches should be uploaded in the order they were created to prevent + // any potential corruption. + client.post(urls.events,200);client.config.overwriteRoutes=true;window.mParticle.config.flags=_assign({},enableBatchingConfigFlags);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event 0');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();expect(client.called(),'FetchMock should have been called').to.equal(true);var batch1=JSON.parse(client._calls[0][1].body);// Batch 1 should contain only session start, AST and a single event + // in this exact order + expect(batch1.events.length).to.equal(3);expect(batch1.events[0].event_type).to.equal('session_start');expect(batch1.events[1].event_type).to.equal('application_state_transition');expect(batch1.events[2].data.event_name).to.equal('Test Event 0');// Log a second batch of events + window.mParticle.logEvent('Test Event 1');window.mParticle.logEvent('Test Event 2');window.mParticle.logEvent('Test Event 3');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();var batch2=JSON.parse(client._calls[1][1].body);// Batch 2 should contain three custom events + expect(batch2.events.length).to.equal(3);expect(batch2.events[0].data.event_name).to.equal('Test Event 1');expect(batch2.events[1].data.event_name).to.equal('Test Event 2');expect(batch2.events[2].data.event_name).to.equal('Test Event 3');// Log a third batch of events + window.mParticle.logEvent('Test Event 4');window.mParticle.logEvent('Test Event 5');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();var batch3=JSON.parse(client._calls[2][1].body);// Batch 3 should contain two custom events + expect(batch3.events.length).to.equal(2);expect(batch3.events[0].data.event_name).to.equal('Test Event 4');expect(batch3.events[1].data.event_name).to.equal('Test Event 5');done();});// TODO: Investigate workflow with unshift vs push + // https://go.mparticle.com/work/SQDSDKS-5165 + it.skip('should keep batches in sequence for future retries when an HTTP 500 error occurs',function(done){// If batches cannot upload, they should be added back to the Batch Queue + // in the order they were created so they can be retransmitted. + client.post(urls.events,500);window.mParticle.config.flags=_assign({},enableBatchingConfigFlags);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);// Generates Batch 1 with Session Start + AST + // Adds a custom event to Batch 1 + window.mParticle.logEvent('Test Event 0');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();expect(client.called(),'FetchMock should have been called').to.equal(true);var batch1=JSON.parse(client._calls[0][1].body);// Batch 1 should contain only session start, AST and a single event + // in this exact order + expect(batch1.events.length).to.equal(3);expect(batch1.events[0].event_type).to.equal('session_start');expect(batch1.events[1].event_type).to.equal('application_state_transition');expect(batch1.events[2].data.event_name).to.equal('Test Event 0');// Batch 2 + window.mParticle.logEvent('Test Event 1');window.mParticle.logEvent('Test Event 2');window.mParticle.logEvent('Test Event 3');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// Batch 3 + window.mParticle.logEvent('Test Event 4');window.mParticle.logEvent('Test Event 5');window.mParticle.logEvent('Test Event 6');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// Reset clock so that the setTimeout return immediately + clock.restore();setTimeout(function(){var batchQueue=window.mParticle.getInstance()._APIClient.uploader.batchesQueuedForProcessing;expect(batchQueue.length).to.equal(3);expect(batchQueue[0].events[0].event_type).to.equal('session_start');expect(batchQueue[0].events[1].event_type).to.equal('application_state_transition');expect(batchQueue[0].events[2].data.event_name).to.equal('Test Event 0');expect(batchQueue[1].events[0].data.event_name).to.equal('Test Event 1');expect(batchQueue[1].events[1].data.event_name).to.equal('Test Event 2');expect(batchQueue[1].events[2].data.event_name).to.equal('Test Event 3');expect(batchQueue[2].events[0].data.event_name).to.equal('Test Event 4');expect(batchQueue[2].events[1].data.event_name).to.equal('Test Event 5');expect(batchQueue[2].events[2].data.event_name).to.equal('Test Event 6');done();},0);});// TODO: Investigate workflow with unshift vs push + // https://go.mparticle.com/work/SQDSDKS-5165 + it.skip('should keep and retry batches in sequence if the transmission fails midway',function(done){// First request is successful, subsequent requests fail + client.post(urls.events,200,{overwriteRoutes:false,repeat:1});client.post(urls.events,429,{overwriteRoutes:false});window.mParticle.config.flags=_assign({},enableBatchingConfigFlags);window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);// Generates Batch 1 with Session Start + AST + // Adds a custom event to Batch 1 + window.mParticle.logEvent('Test Event 0');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// Batch 2 + window.mParticle.logEvent('Test Event 1');window.mParticle.logEvent('Test Event 2');window.mParticle.logEvent('Test Event 3');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// Batch 3 + window.mParticle.logEvent('Test Event 4');window.mParticle.logEvent('Test Event 5');window.mParticle.logEvent('Test Event 6');// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// Reset timer so the setTimeout can trigger + clock.restore();setTimeout(function(){// Batch upload should be triggered 3 times, but only + // 2 should be waiting for retry + expect(client.calls().length).to.equal(3);var batchQueue=window.mParticle.getInstance()._APIClient.uploader.batchesQueuedForProcessing;expect(batchQueue.length).to.equal(2);expect(batchQueue[0].events[0].data.event_name).to.equal('Test Event 1');expect(batchQueue[0].events[1].data.event_name).to.equal('Test Event 2');expect(batchQueue[0].events[2].data.event_name).to.equal('Test Event 3');expect(batchQueue[1].events[0].data.event_name).to.equal('Test Event 4');expect(batchQueue[1].events[1].data.event_name).to.equal('Test Event 5');expect(batchQueue[1].events[2].data.event_name).to.equal('Test Event 6');done();},0);});});describe('batching via window.fetch',function(){beforeEach(function(){client.post(urls.events,200);client.config.overwriteRoutes=true;clock=sinon$1.useFakeTimers({now:new Date().getTime()});window.mParticle.config.flags=_assign({},enableBatchingConfigFlags);});afterEach(function(){client.restore();sinon$1.restore();clock.restore();});it('should use custom v3 endpoint',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1);// Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000);var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should have latitude/longitude for location when batching',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.setPosition(100,100);window.mParticle.logEvent('Test Event');clock.tick(1000);// Tick forward 1000 ms to hit upload interval and force an upload + var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);batch.events[2].data.location.should.have.property('latitude',100);batch.events[2].data.location.should.have.property('longitude',100);done();});it('should force uploads when using public `upload`',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1);// no calls made to fetch yet + (client.lastCall()===undefined).should.equal(true);// force upload, triggering window.fetch + window.mParticle.upload();var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should force uploads when a commerce event is called',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1);var product1=window.mParticle.eCommerce.createProduct('iphone','iphoneSKU',999);window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart,product1);var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');batch.events[3].event_type.should.equal('commerce_event');batch.events[3].data.product_action.action.should.equal('add_to_cart');done();});it('should return pending uploads if a 500 is returned',function(done){window.mParticle._resetForTests(MPConfig);// var clock = sinon.useFakeTimers(); + client.post(urls.events,500);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');var pendingEvents=window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing;pendingEvents.length.should.equal(3);pendingEvents[0].EventName.should.equal(1);pendingEvents[1].EventName.should.equal(10);pendingEvents[2].EventName.should.equal('Test Event');client.post(urls.events,200);(client.lastCall()===undefined).should.equal(true);clock.tick(1000);var nowPendingEvents=window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing;nowPendingEvents.length.should.equal(0);var batch=JSON.parse(client.lastCall()[1].body);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should send source_message_id with events to v3 endpoint',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000);var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);batch.events[0].data.should.have.property('source_message_id');done();});it('should send user-defined SourceMessageId events to v3 endpoint',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logBaseEvent({messageType:4,name:'Test Event',data:{key:'value'},eventType:3,customFlags:{flagKey:'flagValue'},sourceMessageId:'abcdefg'});// Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1);// Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000);var lastCall=client.lastCall();var endpoint=lastCall[0];var batch=JSON.parse(client.lastCall()[1].body);endpoint.should.equal(urls.events);// event batch includes session start, ast, then last event is Test Event + batch.events[batch.events.length-1].data.should.have.property('source_message_id','abcdefg');done();});it('should call the identity callback after a session ends if user is returning to the page after a long period of time',function(done){// Background of bug that this test fixes: + // User navigates away from page and returns after some time + // and the session should end. There is a UAC firing inside of + // config.identityCallback, which would send to our servers with + // the previous session ID because the identity call back fired + // before the session logic that determines if a new session should + // start. + window.mParticle._resetForTests(MPConfig);window.mParticle.config.identityCallback=function(result){var currentUser=result.getUser();if(currentUser){// TODO: Investigate if we should update definitely typed typings for + // setUserAttribute which only allows strings right now + // more context at https://go.mparticle.com/work/SQDSDKS-4576 + currentUser.setUserAttribute("number","".concat(Math.floor(Math.random()*1000+1)));}};var endSessionFunction=window.mParticle.getInstance()._SessionManager.endSession;window.mParticle.init(apiKey,window.mParticle.config);// Mock end session so that the SDK doesn't actually send it. We do this + // to mimic a return to page behavior, below: + window.mParticle.getInstance()._SessionManager.endSession=function(){};// Force 35 minutes to pass, so that when we return to the page, when + // the SDK initializes it will know to end the session. + clock.tick(35*60000);// Undo mock of end session so that when we initializes, it will end + // the session for real. + window.mParticle.getInstance()._SessionManager.endSession=endSessionFunction;// Initialize imitates returning to the page + window.mParticle.init(apiKey,window.mParticle.config);// Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload();// We have to restore the clock in order to use setTimeout below + clock.restore();setTimeout(function(){var batch1=JSON.parse(client._calls[0][1].body);var batch2=JSON.parse(client._calls[1][1].body);var batch3=JSON.parse(client._calls[2][1].body);var batch4=JSON.parse(client._calls[3][1].body);var batch5=JSON.parse(client._calls[4][1].body);// UAC event + expect(batch1.events.length,'Batch 1: UAC event').to.equal(1);// session start, AST + expect(batch2.events.length,'Batch 2: Session Start, AST').to.equal(2);// session end + expect(batch3.events.length,'Batch 3: Session End').to.equal(1);// UAC event + expect(batch4.events.length,'Batch 5: Session Start, AST').to.equal(2);// session start, AST + expect(batch5.events.length,'Batch 4: UAC event').to.equal(1);var batch1UAC=TestsCore.findEventFromBatch(batch1,'user_attribute_change');batch1UAC.should.be.ok();var batch2SessionStart=TestsCore.findEventFromBatch(batch2,'session_start');var batch2AST=TestsCore.findEventFromBatch(batch2,'application_state_transition');batch2SessionStart.should.be.ok();batch2AST.should.be.ok();var batch3SessionEnd=TestsCore.findEventFromBatch(batch3,'session_end');batch3SessionEnd.should.be.ok();var batch4SessionStart=TestsCore.findEventFromBatch(batch4,'session_start');var batch4AST=TestsCore.findEventFromBatch(batch4,'application_state_transition');batch4SessionStart.should.be.ok();batch4AST.should.be.ok();var batch5UAC=TestsCore.findEventFromBatch(batch5,'user_attribute_change');batch5UAC.should.be.ok();_typeof(batch1.source_request_id).should.equal('string');_typeof(batch2.source_request_id).should.equal('string');_typeof(batch3.source_request_id).should.equal('string');_typeof(batch4.source_request_id).should.equal('string');_typeof(batch5.source_request_id).should.equal('string');batch1.source_request_id.should.not.equal(batch2.source_request_id);batch1.source_request_id.should.not.equal(batch3.source_request_id);batch1.source_request_id.should.not.equal(batch4.source_request_id);batch1.source_request_id.should.not.equal(batch5.source_request_id);batch2.source_request_id.should.not.equal(batch3.source_request_id);batch2.source_request_id.should.not.equal(batch4.source_request_id);batch2.source_request_id.should.not.equal(batch5.source_request_id);batch3.source_request_id.should.not.equal(batch4.source_request_id);batch3.source_request_id.should.not.equal(batch5.source_request_id);batch4.source_request_id.should.not.equal(batch5.source_request_id);batch1UAC.data.session_uuid.should.equal(batch2AST.data.session_uuid);batch1UAC.data.session_uuid.should.equal(batch2SessionStart.data.session_uuid);batch1UAC.data.session_uuid.should.not.equal(batch5UAC.data.session_uuid);batch1UAC.data.session_uuid.should.not.equal(batch4SessionStart.data.session_uuid);batch1UAC.data.session_uuid.should.not.equal(batch4AST.data.session_uuid);batch1UAC.data.session_start_unixtime_ms.should.equal(batch2AST.data.session_start_unixtime_ms);batch1UAC.data.session_start_unixtime_ms.should.equal(batch2SessionStart.data.session_start_unixtime_ms);batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch5UAC.data.session_start_unixtime_ms);batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch4SessionStart.data.session_start_unixtime_ms);batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch4AST.data.session_start_unixtime_ms);batch2SessionStart.data.session_uuid.should.equal(batch2AST.data.session_uuid);batch2SessionStart.data.session_uuid.should.equal(batch3SessionEnd.data.session_uuid);batch2AST.data.session_uuid.should.equal(batch3SessionEnd.data.session_uuid);batch2SessionStart.data.session_start_unixtime_ms.should.equal(batch2AST.data.session_start_unixtime_ms);batch2SessionStart.data.session_start_unixtime_ms.should.equal(batch3SessionEnd.data.session_start_unixtime_ms);batch2AST.data.session_start_unixtime_ms.should.equal(batch3SessionEnd.data.session_start_unixtime_ms);batch4AST.data.session_uuid.should.equal(batch5UAC.data.session_uuid);batch4SessionStart.data.session_uuid.should.equal(batch5UAC.data.session_uuid);batch4SessionStart.data.session_uuid.should.equal(batch4AST.data.session_uuid);batch4AST.data.session_start_unixtime_ms.should.equal(batch5UAC.data.session_start_unixtime_ms);batch4SessionStart.data.session_start_unixtime_ms.should.equal(batch5UAC.data.session_start_unixtime_ms);batch4SessionStart.data.session_start_unixtime_ms.should.equal(batch4AST.data.session_start_unixtime_ms);done();// wait for more than 1000 milliseconds to force the final upload + },1200);});});describe('batching via XHR for older browsers without window.fetch',function(){var fetch=window.fetch;beforeEach(function(){delete window.fetch;window.mParticle.config.flags={eventBatchingIntervalMillis:1000};mockServer.respondWith(urls.events,[200,{},JSON.stringify({mpid:testMPID,Store:{}})]);clock=sinon$1.useFakeTimers();});afterEach(function(){window.mParticle._resetForTests(MPConfig);window.fetch=fetch;sinon$1.restore();clock.restore();});it('should use custom v3 endpoint',function(done){window.mParticle._resetForTests(MPConfig);mockServer.requests=[];window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1);// Upload interval hit, now will send requests + clock.tick(1000);// 1st request is /Identity call, 2nd request is /Event call + var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should force uploads when using public `upload`',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1);// Upload interval hit, now will send requests + clock.tick(1000);window.mParticle.upload();// 1st request is /Identity call, 2nd request is /Event call + var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should trigger an upload of batch when a commerce event is called',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');// The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1);var product1=window.mParticle.eCommerce.createProduct('iphone','iphoneSKU',999);window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart,product1);// 1st request is /Identity call, 2nd request is /Event call + var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');batch.events[3].event_type.should.equal('commerce_event');batch.events[3].data.product_action.action.should.equal('add_to_cart');done();});it('should trigger an upload of batch when a UIC occurs',function(done){window.mParticle._resetForTests(MPConfig);// include an identify request so that it creates a UIC + window.mParticle.config.identifyRequest={userIdentities:{customerid:'foo-customer-id'}};window.mParticle.init(apiKey,window.mParticle.config);// Requests sent should be identify call, then UIC event + // Session start, AST, and Test Event are queued, and don't appear + // in the mockServer.requests + mockServer.requests.length.should.equal(2);// 1st request is /Identity call, 2nd request is UIC call + var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('user_identity_change');// force upload of other events + window.mParticle.upload();var batch2=JSON.parse(mockServer.thirdRequest.requestBody);batch2.events[0].event_type.should.equal('session_start');batch2.events[1].event_type.should.equal('application_state_transition');done();});it('should trigger an upload of batch when a UAC occurs',function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.init(apiKey,window.mParticle.config);// Set a user attribute to trigger a UAC event + window.mParticle.Identity.getCurrentUser().setUserAttribute('age',25);// Requests sent should be identify call, then + // a request for session start, AST, and UAC + mockServer.requests.length.should.equal(2);// 1st request is /Identity call, 2nd request is UIC call + var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('user_attribute_change');done();});it('should return pending uploads if a 500 is returned',function(done){window.mParticle._resetForTests(MPConfig);// var clock = sinon.useFakeTimers(); + mockServer.respondWith(urls.events,[500,{},JSON.stringify({mpid:testMPID,Store:{}})]);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');var pendingEvents=window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing;pendingEvents.length.should.equal(3);pendingEvents[0].EventName.should.equal(1);pendingEvents[1].EventName.should.equal(10);pendingEvents[2].EventName.should.equal('Test Event');clock.tick(1000);var nowPendingEvents=window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing;nowPendingEvents.length.should.equal(0);var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Test Event');done();});it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call',function(done){window.mParticle._resetForTests(MPConfig);// var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch=function(batch){return batch;};window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');clock.tick(1000);var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.modified.should.equal(true);done();});it('should respect rules for the batch modification',function(done){window.mParticle._resetForTests(MPConfig);// var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch=function(batch){batch.events.map(function(event){if(event.event_type==="custom_event"){event.data.event_name='Modified!';}});return batch;};window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');clock.tick(1000);var batch=JSON.parse(mockServer.secondRequest.requestBody);batch.events.length.should.equal(3);batch.events[0].event_type.should.equal('session_start');batch.events[1].event_type.should.equal('application_state_transition');batch.events[2].event_type.should.equal('custom_event');batch.events[2].data.event_name.should.equal('Modified!');done();});it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call',function(done){window.mParticle._resetForTests(MPConfig);// var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch=function(batch){return undefined;};window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');clock.tick(1000);(mockServer.secondRequest===null).should.equal(true);done();});});});describe('Beacon Upload',function(){var mockServer;before(function(){client.restore();sinon$1.restore();});beforeEach(function(){client.restore();mockServer=sinon$1.createFakeServer();mockServer.respondImmediately=true;mockServer.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);window.mParticle.config.flags={eventBatchingIntervalMillis:1000};});afterEach(function(){sinon$1.restore();mockServer.reset();client.restore();});it('should trigger beacon on page visibilitychange events',function(done){window.mParticle._resetForTests(MPConfig);var bond=sinon$1.spy(navigator,'sendBeacon');window.mParticle.init(apiKey,window.mParticle.config);// visibility change is a document property, not window + document.dispatchEvent(new Event('visibilitychange'));bond.called.should.eql(true);bond.lastCall.args[0].should.eql(urls.events);done();});it('should trigger beacon on page beforeunload events',function(done){window.mParticle._resetForTests(MPConfig);var bond=sinon$1.spy(navigator,'sendBeacon');window.mParticle.init(apiKey,window.mParticle.config);// karma fails if onbeforeunload is not set to null + window.onbeforeunload=null;window.dispatchEvent(new Event('beforeunload'));bond.called.should.eql(true);bond.getCalls()[0].args[0].should.eql(urls.events);done();});it('should trigger beacon on pagehide events',function(done){window.mParticle._resetForTests(MPConfig);var bond=sinon$1.spy(navigator,'sendBeacon');window.mParticle.init(apiKey,window.mParticle.config);window.dispatchEvent(new Event('pagehide'));bond.called.should.eql(true);bond.getCalls()[0].args[0].should.eql(urls.events);_typeof(bond.getCalls()[0].args[1]).should.eql('object');done();});});var dtpn={blok:{ev:true,ea:true,ua:true,id:true},vers:{version:1,data_plan_id:"robs_plan",last_modified_on:"2020-10-27T19:12:42.397Z",version_document:{data_points:[{description:"",match:{type:"product_impression",criteria:{}},validator:{type:"json_schema",definition:{properties:{data:{additionalProperties:true,properties:{custom_flags:{additionalProperties:false,description:"",properties:{NotSoCustomFlag:{description:"",type:"boolean"}},required:[],type:"object"},custom_attributes:{additionalProperties:false,description:"",properties:{thing1:{description:"",type:"string"}},required:["thing1"],type:"object"},product_impressions:{description:"",items:{additionalProperties:false,description:"",properties:{product_impression_list:{description:"",type:"string"},products:{description:"",items:{additionalProperties:true,description:"",properties:{custom_attributes:{additionalProperties:false,description:"",properties:{allowedAttr2:{description:"",type:"string"},allowedAttr1:{description:"",type:"string"}},required:[],type:"object"}},required:[],type:"object"},type:"array"}},required:[],type:"object"},type:"array"}},required:["custom_attributes"],type:"object"}}}}},{description:"",match:{type:"screen_view",criteria:{screen_name:"another new screenview event"}},validator:{type:"json_schema",definition:{properties:{data:{additionalProperties:false,properties:{activity_type:{description:"",pattern:"[a-z]",type:"string"}},required:[],type:"object"}}}},active_transformation_ids:null},{match:{type:"custom_event",criteria:{event_name:"Search Event",custom_event_type:"search"}},validator:{type:"json_schema",definition:{}}},{match:{type:"custom_event",criteria:{event_name:"locationEvent",custom_event_type:"location"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{foo:{},"foo foo":{},"foo number":{}}}}}}}}},{match:{type:"product_action",criteria:{action:"add_to_cart"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{attributeBoolean:{},attributeEmail:{},attributeNumEnum:{},attributeNumMinMax:{},attributeStringAlpha:{}}}}}}}}},{match:{type:"promotion_action",criteria:{action:"view"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{"not required":{},required:{}}}}}}}}},{match:{type:"custom_event",criteria:{event_name:"TestEvent",custom_event_type:"navigation"}},validator:{type:"json_schema",definition:{}}},{match:{type:"screen_view",criteria:{screen_name:"A New ScreenViewEvent"}},validator:{type:"json_schema",definition:{}}},{match:{type:"screen_view",criteria:{screen_name:"my screeeen"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{test1key:{},test2key:{}}}}}}}}},{match:{type:"custom_event",criteria:{event_name:"something something something",custom_event_type:"navigation"}},validator:{type:"json_schema",definition:{}}},{match:{type:"user_attributes"},validator:{type:"json_schema",definition:{additionalProperties:false,properties:{"a third attribute":{},"my attribute":{},"my other attribute":{}}}}},{match:{type:"custom_event",criteria:{event_name:"SocialEvent",custom_event_type:"social"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{}}}}}}}},{match:{type:"product_action",criteria:{action:"purchase"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{eventAttribute1:{},eventAttribute2:{}}},product_action:{properties:{products:{items:{properties:{custom_attributes:{additionalProperties:false,properties:{plannedAttr1:{},plannedAttr2:{}}}}}}}}}}}}}},{match:{type:"promotion_action",criteria:{action:"click"}},validator:{type:"json_schema",definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{eventAttribute1:{},eventAttribute2:{}}}}}}}}},{description:"User Identities",match:{type:"user_identities",criteria:{}},validator:{type:"json_schema",definition:{additionalProperties:true,properties:{customerid:{description:"",type:"string"},amp_id:{description:"",type:"string"},email:{description:"",type:"string"}},required:["email"],type:"object"}}}]}}};var dataPlan={dtpn:dtpn};var dataPlan$1=/*#__PURE__*/Object.freeze({__proto__:null,dtpn:dtpn,'default':dataPlan});/* + TODO: Including this as a workaround because attempting to import it from + @mparticle/data-planning-models directly creates a build error. + */var DataPlanMatchType={ScreenView:"screen_view",CustomEvent:"custom_event",Commerce:"commerce",UserAttributes:"user_attributes",UserIdentities:"user_identities",ProductAction:"product_action",PromotionAction:"promotion_action",ProductImpression:"product_impression"};/* + inspiration from https://github.com/mParticle/data-planning-node/blob/master/src/data_planning/data_plan_event_validator.ts + but modified to only include commerce events, custom events, screen views, and removes validation + + The purpose of the KitBlocker class is to parse a data plan and determine what events, event/user/product attributes, and user identities should be blocked from downstream forwarders. + + KitBlocker is instantiated with a data plan on mParticle initialization. KitBlocker.kitBlockingEnabled is false if no data plan is passed. + It parses the data plan by creating a `dataPlanMatchLookups` object in the following manner: + 1. For all events and user attributes/identities, it generates a `matchKey` in the shape of `typeOfEvent:eventType:nameOfEvent` + a. The matchKeys' value will return `true` if additionalProperties for the custom attributes/identities is `true`, otherwise it will return an object of planned attribute/identities + 2. For commerce events, after step 1 and 1a, a second `matchKey` is included that appends `Products`. This is used to determine productAttributes blocked + + When an event is logged in mParticle, it is sent to our server and then calls `KitBlocker.createBlockedEvent` before passing the event to each forwarder. + If the event is blocked, it will not send to the forwarder. If the event is not blocked, event/user/product attributes and user identities will be removed from the returned event if blocked. + */var KitBlocker=/** @class */function(){function KitBlocker(dataPlan,mpInstance){var _this=this;var _a,_b,_c,_d,_e,_f,_g,_h,_j,_k,_l,_m,_o,_p,_q;this.dataPlanMatchLookups={};this.blockEvents=false;this.blockEventAttributes=false;this.blockUserAttributes=false;this.blockUserIdentities=false;this.kitBlockingEnabled=false;// if data plan is not requested, the data plan is {document: null} + if(dataPlan&&!dataPlan.document){this.kitBlockingEnabled=false;return;}this.kitBlockingEnabled=true;this.mpInstance=mpInstance;this.blockEvents=(_c=(_b=(_a=dataPlan===null||dataPlan===void 0?void 0:dataPlan.document)===null||_a===void 0?void 0:_a.dtpn)===null||_b===void 0?void 0:_b.blok)===null||_c===void 0?void 0:_c.ev;this.blockEventAttributes=(_f=(_e=(_d=dataPlan===null||dataPlan===void 0?void 0:dataPlan.document)===null||_d===void 0?void 0:_d.dtpn)===null||_e===void 0?void 0:_e.blok)===null||_f===void 0?void 0:_f.ea;this.blockUserAttributes=(_j=(_h=(_g=dataPlan===null||dataPlan===void 0?void 0:dataPlan.document)===null||_g===void 0?void 0:_g.dtpn)===null||_h===void 0?void 0:_h.blok)===null||_j===void 0?void 0:_j.ua;this.blockUserIdentities=(_m=(_l=(_k=dataPlan===null||dataPlan===void 0?void 0:dataPlan.document)===null||_k===void 0?void 0:_k.dtpn)===null||_l===void 0?void 0:_l.blok)===null||_m===void 0?void 0:_m.id;var versionDocument=(_q=(_p=(_o=dataPlan===null||dataPlan===void 0?void 0:dataPlan.document)===null||_o===void 0?void 0:_o.dtpn)===null||_p===void 0?void 0:_p.vers)===null||_q===void 0?void 0:_q.version_document;var dataPoints=versionDocument===null||versionDocument===void 0?void 0:versionDocument.data_points;if(versionDocument){try{if((dataPoints===null||dataPoints===void 0?void 0:dataPoints.length)>0){dataPoints.forEach(function(point){return _this.addToMatchLookups(point);});}}catch(e){this.mpInstance.Logger.error('There was an issue with the data plan: '+e);}}}KitBlocker.prototype.addToMatchLookups=function(point){var _a,_b,_c;if(!point.match||!point.validator){this.mpInstance.Logger.warning("Data Plan Point is not valid' + ".concat(point));return;}// match keys for non product custom attribute related data points + var matchKey=this.generateMatchKey(point.match);var properties=this.getPlannedProperties(point.match.type,point.validator);this.dataPlanMatchLookups[matchKey]=properties;// match keys for product custom attribute related data points + if(((_a=point===null||point===void 0?void 0:point.match)===null||_a===void 0?void 0:_a.type)===DataPlanMatchType.ProductImpression||((_b=point===null||point===void 0?void 0:point.match)===null||_b===void 0?void 0:_b.type)===DataPlanMatchType.ProductAction||((_c=point===null||point===void 0?void 0:point.match)===null||_c===void 0?void 0:_c.type)===DataPlanMatchType.PromotionAction){matchKey=this.generateProductAttributeMatchKey(point.match);properties=this.getProductProperties(point.match.type,point.validator);this.dataPlanMatchLookups[matchKey]=properties;}};KitBlocker.prototype.generateMatchKey=function(match){var criteria=match.criteria||'';switch(match.type){case DataPlanMatchType.CustomEvent:var customEventCriteria=criteria;return [DataPlanMatchType.CustomEvent,customEventCriteria.custom_event_type,customEventCriteria.event_name].join(':');case DataPlanMatchType.ScreenView:var screenViewCriteria=criteria;return [DataPlanMatchType.ScreenView,'',screenViewCriteria.screen_name].join(':');case DataPlanMatchType.ProductAction:var productActionMatch=criteria;return [match.type,productActionMatch.action].join(':');case DataPlanMatchType.PromotionAction:var promoActionMatch=criteria;return [match.type,promoActionMatch.action].join(':');case DataPlanMatchType.ProductImpression:var productImpressionActionMatch=criteria;return [match.type,productImpressionActionMatch.action].join(':');case DataPlanMatchType.UserIdentities:case DataPlanMatchType.UserAttributes:return [match.type].join(':');default:return null;}};KitBlocker.prototype.generateProductAttributeMatchKey=function(match){var criteria=match.criteria||'';switch(match.type){case DataPlanMatchType.ProductAction:var productActionMatch=criteria;return [match.type,productActionMatch.action,'ProductAttributes'].join(':');case DataPlanMatchType.PromotionAction:var promoActionMatch=criteria;return [match.type,promoActionMatch.action,'ProductAttributes'].join(':');case DataPlanMatchType.ProductImpression:return [match.type,'ProductAttributes'].join(':');default:return null;}};KitBlocker.prototype.getPlannedProperties=function(type,validator){var _a,_b,_c,_d,_e,_f,_g,_h;var customAttributes;var userAdditionalProperties;switch(type){case DataPlanMatchType.CustomEvent:case DataPlanMatchType.ScreenView:case DataPlanMatchType.ProductAction:case DataPlanMatchType.PromotionAction:case DataPlanMatchType.ProductImpression:customAttributes=(_d=(_c=(_b=(_a=validator===null||validator===void 0?void 0:validator.definition)===null||_a===void 0?void 0:_a.properties)===null||_b===void 0?void 0:_b.data)===null||_c===void 0?void 0:_c.properties)===null||_d===void 0?void 0:_d.custom_attributes;if(customAttributes){if(customAttributes.additionalProperties===true||customAttributes.additionalProperties===undefined){return true;}else {var properties={};for(var _i=0,_j=Object.keys(customAttributes.properties);_i<_j.length;_i++){var property=_j[_i];properties[property]=true;}return properties;}}else {if(((_g=(_f=(_e=validator===null||validator===void 0?void 0:validator.definition)===null||_e===void 0?void 0:_e.properties)===null||_f===void 0?void 0:_f.data)===null||_g===void 0?void 0:_g.additionalProperties)===false){return {};}else {return true;}}case DataPlanMatchType.UserAttributes:case DataPlanMatchType.UserIdentities:userAdditionalProperties=(_h=validator===null||validator===void 0?void 0:validator.definition)===null||_h===void 0?void 0:_h.additionalProperties;if(userAdditionalProperties===true||userAdditionalProperties===undefined){return true;}else {var properties={};var userProperties=validator.definition.properties;for(var _k=0,_l=Object.keys(userProperties);_k<_l.length;_k++){var property=_l[_k];properties[property]=true;}return properties;}default:return null;}};KitBlocker.prototype.getProductProperties=function(type,validator){var _a,_b,_c,_d,_e,_f,_g,_h,_j,_k,_l,_m,_o,_p,_q,_r,_s,_t,_u;var productCustomAttributes;switch(type){case DataPlanMatchType.ProductImpression:productCustomAttributes=(_k=(_j=(_h=(_g=(_f=(_e=(_d=(_c=(_b=(_a=validator===null||validator===void 0?void 0:validator.definition)===null||_a===void 0?void 0:_a.properties)===null||_b===void 0?void 0:_b.data)===null||_c===void 0?void 0:_c.properties)===null||_d===void 0?void 0:_d.product_impressions)===null||_e===void 0?void 0:_e.items)===null||_f===void 0?void 0:_f.properties)===null||_g===void 0?void 0:_g.products)===null||_h===void 0?void 0:_h.items)===null||_j===void 0?void 0:_j.properties)===null||_k===void 0?void 0:_k.custom_attributes;//product item attributes + if((productCustomAttributes===null||productCustomAttributes===void 0?void 0:productCustomAttributes.additionalProperties)===false){var properties={};for(var _i=0,_v=Object.keys(productCustomAttributes===null||productCustomAttributes===void 0?void 0:productCustomAttributes.properties);_i<_v.length;_i++){var property=_v[_i];properties[property]=true;}return properties;}return true;case DataPlanMatchType.ProductAction:case DataPlanMatchType.PromotionAction:productCustomAttributes=(_u=(_t=(_s=(_r=(_q=(_p=(_o=(_m=(_l=validator===null||validator===void 0?void 0:validator.definition)===null||_l===void 0?void 0:_l.properties)===null||_m===void 0?void 0:_m.data)===null||_o===void 0?void 0:_o.properties)===null||_p===void 0?void 0:_p.product_action)===null||_q===void 0?void 0:_q.properties)===null||_r===void 0?void 0:_r.products)===null||_s===void 0?void 0:_s.items)===null||_t===void 0?void 0:_t.properties)===null||_u===void 0?void 0:_u.custom_attributes;//product item attributes + if(productCustomAttributes){if(productCustomAttributes.additionalProperties===false){var properties={};for(var _w=0,_x=Object.keys(productCustomAttributes===null||productCustomAttributes===void 0?void 0:productCustomAttributes.properties);_w<_x.length;_w++){var property=_x[_w];properties[property]=true;}return properties;}}return true;default:return null;}};KitBlocker.prototype.getMatchKey=function(eventToMatch){switch(eventToMatch.event_type){case dist.EventTypeEnum.screenView:var screenViewEvent=eventToMatch;if(screenViewEvent.data){return ['screen_view','',screenViewEvent.data.screen_name].join(':');}return null;case dist.EventTypeEnum.commerceEvent:var commerceEvent=eventToMatch;var matchKey=[];if(commerceEvent&&commerceEvent.data){var _a=commerceEvent.data,product_action=_a.product_action,product_impressions=_a.product_impressions,promotion_action=_a.promotion_action;if(product_action){matchKey.push(DataPlanMatchType.ProductAction);matchKey.push(product_action.action);}else if(promotion_action){matchKey.push(DataPlanMatchType.PromotionAction);matchKey.push(promotion_action.action);}else if(product_impressions){matchKey.push(DataPlanMatchType.ProductImpression);}}return matchKey.join(':');case dist.EventTypeEnum.customEvent:var customEvent=eventToMatch;if(customEvent.data){return ['custom_event',customEvent.data.custom_event_type,customEvent.data.event_name].join(':');}return null;default:return null;}};KitBlocker.prototype.getProductAttributeMatchKey=function(eventToMatch){switch(eventToMatch.event_type){case dist.EventTypeEnum.commerceEvent:var commerceEvent=eventToMatch;var matchKey=[];var _a=commerceEvent.data,product_action=_a.product_action,product_impressions=_a.product_impressions,promotion_action=_a.promotion_action;if(product_action){matchKey.push(DataPlanMatchType.ProductAction);matchKey.push(product_action.action);matchKey.push('ProductAttributes');}else if(promotion_action){matchKey.push(DataPlanMatchType.PromotionAction);matchKey.push(promotion_action.action);matchKey.push('ProductAttributes');}else if(product_impressions){matchKey.push(DataPlanMatchType.ProductImpression);matchKey.push('ProductAttributes');}return matchKey.join(':');default:return null;}};KitBlocker.prototype.createBlockedEvent=function(event){/* + return a transformed event based on event/event attributes, + then product attributes if applicable, then user attributes, + then the user identities + */try{if(event){event=this.transformEventAndEventAttributes(event);}if(event&&event.EventDataType===Types.MessageType.Commerce){event=this.transformProductAttributes(event);}if(event){event=this.transformUserAttributes(event);event=this.transformUserIdentities(event);}return event;}catch(e){return event;}};KitBlocker.prototype.transformEventAndEventAttributes=function(event){var clonedEvent=_assign({},event);var baseEvent=convertEvent(clonedEvent);var matchKey=this.getMatchKey(baseEvent);var matchedEvent=this.dataPlanMatchLookups[matchKey];if(this.blockEvents){/* + If the event is not planned, it doesn't exist in dataPlanMatchLookups + and should be blocked (return null to not send anything to forwarders) + */if(!matchedEvent){return null;}}if(this.blockEventAttributes){/* + matchedEvent is set to `true` if additionalProperties is `true` + otherwise, delete attributes that exist on event.EventAttributes + that aren't on + */if(matchedEvent===true){return clonedEvent;}if(matchedEvent){for(var _i=0,_a=Object.keys(clonedEvent.EventAttributes);_i<_a.length;_i++){var key=_a[_i];if(!matchedEvent[key]){delete clonedEvent.EventAttributes[key];}}return clonedEvent;}else {return clonedEvent;}}return clonedEvent;};KitBlocker.prototype.transformProductAttributes=function(event){var _a;var clonedEvent=_assign({},event);var baseEvent=convertEvent(clonedEvent);var matchKey=this.getProductAttributeMatchKey(baseEvent);var matchedEvent=this.dataPlanMatchLookups[matchKey];function removeAttribute(matchedEvent,productList){productList.forEach(function(product){for(var _i=0,_a=Object.keys(product.Attributes);_i<_a.length;_i++){var productKey=_a[_i];if(!matchedEvent[productKey]){delete product.Attributes[productKey];}}});}if(this.blockEvents){/* + If the event is not planned, it doesn't exist in dataPlanMatchLookups + and should be blocked (return null to not send anything to forwarders) + */if(!matchedEvent){return null;}}if(this.blockEventAttributes){/* + matchedEvent is set to `true` if additionalProperties is `true` + otherwise, delete attributes that exist on event.EventAttributes + that aren't on + */if(matchedEvent===true){return clonedEvent;}if(matchedEvent){switch(event.EventCategory){case Types.CommerceEventType.ProductImpression:clonedEvent.ProductImpressions.forEach(function(impression){removeAttribute(matchedEvent,impression===null||impression===void 0?void 0:impression.ProductList);});break;case Types.CommerceEventType.ProductPurchase:removeAttribute(matchedEvent,(_a=clonedEvent.ProductAction)===null||_a===void 0?void 0:_a.ProductList);break;default:this.mpInstance.Logger.warning('Product Not Supported ');}return clonedEvent;}else {return clonedEvent;}}return clonedEvent;};KitBlocker.prototype.transformUserAttributes=function(event){var clonedEvent=_assign({},event);if(this.blockUserAttributes){/* + If the user attribute is not found in the matchedAttributes + then remove it from event.UserAttributes as it is blocked + */var matchedAttributes=this.dataPlanMatchLookups['user_attributes'];if(this.mpInstance._Helpers.isObject(matchedAttributes)){for(var _i=0,_a=Object.keys(clonedEvent.UserAttributes);_i<_a.length;_i++){var ua=_a[_i];if(!matchedAttributes[ua]){delete clonedEvent.UserAttributes[ua];}}}}return clonedEvent;};KitBlocker.prototype.isAttributeKeyBlocked=function(key){/* used when an attribute is added to the user */if(!this.blockUserAttributes){return false;}if(this.blockUserAttributes){var matchedAttributes=this.dataPlanMatchLookups['user_attributes'];if(matchedAttributes===true){return false;}if(!matchedAttributes[key]){return true;}}return false;};KitBlocker.prototype.isIdentityBlocked=function(key){/* used when an attribute is added to the user */if(!this.blockUserIdentities){return false;}if(this.blockUserIdentities){var matchedIdentities=this.dataPlanMatchLookups['user_identities'];if(matchedIdentities===true){return false;}if(!matchedIdentities[key]){return true;}}else {return false;}return false;};KitBlocker.prototype.transformUserIdentities=function(event){var _this=this;var _a;/* + If the user identity is not found in matchedIdentities + then remove it from event.UserIdentities as it is blocked. + event.UserIdentities is of type [{Identity: 'id1', Type: 7}, ...] + and so to compare properly in matchedIdentities, each Type needs + to be converted to an identityName + */var clonedEvent=_assign({},event);if(this.blockUserIdentities){var matchedIdentities_1=this.dataPlanMatchLookups['user_identities'];if(this.mpInstance._Helpers.isObject(matchedIdentities_1)){if((_a=clonedEvent===null||clonedEvent===void 0?void 0:clonedEvent.UserIdentities)===null||_a===void 0?void 0:_a.length){clonedEvent.UserIdentities.forEach(function(uiByType,i){var identityName=Types.IdentityType.getIdentityName(_this.mpInstance._Helpers.parseNumber(uiByType.Type));if(!matchedIdentities_1[identityName]){clonedEvent.UserIdentities.splice(i,1);}});}}}return clonedEvent;};return KitBlocker;}();// import sinon from 'sinon'; + var forwarderDefaultConfiguration$4=TestsCore.forwarderDefaultConfiguration,MockForwarder$6=TestsCore.MockForwarder;describe('kit blocking',function(){var mockServer;var kitBlockerDataPlan={document:dataPlan$1};beforeEach(function(){mockServer=sinon$2.createFakeServer();mockServer.respondImmediately=true;window.mParticle.config.dataPlan={document:dataPlan$1};window.mParticle.config.kitConfigs=[];});afterEach(function(){mockServer.reset();sinon$2.restore();});describe('kitBlocker',function(){it('kitBlocker should parse data plan into dataPlanMatchLookups properly',function(done){var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var dataPlanMatchLookups=kitBlocker.dataPlanMatchLookups;dataPlanMatchLookups.should.have.property('custom_event:search:Search Event',true);dataPlanMatchLookups.should.have.property('screen_view::another new screenview event',{});dataPlanMatchLookups.should.have.property('custom_event:location:locationEvent',{foo:true,'foo foo':true,'foo number':true});dataPlanMatchLookups.should.have.property('product_action:add_to_cart',{attributeNumMinMax:true,attributeEmail:true,attributeNumEnum:true,attributeStringAlpha:true,attributeBoolean:true});dataPlanMatchLookups.should.have.property('product_action:add_to_cart:ProductAttributes',true);dataPlanMatchLookups.should.have.property('promotion_action:view',{'not required':true,'required':true});dataPlanMatchLookups.should.have.property('promotion_action:view:ProductAttributes',true);dataPlanMatchLookups.should.have.property('custom_event:navigation:TestEvent',true);dataPlanMatchLookups.should.have.property('product_impression:ProductAttributes',{allowedAttr1:true,allowedAttr2:true});dataPlanMatchLookups.should.have.property('screen_view::A New ScreenViewEvent',true);dataPlanMatchLookups.should.have.property('screen_view::my screeeen',{test2key:true,test1key:true});dataPlanMatchLookups.should.have.property('custom_event:navigation:something something something',true);dataPlanMatchLookups.should.have.property('user_attributes',{'my attribute':true,'my other attribute':true,'a third attribute':true});dataPlanMatchLookups.should.have.property('user_identities',true);dataPlanMatchLookups.should.have.property('custom_event:social:SocialEvent',{});dataPlanMatchLookups.should.have.property('product_action:purchase',{eventAttribute1:true,eventAttribute2:true});dataPlanMatchLookups.should.have.property('product_action:purchase:ProductAttributes',{plannedAttr1:true,plannedAttr2:true});dataPlanMatchLookups.should.have.property('promotion_action:click',{eventAttribute1:true,eventAttribute2:true});dataPlanMatchLookups.should.have.property('promotion_action:click:ProductAttributes',true);done();});});describe('kitblocking - events and event attributes',function(){var kitBlocker;var event;beforeEach(function(){kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());event={DeviceId:'test',IsFirstRun:true,EventName:null,EventCategory:null,MPID:testMPID,EventAttributes:null,SDKVersion:'1.0.0',SourceMessageId:'testSMID',SessionId:'sessionId',SessionStartDate:1,Timestamp:1,EventDataType:null,Debug:true,CurrencyCode:'usd'};});it('should transform an unplanned event to null if blok.ev = true',function(done){event.EventName='unplanned event';event.EventCategory=Types.EventType.Search;event.EventAttributes={keyword2:'test'};event.EventDataType=Types.MessageType.PageEvent;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);(transformedEvent===null).should.equal(true);done();});it('should transform EventAttributes if an event attribute is not planned and blok.ea = true',function(done){event.EventName='locationEvent';event.EventCategory=Types.EventType.Location;event.EventAttributes={unplannedAttr:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);transformedEvent.EventAttributes.should.not.have.property('unplannedAttr');transformedEvent.EventAttributes.should.have.property('foo','hi');done();});it('should transform EventAttributes if there are no custom attributes and additionalProperties === false',function(done){event.EventName='another new screenview event';event.EventCategory=Types.EventType.Location;event.EventAttributes={unplannedAttr:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageView;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);transformedEvent.EventAttributes.should.not.have.property('unplannedAttr');transformedEvent.EventAttributes.should.not.have.property('foo');done();});it('should include unplanned event attributes if additionalProperties = true and blok.ea = true',function(done){event.EventName='something something something';event.EventCategory=Types.EventType.Navigation;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);transformedEvent.EventAttributes.should.have.property('foo','hi');transformedEvent.EventAttributes.should.have.property('keyword2','test');done();});it('should block any unplanned event attributes if custom attributes is empty, additionalProperties = false, and block.ea = true.',function(done){event.EventName='SocialEvent';event.EventCategory=Types.EventType.Social;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);Object.keys(transformedEvent.EventAttributes).length.should.equal(0);done();});it('should not block any unplanned event attributes if custom attributes is empty, additionalProperties = true, and block.ea = true.',function(done){// modify this test so that the above + var socialDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){var _a,_b;return ((_b=(_a=dataPoint===null||dataPoint===void 0?void 0:dataPoint.match)===null||_a===void 0?void 0:_a.criteria)===null||_b===void 0?void 0:_b.event_name)==='SocialEvent';});socialDataPoint.validator.definition.properties.data.properties.custom_attributes.additionalProperties=true;kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());event.EventName='SocialEvent';event.EventCategory=Types.EventType.Social;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;var transformedEvent=kitBlocker.transformEventAndEventAttributes(event);Object.keys(transformedEvent.EventAttributes).length.should.equal(2);transformedEvent.EventAttributes.should.have.property('foo','hi');transformedEvent.EventAttributes.should.have.property('keyword2','test');socialDataPoint.validator.definition.properties.data.properties.custom_attributes.additionalProperties=false;done();});});describe('kit blocking - user attributes/identities',function(){var event;beforeEach(function(){new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());event={DeviceId:'test',IsFirstRun:true,EventName:null,EventCategory:null,MPID:testMPID,EventAttributes:null,SDKVersion:'1.0.0',SourceMessageId:'testSMID',SessionId:'sessionId',SessionStartDate:1,Timestamp:1,EventDataType:null,Debug:true,CurrencyCode:'usd'};});it('should block any unplanned user attributes when blok.ua = true and additionalPropertes = false',function(done){event.EventName='something something something';event.EventCategory=Types.EventType.Navigation;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;event.UserAttributes={'my attribute':'test1','my other attribute':'test2','a third attribute':'test3','unplanned attribute':'test4'};var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformUserAttributes(event);transformedEvent.UserAttributes.should.have.property('my attribute','test1');transformedEvent.UserAttributes.should.have.property('my other attribute','test2');transformedEvent.UserAttributes.should.have.property('a third attribute','test3');transformedEvent.UserAttributes.should.not.have.property('unplanned attribute');done();});it('should not block any unplanned user attributes if blok.ua = false',function(done){//TODO - what if this additional properties is false? shoudl we validate that? + window.mParticle.config.dataPlan.document.dtpn.blok.ua=false;event.EventName='something something something',event.EventCategory=Types.EventType.Navigation,event.EventAttributes={keyword2:'test',foo:'hi'},event.EventDataType=Types.MessageType.PageEvent,event.UserAttributes={'my attribute':'test1','my other attribute':'test2','a third attribute':'test3','unplanned attribute':'test4'};var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformUserAttributes(event);transformedEvent.UserAttributes.should.have.property('my attribute','test1');transformedEvent.UserAttributes.should.have.property('my other attribute','test2');transformedEvent.UserAttributes.should.have.property('a third attribute','test3');transformedEvent.UserAttributes.should.have.property('unplanned attribute','test4');//reset + window.mParticle.config.dataPlan.document.dtpn.blok.ua=true;done();});it('isAttributeKeyBlocked should return false for attributes that are blocked and true for properties that are not',function(done){// this key is blocked because the default data plan has user_attributes>additional_properties = false + var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var isBlocked=kitBlocker.isAttributeKeyBlocked('blocked');isBlocked.should.equal(true);var userAttributeDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_attributes';});userAttributeDataPoint.validator.definition.additionalProperties=true;var kitBlocker2=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());isBlocked=kitBlocker2.isAttributeKeyBlocked('my attribute');isBlocked.should.equal(false);// reset to original data plan + userAttributeDataPoint.validator.definition.additionalProperties=false;done();});it('should not block any unplanned user identities when blok.id = true and additionalProperties = true',function(done){event.EventName='something something something';event.EventCategory=Types.EventType.Navigation;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;event.UserIdentities=[{Type:7,Identity:'email@gmail.com'},{Type:1,Identity:'customerid1'},{Type:4,Identity:'GoogleId'}];var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformUserIdentities(event);transformedEvent.UserIdentities.filter(function(UI){return UI.Type===1;})[0].should.have.property('Identity','customerid1');transformedEvent.UserIdentities.filter(function(UI){return UI.Type===7;})[0].should.have.property('Identity','email@gmail.com');transformedEvent.UserIdentities.filter(function(UI){return UI.Type===4;})[0].should.have.property('Identity','GoogleId');done();});it('should block user identities when additional properties = false and blok.id = true',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;event.EventName='something something something';event.EventCategory=Types.EventType.Navigation;event.EventAttributes={keyword2:'test',foo:'hi'};event.EventDataType=Types.MessageType.PageEvent;event.UserIdentities=[{Type:7,Identity:'email@gmail.com'},{Type:1,Identity:'customerid1'},{Type:4,Identity:'GoogleId'}];var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformUserIdentities(event);transformedEvent.UserIdentities.find(function(UI){return UI.Type===1;}).should.have.property('Identity','customerid1');transformedEvent.UserIdentities.find(function(UI){return UI.Type===7;}).should.have.property('Identity','email@gmail.com');(transformedEvent.UserIdentities.find(function(UI){return UI.Type===4;})===undefined).should.equal(true);// reset + userIdentityDataPoint.validator.definition.additionalProperties=true;done();});it('isIdentityBlocked should return false for identities that are blocked and true for properties that are not',function(done){// this identity is not blocked because the default data plan has user_identities>additional_properties = false + var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var isBlocked=kitBlocker.isIdentityBlocked('random identity');isBlocked.should.equal(false);// for next test, change additionalProperties to false + var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;var kitBlocker2=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());isBlocked=kitBlocker2.isIdentityBlocked('facebook');isBlocked.should.equal(true);// reset to original data plan + userIdentityDataPoint.validator.definition.additionalProperties=true;done();});});describe('kit blocking - product attributes',function(){var event;var products;beforeEach(function(){new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());products=[{Attributes:{'plannedAttr1':'val1','plannedAttr2':'val2','unplannedAttr1':'val3','allowedAttr1':'val4','allowedAttr2':'val5'},Name:'iPhone',Category:'category',CouponCode:'coupon',Position:1,Price:999,Quantity:1,Sku:'iphoneSKU',TotalAmount:999,Variant:'128'},{Attributes:{'plannedAttr1':'val1','plannedAttr2':'val2','unplannedAttr1':'val3','allowedAttr1':'val4','allowedAttr2':'val5'},Name:'S10',Category:'category',CouponCode:'coupon',Position:2,Price:500,Quantity:1,Sku:'galaxySKU',TotalAmount:500,Variant:'256'}];event={DeviceId:'test',IsFirstRun:true,EventName:null,EventCategory:null,MPID:testMPID,EventAttributes:null,SDKVersion:'1.0.0',SourceMessageId:'testSMID',SessionId:'sessionId',SessionStartDate:1,Timestamp:1,EventDataType:null,Debug:true,CurrencyCode:'usd'};});it('should transform productAttributes if an product attribute is not planned, additionalProperties = false, and blok.ea = true',function(done){event.EventName='eCommerce - Purchase';event.EventCategory=Types.CommerceEventType.ProductPurchase;event.EventDataType=Types.MessageType.Commerce;event.ProductAction={ProductActionType:SDKProductActionType.Purchase,ProductList:products};var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformProductAttributes(event);transformedEvent.ProductAction.ProductList[0].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr1');transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr2');transformedEvent.ProductAction.ProductList[1].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr1');transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr2');done();});it('should not transform productAttributes if a product attribute is not planned, additionalProperties = false, and blok.ea = true',function(done){event.EventName='eCommerce - AddToCart';event.EventCategory=Types.CommerceEventType.AddToCart;event.EventDataType=Types.MessageType.Commerce;event.ProductAction={ProductActionType:SDKProductActionType.AddToCart,ProductList:products};var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformProductAttributes(event);transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('unplannedAttr1');transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr1');transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr2');transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('unplannedAttr1');transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr1');transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr2');done();});it('should transform productAttributes in product impressions if an product attribute is not planned, additionalProperties = false, and blok.ea = true',function(done){event.EventName='eCommerce - Impression';event.ProductImpressions=[{ProductImpressionList:'imp1',ProductList:products},{ProductImpressionList:'imp2',ProductList:products}];event.EventCategory=Types.CommerceEventType.ProductImpression;event.EventDataType=Types.MessageType.Commerce;var kitBlocker=new KitBlocker(kitBlockerDataPlan,window.mParticle.getInstance());var transformedEvent=kitBlocker.transformProductAttributes(event);transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.have.property('allowedAttr1','val4');transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.have.property('allowedAttr2','val5');transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.not.have.property('unplannedAttr2');transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.have.property('allowedAttr1','val4');transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.have.property('allowedAttr2','val5');transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.not.have.property('unplannedAttr2');transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.have.property('allowedAttr1','val4');transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.have.property('allowedAttr2','val5');transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.not.have.property('unplannedAttr2');transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.have.property('allowedAttr1','val4');transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.have.property('allowedAttr2','val5');transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.not.have.property('unplannedAttr1');transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.not.have.property('unplannedAttr2');done();});});describe('kit blocking - integration tests',function(){beforeEach(function(){mockServer.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);});it('integration test - should log an error if the data plan has an error on it',function(done){var errorMessage='This is an error';window.mParticle.config.dataPlan={document:{error_message:errorMessage}};var errorMessages=[];window.mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);window.mParticle.config.logLevel='verbose';window.mParticle.config.logger={error:function error(err){errorMessages.push(err);}};window.mParticle.init(apiKey,window.mParticle.config);errorMessages[0].should.equal(errorMessage);window.mParticle.config.requestConfig=false;done();});it('integration test - should block a custom event from reaching the forwarder if event is unplanned and block.ev=true',function(done){window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Blocked event');var event=window.MockForwarder1.instance.receivedEvent;(event===null).should.equal(true);done();});it('integration test - should allow unplanned custom events through to forwarder if blok.ev=false',function(done){window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.config.dataPlan.document.dtpn.blok.ev=false;window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Unplanned Event');var event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('EventName','Unplanned Event');// reset + window.mParticle.config.dataPlan.document.dtpn.blok.ev=true;done();});it('integration test - should block an unplanned attribute from being set on the forwarder if additionalProperties = false and blok.ua = true',function(done){window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserAttribute('unplannedAttr',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',false);done();});it('integration test - should allow an unplanned attribute to be set on forwarder if additionalProperties = true and blok.ua = true',function(done){var userAttributeDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_attributes';});userAttributeDataPoint.validator.definition.additionalProperties=true;window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserAttribute('unplanned but unblocked',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);userAttributeDataPoint.validator.definition.additionalProperties=false;done();});it('integration test - should allow an unplanned user attribute to be set on the forwarder if blok=false',function(done){window.mParticle.config.dataPlan.document.dtpn.blok.ua=false;window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserAttribute('unplanned but not blocked',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);window.mParticle.config.dataPlan.document.dtpn.blok.ua=true;done();});it('integration test - should block an unplanned attribute set via setUserTag from being set on the forwarder if additionalProperties = false and blok.ua = true',function(done){window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserTag('unplannedAttr',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',false);done();});it('integration test - should allow an unplanned attribute set via setUserTag to be set on forwarder if additionalProperties = true and blok.ua = true',function(done){var userAttributeDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_attributes';});userAttributeDataPoint.validator.definition.additionalProperties=true;window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserTag('unplanned but unblocked',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);userAttributeDataPoint.validator.definition.additionalProperties=false;done();});it('integration test - should allow an unplanned user attribute set via setUserTag to be set on the forwarder if blok=false',function(done){window.mParticle.config.dataPlan.document.dtpn.blok.ua=false;window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.getCurrentUser().setUserTag('unplanned but not blocked',true);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);window.mParticle.config.dataPlan.document.dtpn.blok.ua=true;done();});describe('integration tests - user identity related',function(){var userIdentityRequest;beforeEach(function(){['login','logout','modify'].forEach(function(identityMethod){mockServer.respondWith(urls[identityMethod],[200,{},JSON.stringify({mpid:'testMPID',is_logged_in:true})]);});var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);userIdentityRequest={userIdentities:{google:'test',customerid:'id1',other:'id2',yahoo:'yahoo1',email:'email@gmail.com'}};});it('integration test - should not block any unplanned user identities to the forwarder when blok.id = true and additionalProperties = true',function(done){window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.login({userIdentities:{customerid:'customerid1',email:'email@gmail.com','google':'GoogleId'}});window.mParticle.logEvent('something something something',Types.EventType.Navigation);var event=window.MockForwarder1.instance.receivedEvent;event.UserIdentities.find(function(UI){return UI.Type===1;}).should.have.property('Identity','customerid1');event.UserIdentities.find(function(UI){return UI.Type===7;}).should.have.property('Identity','email@gmail.com');event.UserIdentities.find(function(UI){return UI.Type===4;}).should.have.property('Identity','GoogleId');done();});it('integration test - should block user identities to the forwarder when additional properties = false and blok.id = true',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.login({userIdentities:{customerid:'customerid1',email:'email@gmail.com','google':'GoogleId'}});window.mParticle.logEvent('something something something',Types.EventType.Navigation);var event=window.MockForwarder1.instance.receivedEvent;event.UserIdentities.find(function(UI){return UI.Type===1;}).should.have.property('Identity','customerid1');event.UserIdentities.find(function(UI){return UI.Type===7;}).should.have.property('Identity','email@gmail.com');(event.UserIdentities.find(function(UI){return UI.Type===4;})===undefined).should.not.have.property('Identity','GoogleId');// reset + userIdentityDataPoint.validator.definition.additionalProperties=true;done();});it('integration test - should not block identities from being passed to onUserIdentified/onLogoutComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)',function(done){var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.logout(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('other','id2');onUserIdentifiedUserIdentities.should.have.property('yahoo','yahoo1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');var onLogoutCompleteUserIdentities=window.MockForwarder1.instance.onLogoutCompleteUser.getUserIdentities().userIdentities;onLogoutCompleteUserIdentities.should.not.have.property('google');onLogoutCompleteUserIdentities.should.have.property('customerid','id1');onLogoutCompleteUserIdentities.should.have.property('other','id2');onLogoutCompleteUserIdentities.should.have.property('yahoo','yahoo1');onLogoutCompleteUserIdentities.should.have.property('email','email@gmail.com');done();});it('integration test - should block identities from being passed to onUserIdentified/onLogoutComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.logout(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.not.have.property('other','id2');onUserIdentifiedUserIdentities.should.not.have.property('yahoo');var onLogoutCompleteUserIdentities=window.MockForwarder1.instance.onLogoutCompleteUser.getUserIdentities().userIdentities;onLogoutCompleteUserIdentities.should.have.property('customerid','id1');onLogoutCompleteUserIdentities.should.have.property('email','email@gmail.com');onLogoutCompleteUserIdentities.should.not.have.property('google');onLogoutCompleteUserIdentities.should.not.have.property('other','id2');onLogoutCompleteUserIdentities.should.not.have.property('yahoo');userIdentityDataPoint.validator.definition.additionalProperties=true;done();});it('integration test - should not block identities from being passed to onUserIdentified/onModifyComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)',function(done){var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.modify(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('other','id2');onUserIdentifiedUserIdentities.should.have.property('yahoo','yahoo1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');var onModifyCompleteUserIdentities=window.MockForwarder1.instance.onModifyCompleteUser.getUserIdentities().userIdentities;onModifyCompleteUserIdentities.should.not.have.property('google');onModifyCompleteUserIdentities.should.have.property('customerid','id1');onModifyCompleteUserIdentities.should.have.property('other','id2');onModifyCompleteUserIdentities.should.have.property('yahoo','yahoo1');onModifyCompleteUserIdentities.should.have.property('email','email@gmail.com');done();});it('integration test - should block identities from being passed to onUserIdentified/onModifyComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.modify(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.not.have.property('other','id2');onUserIdentifiedUserIdentities.should.not.have.property('yahoo');var onModifyCompleteUserIdentities=window.MockForwarder1.instance.onModifyCompleteUser.getUserIdentities().userIdentities;onModifyCompleteUserIdentities.should.have.property('customerid','id1');onModifyCompleteUserIdentities.should.have.property('email','email@gmail.com');onModifyCompleteUserIdentities.should.not.have.property('google');onModifyCompleteUserIdentities.should.not.have.property('other','id2');onModifyCompleteUserIdentities.should.not.have.property('yahoo');userIdentityDataPoint.validator.definition.additionalProperties=true;done();});it('integration test - should not block identities from being passed to onUserIdentified/onIdentifyComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)',function(done){var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.identifyRequest=userIdentityRequest;window.mParticle.init(apiKey,window.mParticle.config);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('other','id2');onUserIdentifiedUserIdentities.should.have.property('yahoo','yahoo1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');var onIdentifyCompleteUserIdentities=window.MockForwarder1.instance.onIdentifyCompleteUser.getUserIdentities().userIdentities;onIdentifyCompleteUserIdentities.should.not.have.property('google');onIdentifyCompleteUserIdentities.should.have.property('customerid','id1');onIdentifyCompleteUserIdentities.should.have.property('other','id2');onIdentifyCompleteUserIdentities.should.have.property('yahoo','yahoo1');onIdentifyCompleteUserIdentities.should.have.property('email','email@gmail.com');done();});it('integration test - should block identities from being passed to onUserIdentified/onIdentifyComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.identify(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.not.have.property('other','id2');onUserIdentifiedUserIdentities.should.not.have.property('yahoo');var onIdentifyCompleteUserIdentities=window.MockForwarder1.instance.onIdentifyCompleteUser.getUserIdentities().userIdentities;onIdentifyCompleteUserIdentities.should.have.property('customerid','id1');onIdentifyCompleteUserIdentities.should.have.property('email','email@gmail.com');onIdentifyCompleteUserIdentities.should.not.have.property('google');onIdentifyCompleteUserIdentities.should.not.have.property('other','id2');onIdentifyCompleteUserIdentities.should.not.have.property('yahoo');userIdentityDataPoint.validator.definition.additionalProperties=true;done();});it('integration test - should not block identities from being passed to onUserIdentified/onLoginComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)',function(done){var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.login(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('other','id2');onUserIdentifiedUserIdentities.should.have.property('yahoo','yahoo1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');var onLoginCompleteUserIdentities=window.MockForwarder1.instance.onLoginCompleteUser.getUserIdentities().userIdentities;onLoginCompleteUserIdentities.should.not.have.property('google');onLoginCompleteUserIdentities.should.have.property('customerid','id1');onLoginCompleteUserIdentities.should.have.property('other','id2');onLoginCompleteUserIdentities.should.have.property('yahoo','yahoo1');onLoginCompleteUserIdentities.should.have.property('email','email@gmail.com');done();});it('integration test - should block identities from being passed to onUserIdentified/onLoginComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)',function(done){var userIdentityDataPoint=dtpn.vers.version_document.data_points.find(function(dataPoint){return dataPoint.match.type==='user_identities';});userIdentityDataPoint.validator.definition.additionalProperties=false;var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);var config1=forwarderDefaultConfiguration$4('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.Identity.login(userIdentityRequest);var onUserIdentifiedUserIdentities=window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities;onUserIdentifiedUserIdentities.should.have.property('customerid','id1');onUserIdentifiedUserIdentities.should.have.property('email','email@gmail.com');onUserIdentifiedUserIdentities.should.not.have.property('google');onUserIdentifiedUserIdentities.should.not.have.property('other','id2');onUserIdentifiedUserIdentities.should.not.have.property('yahoo');var onLoginCompleteUserIdentities=window.MockForwarder1.instance.onLoginCompleteUser.getUserIdentities().userIdentities;onLoginCompleteUserIdentities.should.have.property('customerid','id1');onLoginCompleteUserIdentities.should.have.property('email','email@gmail.com');onLoginCompleteUserIdentities.should.not.have.property('google');onLoginCompleteUserIdentities.should.not.have.property('other','id2');onLoginCompleteUserIdentities.should.not.have.property('yahoo');userIdentityDataPoint.validator.definition.additionalProperties=true;done();});});describe('integration tests - product attribute related',function(){var prodattr1,prodattr2,product1,product2,transactionAttributes,customAttributes,customFlags;beforeEach(function(){var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);prodattr1={'plannedAttr1':'val1','plannedAttr2':'val2','unplannedAttr1':'val3'};prodattr2={'plannedAttr1':'val1','plannedAttr2':'val2','unplannedAttr1':'val3'};product1=window.mParticle.eCommerce.createProduct('iphone','iphoneSKU',999,1,'variant','category','brand',1,'coupon',prodattr1);product2=window.mParticle.eCommerce.createProduct('galaxy','galaxySKU',799,1,'variant','category','brand',1,'coupon',prodattr2);transactionAttributes={Id:'foo-transaction-id',Revenue:430.00,Tax:30};customAttributes={sale:true};customFlags={'Google.Category':'travel'};});it('integration test - should block any unplanned product attributes from reaching the forwarder if additionalProperties = false and block.ea=true',function(done){window.mParticle.eCommerce.logProductAction(window.mParticle.ProductActionType['Purchase'],[product1,product2],customAttributes,customFlags,transactionAttributes);var event=window.MockForwarder1.instance.receivedEvent;var products=event.ProductAction.ProductList;products[0].Attributes.should.have.property('plannedAttr1','val1');products[0].Attributes.should.have.property('plannedAttr2','val2');products[0].Attributes.should.not.have.property('unplannedAttr1');products[1].Attributes.should.have.property('plannedAttr1','val1');products[1].Attributes.should.have.property('plannedAttr2','val2');products[1].Attributes.should.not.have.property('unplannedAttr1');done();});it('integration test - should not block unplanned product attributes from reaching the forwarder if additionalProperties = true and block.ea=true',function(done){window.mParticle.eCommerce.logProductAction(window.mParticle.ProductActionType['AddToCart'],[product1,product2],customAttributes,customFlags,transactionAttributes);var event=window.MockForwarder1.instance.receivedEvent;var products=event.ProductAction.ProductList;products[0].Attributes.should.have.property('plannedAttr1','val1');products[0].Attributes.should.have.property('plannedAttr2','val2');products[0].Attributes.should.have.property('unplannedAttr1');products[1].Attributes.should.have.property('plannedAttr1','val1');products[1].Attributes.should.have.property('plannedAttr2','val2');products[1].Attributes.should.have.property('unplannedAttr1');done();});});describe('integration tests - client passed in data plan',function(){var clientProvidedDataPlan={version_document:{data_points:[{match:{// @ts-ignore (fix this after DataPlanMatchType importing works) + type:'custom_event',criteria:{event_name:'locationEvent123',custom_event_type:'location'}},validator:{// @ts-ignore (fix this after DataPlanMatchType importing works) + type:'json_schema',definition:{properties:{data:{properties:{custom_attributes:{additionalProperties:false,properties:{foo:{},'foo foo':{},'foo number':{}}}}}}}}}]}};it('integration test - should log an error if the client passes a data plan without the proper keys',function(done){// @ts-ignore - purposely leaving out blockUserIdentities as a key below + window.mParticle.config.dataPlanOptions={dataPlanVersion:clientProvidedDataPlan,blockUserAttributes:true,blockEventAttributes:true,blockEvents:true};var errorMessages=[];window.mParticle._resetForTests(MPConfig);window.mParticle.config.logLevel='verbose';window.mParticle.config.logger={error:function error(err){errorMessages.push(err);}};window.mParticle.init(apiKey,window.mParticle.config);errorMessages[0].should.equal('Ensure your config.dataPlanOptions object has the following keys: a "dataPlanVersion" object, and "blockUserAttributes", "blockEventAttributes", "blockEvents", "blockUserIdentities" booleans');done();});it('integration test - should prioritize data plan from config.dataPlanOptions over server provided data plan',function(done){window.mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.config.dataPlanOptions={dataPlanVersion:clientProvidedDataPlan,blockUserAttributes:true,blockEventAttributes:true,blockEvents:true,blockUserIdentities:true};var logs=[];window.mParticle.config.logLevel='verbose';window.mParticle.config.logger={verbose:function verbose(msg){logs.push(msg);}};window.mParticle.init(apiKey,window.mParticle.config);logs.includes('Customer provided data plan found').should.equal(true);logs.includes('Data plan found from mParticle.js').should.equal(false);logs.includes('Data plan found from /config').should.equal(false);// this event is part of the server provided data plan (dataPlan.json) which is being ignored, so the event doesn't go through; + window.mParticle.logEvent('something something something',Types.EventType.Navigation);var event=window.MockForwarder1.instance.receivedEvent;(event===null).should.equal(true);// this event is part of the clientGeneratedDataPlan + window.mParticle.logEvent('locationEvent123',Types.EventType.Location,{unplannedAttr:'test',foo:'hi'});event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('EventName','locationEvent123');event.EventAttributes.should.have.property('foo','hi');event.EventAttributes.should.not.have.property('unplannedAttr');done();});it('integration test - should block or unblock planned events',function(done){window.mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);delete window.mParticle.config.dataPlan;window.mParticle.config.dataPlanOptions={dataPlanVersion:clientProvidedDataPlan,blockUserAttributes:true,blockEventAttributes:true,blockEvents:true,blockUserIdentities:true};window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Blocked event');var event=window.MockForwarder1.instance.receivedEvent;(event===null).should.equal(true);window.mParticle.logEvent('locationEvent123',Types.EventType.Location,{unplannedAttr:'test',foo:'hi'});event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('EventName','locationEvent123');event.EventAttributes.should.have.property('foo','hi');event.EventAttributes.should.not.have.property('unplannedAttr');done();});});describe('integration tests - self hosting set up',function(){it('should create a proper kitblocker on a self hosted set up',function(done){mockServer.respondWith("".concat(urls.config,"&plan_id=robs_plan&plan_version=1"),[200,{},JSON.stringify({dataPlanResult:dataPlan$1})]);window.mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);//requestConfig = true indicates self hosted + window.mParticle.config.requestConfig=true;window.mParticle.config.logLevel='verbose';window.mParticle.config.dataPlan={planId:'robs_plan',planVersion:1};window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Blocked event');var event=window.MockForwarder1.instance.receivedEvent;(event===null).should.equal(true);window.mParticle.config.requestConfig=false;done();});it('should log an error if the data plan has an error on it',function(done){var errorMessage='This is an error';mockServer.respondWith("".concat(urls.config,"&plan_id=robs_plan&plan_version=1"),[200,{},JSON.stringify({dataPlanResult:{error_message:errorMessage}})]);var errorMessages=[];window.mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$6();window.mParticle.addForwarder(mockForwarder);//requestConfig = true indicates self hosted + window.mParticle.config.requestConfig=true;window.mParticle.config.logLevel='verbose';window.mParticle.config.dataPlan={planId:'robs_plan',planVersion:1};window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder'));window.mParticle.config.logLevel='verbose';window.mParticle.config.logger={error:function error(err){errorMessages.push(err);}};window.mParticle.init(apiKey,window.mParticle.config);errorMessages[0].should.equal(errorMessage);window.mParticle.config.requestConfig=false;done();});});});});var findCookie$1=TestsCore.findCookie,getLocalStorage$4=TestsCore.getLocalStorage,getLocalStorageProducts$2=TestsCore.getLocalStorageProducts,setCookie$1=TestsCore.setCookie,setLocalStorage$3=TestsCore.setLocalStorage,findBatch$5=TestsCore.findBatch;var mockServer$c;describe('migrations and persistence-related',function(){beforeEach(function(){client.post(urls.events,200);mockServer$c=sinon$1.createFakeServer();mockServer$c.respondImmediately=true;mockServer$c.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle$5.init(apiKey,mParticle$5.config);});afterEach(function(){mockServer$c.restore();client.restore();});it('should move new schema from cookies to localStorage with useCookieStorage = false',function(done){mParticle$5._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'sid',les:new Date().getTime()},testMPID:{ui:{1:'123'}},cu:testMPID});setCookie$1(workspaceCookieName,cookies);var beforeInitCookieData=findCookie$1(workspaceCookieName);mParticle$5.config.useCookieStorage=false;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');var localStorageData=mParticle$5.getInstance()._Persistence.getLocalStorage();var afterInitCookieData=findCookie$1();beforeInitCookieData[testMPID].ui.should.have.property('1','123');localStorageData[testMPID].ua.should.have.property('gender','male');localStorageData[testMPID].ui.should.have.property('1','123');expect(afterInitCookieData).to.not.be.ok;done();});it('should migrate localStorage to cookies with useCookieStorage = true',function(done){mParticle$5._resetForTests(MPConfig);setLocalStorage$3();mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');var localStorageData=localStorage.getItem('mprtcl-api');var cookieData=findCookie$1();expect(localStorageData).to.not.be.ok;cookieData[testMPID].ua.should.have.property('gender','male');cookieData[testMPID].ui.should.have.property('1','testuser@mparticle.com');done();});it('localStorage - should key cookies on mpid on first run',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=false;mParticle$5.init(apiKey,mParticle$5.config);var cookies1=mParticle$5.getInstance()._Persistence.getLocalStorage();var props1=['ie','sa','ua','ui','ss','dt','les','av','cgid','das','csd','mpid','cp','sid','c'];props1.forEach(function(prop){cookies1.should.not.have.property(prop);});cookies1.should.have.property('cu',testMPID,'gs');cookies1.should.have.property(testMPID);var props2=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'otherMPID',is_logged_in:false})]);mParticle$5.Identity.login();var cookies2=mParticle$5.getInstance()._Persistence.getLocalStorage();cookies2.should.have.property('cu','otherMPID','gs');props2.forEach(function(prop){cookies1[testMPID].should.not.have.property(prop);cookies2[testMPID].should.not.have.property(prop);cookies2['otherMPID'].should.not.have.property(prop);});done();});it('cookies - should key cookies on mpid when there are no cookies yet',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var cookies1=findCookie$1();var props1=['ie','sa','ua','ui','ss','dt','les','av','cgid','das','csd','mpid','cp','sid','c'];cookies1.should.have.property('cu',testMPID,'gs');props1.forEach(function(prop){cookies1.should.not.have.property(prop);});var props2=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'otherMPID',is_logged_in:false})]);mParticle$5.Identity.login();var cookies2=findCookie$1();cookies2.should.have.property('cu','otherMPID',testMPID);props2.forEach(function(prop){cookies1[testMPID].should.not.have.property(prop);cookies2[testMPID].should.not.have.property(prop);cookies2['otherMPID'].should.not.have.property(prop);});done();});it('puts data into cookies when init-ing with useCookieStorage = true',function(done){mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var cookieData=findCookie$1();var localStorageData=mParticle$5.getInstance()._Persistence.getLocalStorage();cookieData.should.have.properties(['gs','cu',testMPID]);var props=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];props.forEach(function(prop){cookieData[testMPID].should.not.have.property(prop);});expect(localStorageData).to.not.be.ok;done();});it('puts data into localStorage when running initializeStorage with useCookieStorage = false',function(done){mParticle$5.init(apiKey,mParticle$5.config);var cookieData=mParticle$5.getInstance()._Persistence.getCookie();var localStorageData=mParticle$5.getInstance()._Persistence.getLocalStorage();expect(localStorageData).to.include.keys(['gs','cu',testMPID]);var props=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];props.forEach(function(prop){expect(localStorageData[testMPID]).to.not.have.property(prop);});expect(cookieData).to.not.be.ok;done();});it('puts data into cookies when updating persistence with useCookieStorage = true',function(done){var cookieData;var localStorageData;mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);cookieData=findCookie$1();expect(cookieData).to.include.keys('gs','cu',testMPID);localStorageData=mParticle$5.getInstance()._Persistence.getLocalStorage();var props=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];props.forEach(function(prop){cookieData[testMPID].should.not.have.property(prop);});expect(localStorageData).to.not.be.ok;done();});it('puts data into localStorage when updating persistence with useCookieStorage = false',function(done){var cookieData;var localStorageData;// Flush out anything in expire before updating in order to silo testing persistence.update() + // mParticle.config.useCookieStorage = false; + mParticle$5.init(apiKey,mParticle$5.config);localStorageData=getLocalStorage$4();cookieData=findCookie$1();expect(localStorageData).to.have.include.keys('gs','cu',testMPID);var props=['ie','sa','ss','dt','les','av','cgid','das','sid','c','mpid','cp'];props.forEach(function(prop){localStorageData[testMPID].should.not.have.property(prop);});expect(cookieData).to.not.be.ok;done();});it('should revert to cookie storage if localStorage is not available and useCookieStorage is set to false',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.getInstance()._Persistence.determineLocalStorageAvailability=function(){return false;};mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');var cookieData=findCookie$1();cookieData[testMPID].ua.should.have.property('gender','male');mParticle$5.getInstance()._Persistence.determineLocalStorageAvailability=function(){return true;};done();});it('should set certain attributes onto global localStorage, while setting user specific to the MPID',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=false;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.setIntegrationAttribute(128,{MCID:'abcedfg'});var data=getLocalStorage$4();data.cu.should.equal(testMPID);data.gs.should.have.properties(['sid','ie','dt','cgid','das','les','ia']);data.testMPID.ua.should.have.property('gender','male');done();});it('should save integration attributes properly on a page refresh',function(done){mParticle$5.setIntegrationAttribute(128,{MCID:'abcedfg'});mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.logEvent('Test Event');var testEvent=findBatch$5(client._calls,'Test Event');testEvent.integration_attributes.should.have.property('128');testEvent.integration_attributes['128'].should.have.property('MCID','abcedfg');done();});it('should set certain attributes onto global cookies, while setting user specific to the MPID',function(done){mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');var data=findCookie$1();data.cu.should.equal(testMPID);data.gs.should.have.properties(['sid','ie','dt','cgid','das','les']);data.testMPID.ua.should.have.property('gender','male');done();});it('should add new MPID to cookies when returned MPID does not match anything in cookies, and have empty UI and UA',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid1',is_logged_in:false})]);var user1={userIdentities:{customerid:'customerid1'}};mParticle$5.Identity.login(user1);var user1Result=mParticle$5.getInstance().Identity.getCurrentUser().getUserIdentities();user1Result.userIdentities.customerid.should.equal('customerid1');mockServer$c.respondWith(urls.logout,[200,{},JSON.stringify({mpid:'mpid2',is_logged_in:false})]);mParticle$5.Identity.logout();var user2Result=mParticle$5.getInstance().Identity.getCurrentUser();Object.keys(user2Result.getUserIdentities().userIdentities).length.should.equal(0);var localStorageData=mParticle$5.getInstance()._Persistence.getLocalStorage();localStorageData.cu.should.equal('mpid2');localStorageData.testMPID.should.not.have.property('ui');localStorageData.mpid1.ui[1].should.equal('customerid1');localStorageData.mpid2.should.not.have.property('ui');done();});it('should have the same currentUserMPID as the last browser session when a reload occurs and no identityRequest is provided',function(done){mParticle$5._resetForTests(MPConfig);var user1={userIdentities:{customerid:'1'}};var user2={userIdentities:{customerid:'2'}};var user3={userIdentities:{customerid:'3'}};mParticle$5.init(apiKey,mParticle$5.config);var data=mParticle$5.getInstance()._Persistence.getLocalStorage();data.cu.should.equal(testMPID);mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid1',is_logged_in:false})]);mParticle$5.Identity.login(user1);var user1Data=mParticle$5.getInstance()._Persistence.getLocalStorage();user1Data.cu.should.equal('mpid1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid2',is_logged_in:false})]);mParticle$5.Identity.login(user2);var user2Data=mParticle$5.getInstance()._Persistence.getLocalStorage();user2Data.cu.should.equal('mpid2');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid3',is_logged_in:false})]);mParticle$5.Identity.login(user3);var user3data=mParticle$5.getInstance()._Persistence.getLocalStorage();user3data.cu.should.equal('mpid3');mParticle$5.init(apiKey,mParticle$5.config);var data3=mParticle$5.getInstance()._Persistence.getLocalStorage();data3.cu.should.equal('mpid3');done();});it('should transfer user attributes and revert to user identities properly',function(done){mParticle$5._resetForTests(MPConfig);var user1={userIdentities:{customerid:'customerid1'}};var user2={userIdentities:{customerid:'customerid2'}};mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test1','test1');var data=getLocalStorage$4();data.cu.should.equal(testMPID);data.testMPID.ua.should.have.property('test1','test1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid1',is_logged_in:false})]);mockServer$c.respondWith('https://identity.mparticle.com/v1/mpid1/modify',[200,{},JSON.stringify({mpid:'mpid1',is_logged_in:false})]);mParticle$5.Identity.login(user1);mParticle$5.Identity.modify({userIdentities:{email:'email@test.com'}});mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test2','test2');var user1Data=mParticle$5.getInstance()._Persistence.getLocalStorage();user1Data.cu.should.equal('mpid1');user1Data.mpid1.ua.should.have.property('test2','test2');user1Data.mpid1.ui.should.have.property('7','email@test.com');user1Data.mpid1.ui.should.have.property('1','customerid1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid2',is_logged_in:false})]);mParticle$5.Identity.login(user2);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test3','test3');var user2Data=mParticle$5.getInstance()._Persistence.getLocalStorage();user2Data.cu.should.equal('mpid2');user2Data.mpid2.ui.should.have.property('1','customerid2');user2Data.mpid2.ua.should.have.property('test3','test3');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'mpid1',is_logged_in:false})]);mParticle$5.Identity.login(user1);var user1RelogInData=mParticle$5.getInstance()._Persistence.getLocalStorage();user1RelogInData.cu.should.equal('mpid1');user1RelogInData.mpid1.ui.should.have.property('1','customerid1');user1RelogInData.mpid1.ui.should.have.property('7','email@test.com');Object.keys(user1RelogInData.mpid1.ui).length.should.equal(2);user1RelogInData.mpid1.ua.should.have.property('test2','test2');done();});it('should remove MPID as keys if the cookie size is beyond the setting',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.maxCookieSize=700;var cookies={gs:{csm:['mpid1','mpid2','mpid3'],sid:'abcd',ie:true,dt:apiKey,cgid:'cgid1',das:'das1'},cu:'mpid3',l:false,mpid1:{ua:{gender:'female',age:29,height:'65',color:'blue',id:'abcdefghijklmnopqrstuvwxyz'},ui:{1:'customerid123',2:'facebookid123'}},mpid2:{ua:{gender:'male',age:20,height:'68',color:'red'},ui:{1:'customerid234',2:'facebookid234',id:'abcdefghijklmnopqrstuvwxyz'}},mpid3:{ua:{gender:'male',age:20,height:'68',color:'red'},ui:{1:'customerid234',2:'facebookid234',id:'abcdefghijklmnopqrstuvwxyz'}}};var expires=new Date(new Date().getTime()+365*24*60*60*1000).toUTCString();var cookiesWithExpiration=mParticle$5.getInstance()._Persistence.reduceAndEncodePersistence(cookies,expires,'testDomain',mParticle$5.config.maxCookieSize);var cookiesWithoutExpiration=cookiesWithExpiration.slice(0,cookiesWithExpiration.indexOf(';expires'));var cookiesResult=JSON.parse(mParticle$5.getInstance()// TODO: Refactor or rename this to highlight that it is + // a string function + ._Persistence.decodePersistence(cookiesWithoutExpiration));expect(cookiesResult['mpid1']).to.not.be.ok;expect(cookiesResult['mpid2']).be.ok;expect(cookiesResult['mpid3']).be.ok;cookiesResult.gs.csm.length.should.equal(3);cookiesResult.gs.csm[0].should.equal('mpid1');cookiesResult.gs.csm[1].should.equal('mpid2');cookiesResult.gs.csm[2].should.equal('mpid3');done();});it('integration test - will change the order of the CSM when a previous MPID logs in again',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=true;mParticle$5.config.maxCookieSize=1000;mParticle$5.init(apiKey,mParticle$5.config);mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();var cookieData=findCookie$1();cookieData.gs.csm[0].should.be.equal('testMPID');cookieData.gs.csm[1].should.be.equal('MPID1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();cookieData=findCookie$1();cookieData.gs.csm[0].should.be.equal('testMPID');cookieData.gs.csm[1].should.be.equal('MPID1');cookieData.gs.csm[2].should.be.equal('MPID2');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'testMPID',is_logged_in:false})]);mParticle$5.Identity.login();cookieData=findCookie$1();cookieData.gs.csm[0].should.be.equal('MPID1');cookieData.gs.csm[1].should.be.equal('MPID2');cookieData.gs.csm[2].should.be.equal('testMPID');done();});it('integration test - should remove a previous MPID as a key from cookies if new user attribute added and exceeds the size of the max cookie size',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=true;mParticle$5.config.maxCookieSize=650;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','68');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','blue');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','60');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id2');var cookieData=findCookie$1();cookieData.gs.csm[0].should.equal('testMPID');cookieData.gs.csm[1].should.equal('MPID1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',45);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','80');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');//this last one puts us over the maxcookiesize threshold and removes 'testMPID' from cookie + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id3');cookieData=findCookie$1();expect(cookieData['testMPID']).to.not.be.ok;cookieData['MPID1'].ua.should.have.property('id','id2');cookieData['MPID1'].ua.should.have.property('gender','male');cookieData['MPID1'].ua.should.have.property('age',30);cookieData['MPID1'].ua.should.have.property('height','60');cookieData['MPID1'].ua.should.have.property('color','green');cookieData['MPID2'].ua.should.have.property('id','id3');cookieData['MPID2'].ua.should.have.property('gender','female');cookieData['MPID2'].ua.should.have.property('age',45);cookieData['MPID2'].ua.should.have.property('height','80');cookieData['MPID2'].ua.should.have.property('color','green');done();});it('should remove a random MPID from storage if there is a new session and there are no other MPIDs in currentSessionMPIDs except for the currentUser mpid',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.maxCookieSize=400;var cookies={gs:{csm:['mpid3'],sid:'abcd',ie:true,dt:apiKey,cgid:'cgid1',das:'das1'},cu:'mpid3',l:false,mpid1:{ua:{gender:'female',age:29,height:'65',color:'blue',id:'abcdefghijklmnopqrstuvwxyz'},ui:{1:'customerid123',2:'facebookid123'}},mpid2:{ua:{gender:'male',age:20,height:'68',color:'red'},ui:{1:'customerid234',2:'facebookid234',id:'abcdefghijklmnopqrstuvwxyz'}},mpid3:{ua:{gender:'male',age:20,height:'68',color:'red'},ui:{1:'customerid234',2:'facebookid234',id:'abcdefghijklmnopqrstuvwxyz'}}};var expires=new Date(new Date().getTime()+365*24*60*60*1000).toString();var cookiesWithExpiration=mParticle$5.getInstance()._Persistence.reduceAndEncodePersistence(cookies,expires,'testDomain',mParticle$5.config.maxCookieSize);var cookiesWithoutExpiration=cookiesWithExpiration.slice(0,cookiesWithExpiration.indexOf(';expires'));var cookiesResult=JSON.parse(mParticle$5.getInstance()._Persistence.decodePersistence(cookiesWithoutExpiration));expect(cookiesResult['mpid1']).to.not.be.ok;expect(cookiesResult['mpid2']).to.not.be.ok;expect(cookiesResult['mpid3']).be.ok;cookiesResult.gs.csm[0].should.equal('mpid3');cookiesResult.should.have.property('mpid3');// TODO: Refactor tests to include this in setup/teardown + mParticle$5.config.maxCookieSize=3000;done();});it('integration test - should remove a random MPID from storage if there is a new session and there are no MPIDs in currentSessionMPIDs',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=true;mParticle$5.config.maxCookieSize=600;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','68');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','blue');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','60');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id2');var cookieData=findCookie$1();cookieData.gs.csm[0].should.equal('testMPID');cookieData.gs.csm[1].should.equal('MPID1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.endSession();mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',45);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','80');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id3');cookieData=findCookie$1();expect(cookieData['testMPID']).to.not.be.ok;cookieData['MPID1'].ua.should.have.property('id','id2');cookieData['MPID1'].ua.should.have.property('gender','male');cookieData['MPID1'].ua.should.have.property('age',30);cookieData['MPID1'].ua.should.have.property('height','60');cookieData['MPID1'].ua.should.have.property('color','green');cookieData['MPID2'].ua.should.have.property('id','id3');cookieData['MPID2'].ua.should.have.property('gender','female');cookieData['MPID2'].ua.should.have.property('age',45);cookieData['MPID2'].ua.should.have.property('height','80');cookieData['MPID2'].ua.should.have.property('color','green');done();});it('integration test - migrates a large localStorage cookie to cookies and properly remove MPIDs',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=false;mParticle$5.config.maxCookieSize=700;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','68');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','blue');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','60');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id2');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',45);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','80');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id3');mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var cookieData=findCookie$1();expect(cookieData['testMPID']).to.not.be.ok;cookieData['MPID1'].ua.should.have.property('id','id2');cookieData['MPID2'].ua.should.have.property('id');done();});it('integration test - migrates all cookie MPIDs to localStorage',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','68');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','blue');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','60');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id2');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',45);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','80');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id3');mParticle$5.config.useCookieStorage=false;mParticle$5.init(apiKey,mParticle$5.config);var lsData=getLocalStorage$4(v4LSKey);lsData.should.have.properties(['gs','cu','testMPID','MPID1','MPID2']);lsData['testMPID'].ua.should.have.properties(['gender','age','height','color','id']);lsData['MPID1'].ua.should.have.properties(['gender','age','height','color','id']);lsData['MPID2'].ua.should.have.properties(['gender','age','height','color','id']);done();});it('integration test - migrates all LS MPIDs to cookies',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.useCookieStorage=false;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','68');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','blue');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id1');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','male');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',30);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','60');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id2');mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender','female');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age',45);mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height','80');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color','green');mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id','id3');mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var cookieData=findCookie$1();cookieData.should.have.properties(['gs','cu','testMPID','MPID1','MPID2']);cookieData['testMPID'].ua.should.have.properties(['gender','age','height','color','id']);cookieData['MPID1'].ua.should.have.properties(['gender','age','height','color','id']);cookieData['MPID2'].ua.should.have.properties(['gender','age','height','color','id']);done();});it('get/set consent state for single user',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);var consentState=mParticle$5.getInstance().Identity.getCurrentUser().getConsentState();expect(consentState).to.equal(null);consentState=mParticle$5.Consent.createConsentState();consentState.addGDPRConsentState('foo purpose',mParticle$5.Consent.createGDPRConsent(true,10));mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState);var storedConsentState=mParticle$5.getInstance().Identity.getCurrentUser().getConsentState();storedConsentState.should.be.ok();storedConsentState.getGDPRConsentState().should.have.property('foo purpose');storedConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Consented',true);storedConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Timestamp',10);done();});it('get/set consent state for multiple users',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle$5.Identity.login();var user1StoredConsentState=mParticle$5.getInstance().Identity.getCurrentUser().getConsentState();expect(user1StoredConsentState).to.equal(null);var consentState=mParticle$5.Consent.createConsentState();consentState.addGDPRConsentState('foo purpose',mParticle$5.Consent.createGDPRConsent(true,10));mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState);mParticle$5._resetForTests(MPConfig,true);mParticle$5.init(apiKey,mParticle$5.config);mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:false})]);mParticle$5.Identity.login();var user2StoredConsentState=mParticle$5.getInstance().Identity.getCurrentUser().getConsentState();expect(user2StoredConsentState).to.equal(null);consentState.removeGDPRConsentState('foo purpose');consentState.addGDPRConsentState('foo purpose 2',mParticle$5.Consent.createGDPRConsent(false,11));mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState);user1StoredConsentState=mParticle$5.getInstance()._Persistence.getConsentState('MPID1');user2StoredConsentState=mParticle$5.getInstance()._Persistence.getConsentState('MPID2');user1StoredConsentState.getGDPRConsentState().should.have.property('foo purpose');user1StoredConsentState.getGDPRConsentState().should.not.have.property('foo purpose 2');user1StoredConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Consented',true);user1StoredConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Timestamp',10);user2StoredConsentState.getGDPRConsentState().should.have.property('foo purpose 2');user1StoredConsentState.getGDPRConsentState().should.not.have.property('foo purpose 1');user2StoredConsentState.getGDPRConsentState()['foo purpose 2'].should.have.property('Consented',false);user2StoredConsentState.getGDPRConsentState()['foo purpose 2'].should.have.property('Timestamp',11);done();});it('integration test - clears and creates new LS on reload if LS is corrupt',function(done){var les=new Date().getTime();mParticle$5._resetForTests(MPConfig);//an extra apostrophe is added to ua here to force a corrupt cookie. On init, cookies will clear and there will be a new cgid, sid, and das to exist + var LS="{'sid':'1992BDBB-AD74-49DB-9B20-5EC8037E72DE'|'ie':1|'ua':'eyJ0ZXN'0Ijoiwq7igJkifQ=='|'ui':'eyIzIjoiwq7igJkifQ=='|'ss':'eyJ1aWQiOnsiRXhwaXJlcyI6IjIwMjgtMDktMTRUMjI6MjI6MTAuMjU0MDcyOVoiLCJWYWx1ZSI6Imc9NjhjMmJhMzktYzg2OS00MTZhLWE4MmMtODc4OWNhZjVmMWU3JnU9NDE3NjQyNTYyMTQ0MTEwODk2OCZjcj00NTgxOTgyIn19'|'dt':'e207c24e36a7a8478ba0fcb3707a616b'|'les':"+les+"|'ssd':1537222930186|'cgid':'4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'|'das':'68c2ba39-c869-416a-a82c-8789caf5f1e7'|'mpid':'4176425621441108968'}";setLocalStorage$3(v4LSKey,LS,true);mParticle$5.init(apiKey,mParticle$5.config);var sessionId=mParticle$5.sessionManager.getSession();var das=mParticle$5.getDeviceId();var cgid=mParticle$5.getInstance()._Persistence.getLocalStorage().gs.cgid;sessionId.should.not.equal('1992BDBB-AD74-49DB-9B20-5EC8037E72DE');das.should.not.equal('68c2ba39-c869-416a-a82c-8789caf5f1e7');cgid.should.not.equal('4ebad5b4-8ed1-4275-8455-838a2e3aa5c0');done();});it('integration test - clears and creates new cookies on reload if cookies is corrupt',function(done){var les=new Date().getTime();mParticle$5._resetForTests(MPConfig);//an extra apostrophe is added to ua here to force a corrupt cookie. On init, cookies will clear and there will be a new cgid, sid, and das to exist + var cookies="{'sid':'1992BDBB-AD74-49DB-9B20-5EC8037E72DE'|'ie':1|'ua':'eyJ0ZXN'0Ijoiwq7igJkifQ=='|'ui':'eyIzIjoiwq7igJkifQ=='|'ss':'eyJ1aWQiOnsiRXhwaXJlcyI6IjIwMjgtMDktMTRUMjI6MjI6MTAuMjU0MDcyOVoiLCJWYWx1ZSI6Imc9NjhjMmJhMzktYzg2OS00MTZhLWE4MmMtODc4OWNhZjVmMWU3JnU9NDE3NjQyNTYyMTQ0MTEwODk2OCZjcj00NTgxOTgyIn19'|'dt':'e207c24e36a7a8478ba0fcb3707a616b'|'les':"+les+"|'ssd':1537222930186|'cgid':'4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'|'das':'68c2ba39-c869-416a-a82c-8789caf5f1e7'|'mpid':'4176425621441108968'}";setCookie$1(workspaceCookieName,cookies,true);mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var sessionId=mParticle$5.sessionManager.getSession();var das=mParticle$5.getDeviceId();var cgid=mParticle$5.getInstance()._Persistence.getCookie().gs.cgid;sessionId.should.not.equal('1992BDBB-AD74-49DB-9B20-5EC8037E72DE');das.should.not.equal('68c2ba39-c869-416a-a82c-8789caf5f1e7');cgid.should.not.equal('4ebad5b4-8ed1-4275-8455-838a2e3aa5c0');done();});it('integration test - clears LS products on reload if LS products are corrupt',function(done){mParticle$5._resetForTests(MPConfig);// randomly added gibberish to a Base64 encoded cart product array to force a corrupt product array + var products='eyItOTE4MjY2NTAzNTA1ODg1NjAwMyI6eyasdjfiojasdifojfsdfJjcCI6W3siTmFtZSI6ImFuZHJvaWQiLCJTa3UiOiI1MTg3MDkiLCJQcmljZSI6MjM0LCJRdWFudGl0eSI6MSwiQnJhbmQiOm51bGwsIlZhcmlhbnQiOm51bGwsIkNhdGVnb3J5IjpudWxsLCJQb3NpdGlvbiI6bnVsbCwiQ291cG9uQ29kZSI6bnVsbCwiVG90YWxBbW91bnQiOjIzNCwiQXR0cmlidXRlcyI6eyJwcm9kYXR0cjEiOiJoaSJ9fSx7Ik5hbWUiOiJ3aW5kb3dzIiwiU2t1IjoiODMzODYwIiwiUHJpY2UiOjM0NSwiUXVhbnRpdHkiOjEsIlRvdGFsQW1vdW50IjozNDUsIkF0dHJpYnV0ZXMiOm51bGx9XX19';localStorage.setItem(localStorageProductsV4,products);mParticle$5.init(apiKey,mParticle$5.config);var productsAfterInit=getLocalStorageProducts$2().testMPID;expect(productsAfterInit.length).to.not.be.ok;done();});it('should save products to persistence correctly when adding and removing products',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);var iphone=mParticle$5.eCommerce.createProduct('iphone','iphonesku',599,1,'iphone variant','iphonecategory','iphonebrand',null,'iphonecoupon',{iphoneattr1:'value1',iphoneattr2:'value2'});mParticle$5.eCommerce.Cart.add(iphone,true);var ls=localStorage.getItem(LocalStorageProductsV4WithWorkSpaceName);var parsedProducts=JSON.parse(atob(ls));// parsedProducts should just have key of testMPID with value of cp with a single product + Object.keys(parsedProducts).length.should.equal(1);parsedProducts['testMPID'].should.have.property('cp');parsedProducts['testMPID'].cp.length.should.equal(1);mParticle$5.eCommerce.Cart.remove(iphone,true);ls=localStorage.getItem(LocalStorageProductsV4WithWorkSpaceName);var parsedProductsAfter=JSON.parse(atob(ls));// parsedProducts should just have key of testMPID with value of cp with no products + Object.keys(parsedProductsAfter).length.should.equal(1);parsedProductsAfter['testMPID'].should.have.property('cp');parsedProductsAfter['testMPID'].cp.length.should.equal(0);done();});it('should only set setFirstSeenTime() once',function(done){mParticle$5._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},previous:{},previous_set:{fst:100},cu:'current'});setCookie$1(workspaceCookieName,cookies);// TODO: Refactor this into setup/teardown + mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance()._Persistence.setFirstSeenTime('current',10000);var currentFirstSeenTime=mParticle$5.getInstance()._Persistence.getFirstSeenTime('current');mParticle$5.getInstance()._Persistence.setFirstSeenTime('current',2);mParticle$5.getInstance()._Persistence.getFirstSeenTime('current').should.equal(currentFirstSeenTime);mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous',10);mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous').should.equal(10);mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous',20);mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous').should.equal(10);mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous_set').should.equal(100);mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous_set',200);mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous_set').should.equal(100);done();});it('should properly set setLastSeenTime()',function(done){mParticle$5._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'lst Test',les:new Date().getTime()},previous:{},previous_set:{lst:10},cu:'current'});setCookie$1(workspaceCookieName,cookies,true);// TODO: https://go.mparticle.com/work/SQDSDKS-5339 + // @ts-ignore + mParticle$5.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var clock=sinon$1.useFakeTimers();clock.tick(100);var persistence=mParticle$5.getInstance()._Persistence;persistence.setLastSeenTime('previous',1);expect(persistence.getLastSeenTime('previous')).to.equal(1);persistence.setLastSeenTime('previous',2);expect(persistence.getLastSeenTime('previous')).to.equal(2);expect(persistence.getLastSeenTime('previous_set')).to.equal(10);persistence.setLastSeenTime('previous_set',20);expect(persistence.getLastSeenTime('previous_set')).to.equal(20);expect(persistence.getLastSeenTime('current')).to.equal(100);persistence.setLastSeenTime('current',200);//lastSeenTime for the current user should always reflect the current time, + //even if was set + expect(persistence.getLastSeenTime('current')).to.equal(100);clock.tick(50);expect(persistence.getLastSeenTime('current')).to.equal(150);clock.restore();done();});it("should set firstSeenTime() for a user that doesn't have storage yet",function(done){mParticle$5._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'lst Test',les:new Date().getTime()},cu:'test'});setCookie$1(workspaceCookieName,cookies,true);// FIXME: Should this be in configs or global? + mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance()._Persistence.setFirstSeenTime('1',1);mParticle$5.getInstance()._Persistence.getFirstSeenTime('1').should.equal(1);//firstSeenTime should ignore subsiquent calls after it has been set + mParticle$5.getInstance()._Persistence.setFirstSeenTime('2',2);mParticle$5.getInstance()._Persistence.getFirstSeenTime('1').should.equal(1);done();});it('fst should be set when the user does not change, after an identify request',function(done){mParticle$5._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'lst Test',les:new Date().getTime()},current:{},cu:'current'});mockServer$c.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'current',is_logged_in:false})]);setCookie$1(workspaceCookieName,cookies,true);// FIXME: Should this be in configs or global? + mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('current')).to.equal(null);mParticle$5.Identity.identify();expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('current')).to.not.equal(null);done();});it('lastSeenTime should be null for users in storage without an lst value',function(done){var cookies=JSON.stringify({gs:{sid:'lst Test',les:new Date().getTime()},previous:{},cu:'current'});setCookie$1(workspaceCookieName,cookies,true);// FIXME: config or global? + mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous')).to.equal(null);done();});it('should save to persistence a device id set with setDeviceId',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.setDeviceId('foo-guid');mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das.should.equal('foo-guid');done();});it('should save to persistence a device id set via mParticle.config',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.config.deviceId='foo-guid';mParticle$5.init(apiKey,mParticle$5.config);mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das.should.equal('foo-guid');done();});it('should prioritize device id set via mParticle.config instead of local storage',function(done){mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);var initialDeviceId=mParticle$5.getInstance().getDeviceId();expect(initialDeviceId).to.not.be["null"];var expectedDeviceId='guid-via-config';mParticle$5.config.deviceId=expectedDeviceId;mParticle$5.init(apiKey,mParticle$5.config);expect(mParticle$5.getInstance().getDeviceId(),'Device ID should match guid passed in via config').to.equal(expectedDeviceId);expect(initialDeviceId,'New Device ID should not match Old Device Id').to.not.equal(expectedDeviceId);expect(mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das,'Device ID stored in Local Storage should be the new Device ID').to.equal(expectedDeviceId);done();});// this test confirms a bug has been fixed where setting a user attribute, then user attribute list + // with a special character in it results in a cookie decode error, which only happened + // when config.useCookieStorage was true + it('should save special characters to persistence when on cookies or local storage',function(done){mockServer$c.respondWith(urls.login,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);// first test local storage + mParticle$5.config.useCookieStorage=false;mParticle$5._resetForTests(MPConfig);mParticle$5.init(apiKey,mParticle$5.config);var user=mParticle$5.Identity.getCurrentUser();user.setUserAttribute('ua-1','a');user.setUserAttributeList('ua-list',['a\\','']);user.getAllUserAttributes()['ua-list'][0].should.equal('a\\');user.getAllUserAttributes()['ua-list'][1].should.equal('');user.getAllUserAttributes()['ua-1'].should.equal('a');mParticle$5._resetForTests(MPConfig);// then test cookie storage + mParticle$5.config.useCookieStorage=true;mParticle$5.init(apiKey,mParticle$5.config);var user2=mParticle$5.Identity.getCurrentUser();user2.setUserAttribute('ua-1','a');user2.setUserAttributeList('ua-list',['a\\','']);user2.getAllUserAttributes()['ua-list'][0].should.equal('a\\');user2.getAllUserAttributes()['ua-list'][1].should.equal('');user2.getAllUserAttributes()['ua-1'].should.equal('a');done();});});var findEventFromRequest$6=TestsCore.findEventFromRequest,getForwarderEvent=TestsCore.getForwarderEvent,setLocalStorage$2=TestsCore.setLocalStorage,forwarderDefaultConfiguration$3=TestsCore.forwarderDefaultConfiguration,MockForwarder$5=TestsCore.MockForwarder,MockSideloadedKit$1=TestsCore.MockSideloadedKit;var mockServer$b;describe('forwarders',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);delete mParticle._instances['default_instance'];client.post(urls.events,200);mockServer$b=sinon$1.createFakeServer();mockServer$b.respondImmediately=true;mockServer$b.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mockServer$b.respondWith(urls.login,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mockServer$b.respondWith(urls.logout,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mockServer$b.respondWith(urls.modify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mockServer$b.respondWith(urls.forwarding,[202,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){client.restore();delete window.MockForwarder1;mockServer$b.restore();});it('should add forwarders via dynamic script loading via the addForwarder method',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._getActiveForwarders().length.should.equal(1);done();});it('should invoke forwarder setIdentity on initialized forwarders (debug = false)',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.identifyRequest={userIdentities:{google:'google123'}};var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('setUserIdentityCalled',true);window.MockForwarder1.instance.userIdentities.should.have.property('4','google123');window.mParticle.identifyRequest={};done();});it('should permit forwarder if no consent configured.',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,null);enabled.should.be.ok();done();});it('should not permit forwarder if consent configured but there is no user.',function(done){var enableForwarder=true;var consented=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:'123',hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,null);enabled.should.not.be.ok();done();});var MockUser=function MockUser(){var consentState=null;return {setConsentState:function setConsentState(state){consentState=state;},getConsentState:function getConsentState(){return consentState;}};};it('should disable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and user consent has been rejected',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should disable forwarder if \'Do Not Forward\' when \'Consent Accepted\' is selected and consent has been accepted',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should enable forwarder if \'Only Forward\' when \'Consent Rejected\' is selected and consent has been rejected',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should enable forwarder if \'Only Forward\' when \'Consent Accepted\' is selected and consent has been accepted',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should disable forwarder if \'Only Forward\' when \'Consent Accepted\' is selected and consent has been rejected',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should enable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and consent has been accepted',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should enable forwarder if \'Do Not Forward\' when \'Consent Accepted\' is selected and consent has been rejected',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should enable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and consent has been accepted',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should disable forwarder if \'Do Not Forward\' when CCPA is \'Not Present\' is selected and user CCPA is not present',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=false;var userConsentPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should disable forwarder if \'Do Not Forward\' when CCPA is \'Present\' is selected and user CCPA is present',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=true;var userConsentPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should enable forwarder if \'Only Forward\' when CCPA is \'Not Present\' is selected and user CCPA is not present',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=false;var userConsentPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should enable forwarder if \'Only Forward\' when CCPA data sale opt out is present is selected and user CCPA is present.',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=true;var userConsentPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should disable forwarder if \'Only Forward\' when CCPA is \'Present\' is selected and user CCPA is not present',function(done){var enableForwarder=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=true;var userConsentPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it('should enable forwarder if \'Do Not Forward\' when CCPA is \'Not Present\' is selected and user CCPA is present',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=false;var userConsentPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should enable forwarder if \'Do Not Forward\' when CCPA is \'Present\' is selected and user CCPA is not present',function(done){var enableForwarder=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent=true;var userConsentPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3('MockForwarder');config.filteringConsentRuleValues={includeOnMatch:enableForwarder,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consentPresent}]};window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("does not initialize a forwarder when forwarder's isDebug != mParticle.isDevelopmentMode",function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3();config.isDebug=true;window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);Should(window.MockForwarder1).not.be.ok();mParticle.getInstance()._getActiveForwarders().length.should.equal(0);done();});it('initializes a forwarder with isDebug = false && mParticle.config.isDevelopmentMode = false',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3();window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('initCalled',true);mParticle.getInstance()._getActiveForwarders().length.should.equal(1);Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1);done();});it('initializes a forwarder with isDebug = true && mParticle.config.isDevelopmentMode = true',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=true;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config=forwarderDefaultConfiguration$3();config.isDebug=true;window.mParticle.config.kitConfigs.push(config);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('initCalled',true);Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1);done();});it('initializes forwarders when isDebug = mParticle.config.isDevelopmentMode',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.isDebug=true;var config2=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.kitConfigs.push(config2);mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._getActiveForwarders().length.should.equal(1);Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1);done();});it("sends events to forwarder when forwarder's isDebug = mParticle.config.isDevelopmentMode ",function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=true;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.isDebug=true;window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('send this event to forwarder');window.MockForwarder1.instance.should.have.property('processCalled',true);done();});it('sends events to forwarder v1 endpoint when mParticle.config.isDevelopmentMode = config.isDebug = false',function(done){mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mockServer$b.requests=[];mParticle.logEvent('send this event to forwarder');window.MockForwarder1.instance.should.have.property('processCalled',true);mockServer$b.requests[mockServer$b.requests.length-1].url.includes('/v1/JS/test_key/Forwarding');done();});it('sends forwarding stats to v2 endpoint when featureFlag setting of batching is true',function(done){mParticle._resetForTests(MPConfig);var clock=sinon$1.useFakeTimers();var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.dataPlan={planVersion:10,planId:'plan-slug'};window.mParticle.config.flags={reportBatching:true};mParticle.init(apiKey,window.mParticle.config);mockServer$b.requests=[];mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{'my-key':'my-value'});clock.tick(5000);var event=getForwarderEvent(mockServer$b.requests,'send this event to forwarder',true);Should(event).should.be.ok();mockServer$b.requests[mockServer$b.requests.length-1].url.includes('/v2/JS/test_key/Forwarding');event.should.have.property('mid',1);event.should.have.property('esid',1234567890);event.should.have.property('n','send this event to forwarder');event.should.have.property('attrs');event.should.have.property('dp');event.dp.should.have.property('PlanVersion',10);event.dp.should.have.property('PlanId','plan-slug');event.should.have.property('dp');event.should.have.property('sdk',mParticle.getVersion());event.should.have.property('dt',MessageType$2.PageEvent);event.should.have.property('et',mParticle.EventType.Navigation);event.should.have.property('dbg',mParticle.getInstance()._Store.SDKConfig.isDevelopmentMode);event.should.have.property('ct');event.should.have.property('eec',0);clock.restore();done();});it('should not send forwarding stats to invisible forwarders',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.isVisible=false;mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{'my-key':'my-value'});var event=findEventFromRequest$6(client._calls,'send this event to forwarder',true);Should(event).should.not.have.property('n');done();});it('should invoke forwarder opt out',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.setOptOut(true);window.MockForwarder1.instance.should.have.property('setOptOutCalled',true);done();});it('should invoke forwarder setuserattribute',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);done();});it('should invoke forwarder setuserattribute when calling setUserAttributeList',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('gender',['male']);window.MockForwarder1.instance.should.have.property('setUserAttributeCalled',true);done();});it('should invoke forwarder removeuserattribute',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().removeUserAttribute('gender');window.MockForwarder1.instance.should.have.property('removeUserAttributeCalled',true);done();});it('should filter user attributes from forwarder on log event',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.userAttributeFilters=[mParticle.generateHash('gender')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('UserAttributes');event.UserAttributes.should.not.have.property('gender');done();});it('should filter user identities from forwarder on init and bring customerid as first ID',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.userIdentityFilters=[mParticle.IdentityType.Google];window.mParticle.config.kitConfigs.push(config1);mParticle.Identity.modify({userIdentities:{google:'test@google.com',email:'test@gmail.com',customerid:'123'}});mParticle.init(apiKey,window.mParticle.config);mParticle.userIdentitiesFilterOnInitTest.length.should.equal(2);mParticle.userIdentitiesFilterOnInitTest[0].Type.should.equal(1);mParticle.userIdentitiesFilterOnInitTest[0].Identity.should.equal('123');mParticle.userIdentitiesFilterOnInitTest[1].Type.should.equal(7);mParticle.userIdentitiesFilterOnInitTest[1].Identity.should.equal('test@gmail.com');Should(mParticle.userIdentitiesFilterOnInitTest[2]).not.be.ok();done();});it('should filter user identities from forwarder on log event and bring customerid as first ID',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.userIdentityFilters=[mParticle.IdentityType.Google];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.modify({userIdentities:{google:'test@google.com',email:'test@gmail.com',customerid:'123'}});mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Object.keys(event.UserIdentities).length.should.equal(2);var googleUserIdentityExits=false;event.UserIdentities.forEach(function(identity){if(identity.Type===mParticle.IdentityType.Google){googleUserIdentityExits=true;}});Should(googleUserIdentityExits).not.be.ok();event.UserIdentities[0].Type.should.equal(mParticle.IdentityType.CustomerId);done();});it('should filter user attributes from forwarder on init, and on subsequent set attribute calls',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.userAttributeFilters=[mParticle.generateHash('gender'),mParticle.generateHash('age')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.userAttributesFilterOnInitTest.should.not.have.property('gender');mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('age',32);mParticle.Identity.getCurrentUser().setUserAttribute('weight',150);window.MockForwarder1.instance.userAttributes.should.have.property('weight',150);window.MockForwarder1.instance.userAttributes.should.not.have.property('age');done();});it('should filter user attributes from forwarder on init, and on subsequent remove attribute calls',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);// filtered User Attributes that should should not call removeUserAttribute + config1.userAttributeFilters=[mParticle.generateHash('weight'),mParticle.generateHash('age')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);// force filtered UA in mock forwarder (due to filtering affecting setUserAttribute) and test init + window.MockForwarder1.instance.userAttributes['weight']=150;mParticle.Identity.getCurrentUser().removeUserAttribute('weight');window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(false);mParticle.userAttributesFilterOnInitTest.should.have.property('weight');mParticle.init(apiKey,window.mParticle.config);var dummyUserAttributes={'gender':'male','age':20};// force filtered UA in mock forwarder (due to filtering affecting setUserAttribute) and non filtered UA + for(var _i=0,_Object$keys=Object.keys(dummyUserAttributes);_i<_Object$keys.length;_i++){var key=_Object$keys[_i];window.MockForwarder1.instance.userAttributes[key]=dummyUserAttributes[key];}// "age" is filtered and should not call removeUserAttribute on forwarder + mParticle.Identity.getCurrentUser().removeUserAttribute('age');window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(false);window.MockForwarder1.instance.userAttributes.should.have.property('age',20);// "gender" is not filtered and should call removeUserAttribute on forwarder + mParticle.Identity.getCurrentUser().removeUserAttribute('gender');window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(true);window.MockForwarder1.instance.userAttributes.should.not.have.property('gender');done();});it('should filter event names',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.eventNameFilters=[mParticle.generateHash(mParticle.EventType.Navigation+'test event')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.startNewSession();window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('test event',mParticle.EventType.Navigation);Should(window.MockForwarder1.instance.receivedEvent).not.be.ok();mParticle.logEvent('test event 2',mParticle.EventType.Navigation);Should(window.MockForwarder1.instance.receivedEvent).be.ok();done();});it('should filter page event names',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.screenNameFilters=[mParticle.generateHash(mParticle.EventType.Unknown+'PageView')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.startNewSession();window.MockForwarder1.instance.receivedEvent=null;mParticle.logPageView();Should(window.MockForwarder1.instance.receivedEvent).not.be.ok();done();});it('should filter event attributes',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.attributeFilters=[mParticle.generateHash(mParticle.EventType.Navigation+'test event'+'test attribute')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('test event',mParticle.EventType.Navigation,{'test attribute':'test value','test attribute 2':'test value 2'});var event=window.MockForwarder1.instance.receivedEvent;event.EventAttributes.should.not.have.property('test attribute');event.EventAttributes.should.have.property('test attribute 2');done();});it('should filter pageview attributes',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.attributeFilters=[mParticle.generateHash(mParticle.EventType.Navigation+'test event'+'test attribute')];config1.screenAttributeFilters=[mParticle.generateHash(mParticle.EventType.Unknown+'ScreenA'+'filteredScreenAttribute')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logPageView('ScreenA',{'filteredScreenAttribute':'this will be filtered','unfilteredScreenAttribute':'this will not be filtered'});var event=window.MockForwarder1.instance.receivedEvent;event.EventAttributes.should.not.have.property('filteredScreenAttribute');event.EventAttributes.should.have.property('unfilteredScreenAttribute','this will not be filtered');done();});it('should call logout on forwarder',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.logout();window.MockForwarder1.instance.should.have.property('logOutCalled',true);window.MockForwarder1.instance.should.have.property('onLogoutCompleteCalled',true);done();});it('should pass in app name to forwarder on initialize',function(done){mParticle.config.appName='Unit Tests';mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('appName','Unit Tests');done();});it('should pass in app version to forwarder on initialize',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.config.appVersion='3.0';mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('appVersion','3.0');done();});it('should pass in user identities to forwarder on initialize',function(done){mParticle._resetForTests(MPConfig);setLocalStorage$2();var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);Object.keys(window.MockForwarder1.instance.userIdentities).length.should.equal(1);done();});it('should pass in user attributes to forwarder on initialize',function(done){mParticle._resetForTests(MPConfig);setLocalStorage$2();var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('userAttributes');window.MockForwarder1.instance.userAttributes.should.have.property('color','blue');window.mParticle.identifyRequest={};done();});it('should not forward event if attribute forwarding rule is set',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringEventAttributeValue={eventAttributeName:mParticle.generateHash('ForwardingRule').toString(),eventAttributeValue:mParticle.generateHash('Forward').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{ForwardingRule:'Forward'});var event=window.MockForwarder1.instance.receivedEvent;event.should.not.have.property('EventName','send this event to forwarder');done();});it('should forward event if event attribute forwarding rule is set and includeOnMatch is true',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringEventAttributeValue={eventAttributeName:mParticle.generateHash('ForwardingRule').toString(),eventAttributeValue:mParticle.generateHash('Forward').toString(),includeOnMatch:true};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{Foo:'Bar',ForwardingRule:'Forward'});var event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('EventName','send this event to forwarder');done();});it('should not forward event if event attribute forwarding rule is set and includeOnMatch is true but attributes do not match',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringEventAttributeValue={eventAttributeName:mParticle.generateHash('ForwardingRule').toString(),eventAttributeValue:mParticle.generateHash('Forward').toString(),includeOnMatch:true};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{Forwarding:'Non-Matching'});var event=window.MockForwarder1.instance.receivedEvent;event.should.not.have.property('EventName','send this event to forwarder');done();});it('should not forward event if event attribute forwarding rule is set and includeOnMatch is false',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringEventAttributeValue={eventAttributeName:mParticle.generateHash('ForwardingRule').toString(),eventAttributeValue:mParticle.generateHash('Forward').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.receivedEvent.EventName.should.equal(1);window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{ForwardingRule:'Forward'});var event=window.MockForwarder1.instance.receivedEvent;Should(event).not.be.ok();done();});it('should forward event if event attribute forwarding rule is set and includeOnMatch is false but attributes do not match',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringEventAttributeValue={eventAttributeName:mParticle.generateHash('ForwardingRule').toString(),eventAttributeValue:mParticle.generateHash('Forward').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.receivedEvent.EventName.should.equal(1);window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('send this event to forwarder',mParticle.EventType.Navigation,{Test:'does not match'});var event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('EventName','send this event to forwarder');done();});it('should send event to forwarder if filtering attribute and includingOnMatch is true',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:true};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','Male');mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;event.should.have.property('UserAttributes');event.UserAttributes.should.have.property('Gender','Male');event.EventName.should.equal('test event');done();});it('should not send event to forwarder if filtering attribute and includingOnMatch is false',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','Male');//reset received event, which will have the initial session start event on it + window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).not.be.ok();done();});it('should permit forwarder if no user attribute value filters configured',function(done){var enabled=mParticle.getInstance()._Forwarders.isEnabledForUserAttributes(null,null);enabled.should.be.ok();enabled=mParticle.getInstance()._Forwarders.isEnabledForUserAttributes({},null);enabled.should.be.ok();done();});it('should send event to forwarder if there are no user attributes on event if includeOnMatch = false',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;window.MockForwarder1.instance.receivedEvent.EventName.should.equal('test event');Should(event).be.ok();done();});it('should not send event to forwarder if there are no user attributes on event if includeOnMatch = true',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:true};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).not.be.ok();done();});it('should send event to forwarder if there is no match and includeOnMatch = false',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','female');mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).be.ok();event.EventName.should.equal('test event');done();});it('should not send event to forwarder if there is no match and includeOnMatch = true',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:true};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','female');mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).not.be.ok();done();});it('should reinitialize forwarders when user attribute changes',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue={userAttributeName:mParticle.generateHash('gender').toString(),userAttributeValue:mParticle.generateHash('male').toString(),includeOnMatch:false};window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','Male');var activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(0);window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).not.be.ok();mParticle.Identity.getCurrentUser().setUserAttribute('Gender','famale');activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(1);window.MockForwarder1.instance.receivedEvent=null;mParticle.logEvent('test event');event=window.MockForwarder1.instance.receivedEvent;Should(event).be.ok();done();});it('should send event to forwarder if the filterinUserAttribute object is invalid',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.filteringUserAttributeValue=undefined;window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','Male');mParticle.logEvent('test event');var event=window.MockForwarder1.instance.receivedEvent;Should(event).be.ok();window.MockForwarder1.instance.receivedEvent.EventName.should.equal('test event');done();});it('should call forwarder onUserIdentified method when identity is returned',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('onUserIdentifiedCalled',true);done();});it('should queue forwarder stats reporting and send after 5 seconds if batching feature is true',function(done){var clock=sinon$1.useFakeTimers();mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.flags={reportBatching:true};mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('not in forwarder');var product=mParticle.eCommerce.createProduct('iphone','sku',123,1);mParticle.eCommerce.Cart.add(product,true);var result=getForwarderEvent(mockServer$b.requests,'not in forwarder');Should(result).not.be.ok();clock.tick(5001);result=getForwarderEvent(mockServer$b.requests,'not in forwarder');result.should.be.ok();result=getForwarderEvent(mockServer$b.requests,'eCommerce - AddToCart');result.should.be.ok();clock.restore();done();});it('should initialize forwarders when a user is not logged in and excludeAnonymousUser=false',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();var mockForwarder2=new MockForwarder$5('MockForwarder2',2);mockForwarder.register(window.mParticle.config);mockForwarder2.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.excludeAnonymousUser=false;var config2=forwarderDefaultConfiguration$3('MockForwarder',2);config2.excludeAnonymousUser=true;window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.kitConfigs.push(config2);mockServer$b.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);var activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(1);mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false);done();});it('should only initialize forwarders with excludeUnknownUser = false for non-logged-in users',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();var mockForwarder2=new MockForwarder$5('MockForwarder2',2);mockForwarder.register(window.mParticle.config);mockForwarder2.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.excludeAnonymousUser=false;var config2=forwarderDefaultConfiguration$3('MockForwarder',2);config2.excludeAnonymousUser=true;window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.kitConfigs.push(config2);mockServer$b.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);var activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(1);mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false);done();});it('should initialize all forwarders when a user is logged in and the page reloads',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();var mockForwarder2=new MockForwarder$5('MockForwarder2',2);mockForwarder.register(window.mParticle.config);mockForwarder2.register(window.mParticle.config);var config1=forwarderDefaultConfiguration$3('MockForwarder',1);config1.excludeAnonymousUser=false;var config2=forwarderDefaultConfiguration$3('MockForwarder',2);config2.excludeAnonymousUser=true;window.mParticle.config.kitConfigs.push(config1);window.mParticle.config.kitConfigs.push(config2);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false);var user={userIdentities:{customerid:'customerid3',email:'email3@test.com'}};mockServer$b.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID2',is_logged_in:true})]);mParticle.Identity.login(user);mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(true);var activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(2);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(true);var activeForwarders2=mParticle.getInstance()._getActiveForwarders();activeForwarders2.length.should.equal(2);done();});it('should save logged in status of most recent user to cookies when logged in',function(done){mParticle._resetForTests(MPConfig);mockServer$b.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:true})]);mParticle.init(apiKey,window.mParticle.config);var ls=mParticle.getInstance()._Persistence.getLocalStorage();ls.l.should.equal(true);mParticle.init(apiKey,window.mParticle.config);var ls2=mParticle.getInstance()._Persistence.getLocalStorage();ls2.hasOwnProperty('l').should.equal(true);mockServer$b.respondWith(urls.logout,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mParticle.Identity.logout();var ls3=mParticle.getInstance()._Persistence.getLocalStorage();ls3.l.should.equal(false);mParticle.init(apiKey,window.mParticle.config);var ls4=mParticle.getInstance()._Persistence.getLocalStorage();ls4.l.should.equal(false);done();});it('should not set integration attributes on forwarders when a non-object attr is passed',function(done){mParticle.setIntegrationAttribute(128,123);var adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(0);done();});it('should set integration attributes on forwarders',function(done){mParticle.setIntegrationAttribute(128,{MCID:'abcdefg'});var adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);adobeIntegrationAttributes.MCID.should.equal('abcdefg');done();});it('should clear integration attributes when an empty object or a null is passed',function(done){mParticle.setIntegrationAttribute(128,{MCID:'abcdefg'});var adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(1);mParticle.setIntegrationAttribute(128,{});adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(0);mParticle.setIntegrationAttribute(128,{MCID:'abcdefg'});adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(1);mParticle.setIntegrationAttribute(128,null);adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(0);done();});it('should set only strings as integration attributes',function(done){mParticle.setIntegrationAttribute(128,{MCID:'abcdefg',fail:{test:'false'},nullValue:null,undefinedValue:undefined});var adobeIntegrationAttributes=mParticle.getIntegrationAttributes(128);Object.keys(adobeIntegrationAttributes).length.should.equal(1);done();});it('should add integration delays to the integrationDelays object',function(done){mParticle._setIntegrationDelay(128,true);mParticle._setIntegrationDelay(24,false);mParticle._setIntegrationDelay(10,true);var integrationDelays=mParticle._getIntegrationDelays();integrationDelays.should.have.property('128',true);integrationDelays.should.have.property('24',false);integrationDelays.should.have.property('10',true);done();});it('integration test - should not log events if there are any integrations delaying, then resume logging events once delays are gone',function(done){mParticle._resetForTests(MPConfig);// this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128,true);mParticle._setIntegrationDelay(24,false);mParticle._setIntegrationDelay(10,true);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('Test Event1');client._calls.length.should.equal(0);mParticle._setIntegrationDelay(10,false);mParticle._setIntegrationDelay(128,false);mParticle.logEvent('Test Event2');client._calls.length.should.equal(4);var sessionStartEvent=findEventFromRequest$6(client._calls,'session_start');var ASTEvent=findEventFromRequest$6(client._calls,'application_state_transition');var testEvent1=findEventFromRequest$6(client._calls,'Test Event1');var testEvent2=findEventFromRequest$6(client._calls,'Test Event2');sessionStartEvent.should.be.ok();ASTEvent.should.be.ok();testEvent1.should.be.ok();testEvent2.should.be.ok();done();});it('integration test - should send events after a configured delay, or 5 seconds by default if setIntegrationDelays are still true',function(done){// testing default of 5000 ms + var clock=sinon$1.useFakeTimers();mParticle._resetForTests(MPConfig);// this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128,true);Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(1);mParticle._setIntegrationDelay(24,false);Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(2);mParticle._setIntegrationDelay(10,true);Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(3);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('Test Event1');client._calls.length.should.equal(0);clock.tick(5001);mParticle.logEvent('Test Event2');client._calls.length.should.equal(4);var sessionStartEvent=findEventFromRequest$6(client._calls,'session_start');var ASTEvent=findEventFromRequest$6(client._calls,'application_state_transition');var testEvent1=findEventFromRequest$6(client._calls,'Test Event1');var testEvent2=findEventFromRequest$6(client._calls,'Test Event2');sessionStartEvent.should.be.ok();ASTEvent.should.be.ok();testEvent1.should.be.ok();testEvent2.should.be.ok();clock.restore();// testing user-configured integrationDelayTimeout + clock=sinon$1.useFakeTimers();mParticle._resetForTests(MPConfig);mParticle.config.integrationDelayTimeout=1000;mParticle._setIntegrationDelay(128,true);mParticle._setIntegrationDelay(24,false);mParticle._setIntegrationDelay(10,true);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('Test Event3');client._calls.length.should.equal(0);clock.tick(1001);mParticle.logEvent('Test Event4');client._calls.length.should.equal(4);var sessionStartEvent2=findEventFromRequest$6(client._calls,'session_start');var ASTEvent2=findEventFromRequest$6(client._calls,'application_state_transition');var testEvent3=findEventFromRequest$6(client._calls,'Test Event3');var testEvent4=findEventFromRequest$6(client._calls,'Test Event4');sessionStartEvent2.should.be.ok();ASTEvent2.should.be.ok();testEvent3.should.be.ok();testEvent4.should.be.ok();clock.restore();done();});it('integration test - after an integration delay is set to false, should fire an event after the event timeout',function(done){var clock=sinon$1.useFakeTimers();mParticle._resetForTests(MPConfig);// this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128,true);mParticle._setIntegrationDelay(24,false);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('test1');client._calls.length.should.equal(0);// now that we set all integrations to false, the SDK should process queued events + mParticle._setIntegrationDelay(128,false);clock.tick(5001);client._calls.length.should.equal(3);clock.restore();done();});it('parse and capture forwarderConfiguration properly from backend',function(done){mParticle._resetForTests(MPConfig);mParticle.config.requestConfig=true;var mockForwarder=new MockForwarder$5('DynamicYield',128);var mockForwarder2=new MockForwarder$5('Adobe',124);mockForwarder.register(window.mParticle.config);mockForwarder2.register(window.mParticle.config);var config={kitConfigs:[{name:'DynamicYield',moduleId:128,isDebug:false,isVisible:true,isDebugString:false,hasDebugString:true,settings:{siteId:8769977},screenNameFilters:[],screenAttributeFilters:[],userIdentityFilters:[],userAttributeFilters:[],eventNameFilters:[],eventTypeFilters:[],attributeFilters:[],githubPath:null,filteringEventAttributeValue:null,filteringUserAttributeValue:null,filteringConsentRuleValues:null,consentRegulationFilters:[],consentRegulationPurposeFilters:[],messageTypeFilters:[],messageTypeStateFilters:[],eventSubscriptionId:24884,excludeAnonymousUser:false},{name:'Adobe',moduleId:124,isDebug:false,isVisible:true,isDebugString:false,hasDebugString:true,settings:{siteId:8769977},screenNameFilters:[],screenAttributeFilters:[],userIdentityFilters:[],userAttributeFilters:[],eventNameFilters:[],eventTypeFilters:[],attributeFilters:[],githubPath:null,filteringEventAttributeValue:null,filteringUserAttributeValue:null,filteringConsentRuleValues:null,consentRegulationFilters:[],consentRegulationPurposeFilters:[],messageTypeFilters:[],messageTypeStateFilters:[],eventSubscriptionId:24884,excludeAnonymousUser:false}]};mockServer$b.respondWith(urls.config,[200,{},JSON.stringify(config)]);mockServer$b.requests=[];mParticle.init(apiKey,window.mParticle.config);var activeForwarders=mParticle.getInstance()._getActiveForwarders();activeForwarders.length.should.equal(2);var moduleIds=[124,128];activeForwarders.forEach(function(forwarder){moduleIds.indexOf(forwarder.id).should.be.greaterThanOrEqual(0);});done();});it('configures forwarders before events are logged via identify callback',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.identifyRequest={userIdentities:{google:'google123'}};window.mParticle.config.identityCallback=function(){mParticle.logEvent('test event');};var mockForwarder=new MockForwarder$5();mockForwarder.register(window.mParticle.config);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('processCalled',true);//mock a page reload which has no configuredForwarders + mParticle.getInstance()._Store.configuredForwarders=[];mParticle.init(apiKey,window.mParticle.config);window.MockForwarder1.instance.should.have.property('processCalled',true);done();});it('should retain preInit.forwarderConstructors, and reinitialize forwarders after calling reset, then init',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._getActiveForwarders().length.should.equal(1);// client calls reset + mParticle.reset();// forwarderConstructors are still there + mParticle.getInstance()._preInit.forwarderConstructors.length.should.equal(1);// client reinitializes mParticle after a reset + mParticle.init(apiKey,window.mParticle.config);// forwarderConstructors are still there + mParticle.getInstance()._getActiveForwarders().length.should.equal(1);mParticle.logEvent('send this event to forwarder');window.MockForwarder1.instance.should.have.property('processCalled',true);done();});it('should send SourceMessageId as part of event sent to forwarders',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('Test Event');window.MockForwarder1.instance.receivedEvent.should.have.property('SourceMessageId');done();});it('should send user-defined SourceMessageId as part of event sent to forwarders via baseEvent',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));mParticle.init(apiKey,window.mParticle.config);mParticle.logBaseEvent({messageType:4,name:'Test Event',data:{key:'value'},eventType:mParticle.EventType.Navigation,customFlags:{flagKey:'flagValue'},sourceMessageId:'abcdefg'});window.MockForwarder1.instance.receivedEvent.should.have.property('SourceMessageId','abcdefg');done();});it('should add a logger to forwarders',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5();mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder'));window.mParticle.config.logLevel='verbose';var infoMessage;window.mParticle.config.logger={verbose:function verbose(msg){infoMessage=msg;}};mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('Test Event');infoMessage.should.equal('Test Event sent');done();});describe('kits with suffixes',function(){it('should add forwarders with suffixes and initialize them accordingly if there is a coresponding kit config with the same suffix',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5('ForwarderWithSuffixV3',1,'v3');var mockForwarder2=new MockForwarder$5('ForwarderWithSuffixV4',1,'v4');mParticle.addForwarder(mockForwarder);mParticle.addForwarder(mockForwarder2);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffixV3',1,'v3'));window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffixV4',1,'v4'));mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._getActiveForwarders().length.should.equal(2);done();});it('should not add a forwarder with suffix if there is not a corresponding kit config with the same suffix',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$5('ForwarderWithSuffix',1,'v3');mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffix',1,'v4'));mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._getActiveForwarders().length.should.equal(0);done();});});describe('side loaded kits',function(){describe('initialization',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);delete mParticle._instances['default_instance'];});afterEach(function(){delete window.MockForwarder1;mockServer$b.restore();});it('should add sideloaded kits to the active forwarders',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);var activeForwarders=mParticle.getInstance()._getActiveForwarders();expect(activeForwarders.length,'active forwarders length').to.equal(sideloadedKits.length);expect(activeForwarders[0].name,'1st active forwarder ').to.deep.equal(sideloadedKit1.name);expect(activeForwarders[1].name,'2nd active forwarder').to.deep.equal(sideloadedKit2.name);});it('should add sideloaded kits along with configured forwarders from server to the active forwarders',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;// This mockForwarder simulates a server configured forwarder + var mockForwarder=new MockForwarder$5('fooForwarder',1);mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('fooForwarder',1));mParticle.init(apiKey,window.mParticle.config);var activeForwarders=mParticle.getInstance()._getActiveForwarders();expect(activeForwarders.length,'active forwarders length').to.equal(sideloadedKits.length+1);expect(activeForwarders[0].name,'1st active forwarder name').to.equal('fooForwarder');expect(activeForwarders[1].name,'2nd active forwarder ').to.deep.equal(sideloadedKit1.name);expect(activeForwarders[2].name,'3rd active forwarder').to.deep.equal(sideloadedKit2.name);});it('should add a flag in batches for reporting if sideloaded kits are used',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;// This mockForwarder simulates a server configured forwarder + var mockForwarder=new MockForwarder$5('fooForwarder',1);mParticle.addForwarder(mockForwarder);window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('fooForwarder',1));mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();expect(mpInstance._Store.sideloadedKitsCount).to.equal(2);mParticle.logEvent('foo',mParticle.EventType.Navigation);var batch=JSON.parse(client.lastCall()[1].body);expect(batch).to.have.property('application_info');expect(batch.application_info).to.have.property('sideloaded_kits_count',2);});it('should NOT add a flag in batches for reporting if sideloaded kits are not used',function(){mParticle.init(apiKey,window.mParticle.config);var mpInstance=window.mParticle.getInstance();expect(mpInstance._Store.isUsingSideloadedKits).to.be.undefined;mParticle.logEvent('foo',mParticle.EventType.Navigation);var batch=JSON.parse(client.lastCall()[1].body);expect(batch).to.have.property('application_info');expect(batch.application_info).not.to.have.property('sideloaded_kits_count');});});describe('forwarding',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);delete mParticle._instances['default_instance'];});afterEach(function(){delete window.MockForwarder1;mockServer$b.restore();});it('should send event to sideloaded kits',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.logEvent('foo',mParticle.EventType.Navigation);var sideloadedKit1Event=window.SideloadedKit11.instance.receivedEvent;var sideloadedKit2Event=window.SideloadedKit22.instance.receivedEvent;sideloadedKit1Event.should.have.property('EventName','foo');sideloadedKit2Event.should.have.property('EventName','foo');});it('should invoke sideloaded identify call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.identifyRequest={userIdentities:{google:'google123'}};window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);window.SideloadedKit11.instance.should.have.property('setUserIdentityCalled',true);window.SideloadedKit22.instance.should.have.property('setUserIdentityCalled',true);window.SideloadedKit11.instance.should.have.property('onUserIdentifiedCalled',true);window.SideloadedKit22.instance.should.have.property('onUserIdentifiedCalled',true);});it('should invoke sideloaded set/removeUserAttribute call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().removeUserAttribute('gender');window.SideloadedKit11.instance.should.have.property('setUserAttributeCalled',true);window.SideloadedKit22.instance.should.have.property('setUserAttributeCalled',true);window.SideloadedKit11.instance.should.have.property('removeUserAttributeCalled',true);window.SideloadedKit22.instance.should.have.property('removeUserAttributeCalled',true);});it('should invoke sideloaded logout call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.logout();window.SideloadedKit11.instance.should.have.property('onLogoutCompleteCalled',true);window.SideloadedKit22.instance.should.have.property('onLogoutCompleteCalled',true);});it('should invoke sideloaded login call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.login({userIdentities:{customerid:'abc'}});window.SideloadedKit11.instance.should.have.property('onLoginCompleteCalled',true);window.SideloadedKit22.instance.should.have.property('onLoginCompleteCalled',true);});it('should invoke sideloaded modify call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.modify({userIdentities:{customerid:'abc'}});window.SideloadedKit11.instance.should.have.property('onModifyCompleteCalled',true);window.SideloadedKit22.instance.should.have.property('onModifyCompleteCalled',true);});it('should invoke sideloaded modify call',function(){var sideloadedKit1=new MockSideloadedKit$1('SideloadedKit1',1);var sideloadedKit2=new MockSideloadedKit$1('SideloadedKit2',2);var mpSideloadedKit1=new mParticle.MPSideloadedKit(sideloadedKit1);var mpSideloadedKit2=new mParticle.MPSideloadedKit(sideloadedKit2);var sideloadedKits=[mpSideloadedKit1,mpSideloadedKit2];window.mParticle.config.sideloadedKits=sideloadedKits;mParticle.init(apiKey,window.mParticle.config);mParticle.setOptOut(true);window.SideloadedKit11.instance.should.have.property('setOptOutCalled',true);window.SideloadedKit22.instance.should.have.property('setOptOutCalled',true);});});});});describe('helpers',function(){beforeEach(function(){mParticle.init(apiKey,window.mParticle.config);});it('should correctly validate an attribute value',function(done){var validatedString=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue('testValue1');var validatedNumber=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(1);var validatedNull=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(null);var validatedObject=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue({});var validatedArray=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue([]);var validatedUndefined=mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(undefined);validatedString.should.be.ok();validatedNumber.should.be.ok();validatedNull.should.be.ok();validatedObject.should.not.be.ok();validatedArray.should.not.be.ok();validatedUndefined.should.not.be.ok();done();});it('should return event name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.logEvent('eventName',mParticle.EventType.Location,{invalidValue:{}});bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'eventName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should return product name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.eCommerce.createProduct('productName','sku',1,1,'variant','category','brand','position','couponCode',{invalidValue:{}});bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'productName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should return commerce event name in warning when sanitizing invalid attributes',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');var product1=mParticle.eCommerce.createProduct('prod1','prod1sku',999);var product2=mParticle.eCommerce.createProduct('prod2','prod2sku',799);var customAttributes={invalidValue:{}};mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart,[product1,product2],customAttributes);bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql("For 'eCommerce - AddToCart', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null.");done();});it('should correctly validate an identity request with copyUserAttribute as a key using any identify method',function(done){var identityApiData={userIdentities:{customerid:'123'},copyUserAttributes:true};var identifyResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'identify');var logoutResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'logout');var loginResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'login');var modifyResult=mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData,'modify');identifyResult.valid.should.equal(true);logoutResult.valid.should.equal(true);loginResult.valid.should.equal(true);modifyResult.valid.should.equal(true);done();});it('should correctly parse string or number',function(done){var string='abc';var number=123;var object={};var array=[];var stringResult=mParticle.getInstance()._Helpers.parseStringOrNumber(string);var numberResult=mParticle.getInstance()._Helpers.parseStringOrNumber(number);var objectResult=mParticle.getInstance()._Helpers.parseStringOrNumber(object);var arrayResult=mParticle.getInstance()._Helpers.parseStringOrNumber(array);var nullResult=mParticle.getInstance()._Helpers.parseStringOrNumber(null);stringResult.should.equal(string);numberResult.should.equal(number);Should(objectResult).not.be.ok();Should(arrayResult).not.be.ok();Should(nullResult).not.be.ok();done();});it('should filterUserIdentities and include customerId as first in the array',function(done){var filterList=[2,4,6,8];var userIdentitiesObject={email:'test@gmail.com',other:'abc',customerid:'123',facebook:'facebook123',google:'google123',yahoo:'yahoo123'};var filteredIdentities=mParticle.getInstance()._Helpers.filterUserIdentities(userIdentitiesObject,filterList);filteredIdentities.length.should.equal(3);filteredIdentities[0].should.have.property('Identity','123');filteredIdentities[0].should.have.property('Type',1);filteredIdentities[1].should.have.property('Identity','test@gmail.com');filteredIdentities[1].should.have.property('Type',7);filteredIdentities[2].should.have.property('Identity','abc');filteredIdentities[2].should.have.property('Type',0);done();});it('should return the appropriate boolean for if events should be delayed by an integration',function(done){var integrationDelays1={128:false,20:false,10:true};var integrationDelays2={128:true};var integrationDelays3={128:false};var integrationDelays4={128:false,20:false,10:false};var result1=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays1);var result2=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays2);var result3=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays3);var result4=mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays4);result1.should.equal(true);result2.should.equal(true);result3.should.equal(false);result4.should.equal(false);done();});it('should return false if integration delay object is empty',function(done){var emptyIntegrationDelays={};var result1=mParticle.getInstance()._Helpers.isDelayedByIntegration(emptyIntegrationDelays);result1.should.equal(false);done();});it('should return expected boolean value when strings are passed',function(done){mParticle.getInstance()._Helpers.returnConvertedBoolean('false').should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(false).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('randomstring').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean(0).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(1).should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean('0').should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('1').should.equal(true);mParticle.getInstance()._Helpers.returnConvertedBoolean(null).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean(undefined).should.equal(false);mParticle.getInstance()._Helpers.returnConvertedBoolean('').should.equal(false);done();});it('should return 0 when hashing undefined or null',function(done){mParticle.generateHash(undefined).should.equal(0);mParticle.generateHash(null).should.equal(0);_typeof(mParticle.generateHash(false)).should.equal('number');mParticle.generateHash(false).should.not.equal(0);done();});it('should generate random value',function(done){var randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();window.crypto.getRandomValues=undefined;randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();//old browsers may return undefined despite //defining the getRandomValues API. - window.crypto.getRandomValues=function(a){a=undefined;return a;};randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();done();});it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createMainStorageName(apiKey);cookieName.should.equal('mprtcl-v4_test_key');done();});it('should create a storage name based on default mParticle storage version if no apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createMainStorageName();cookieName.should.equal('mprtcl-v4');done();});it('should create a product storage name based on default mParticle storage version + apiKey if apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createProductStorageName(apiKey);cookieName.should.equal('mprtcl-prodv4_test_key');done();});it('should create a product storage name based on default mParticle storage version if no apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createProductStorageName();cookieName.should.equal('mprtcl-prodv4');done();});});var userApi=null;mParticle._isTestEnv=true;beforeEach(function(){//mocha can't clean up after itself, so this lets + window.crypto.getRandomValues=function(a){a=undefined;return a;};randomValue=mParticle.getInstance()._Helpers.generateUniqueId();randomValue.should.be.ok();done();});it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createMainStorageName(apiKey);cookieName.should.equal('mprtcl-v4_test_key');done();});it('should create a storage name based on default mParticle storage version if no apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createMainStorageName();cookieName.should.equal('mprtcl-v4');done();});it('should create a product storage name based on default mParticle storage version + apiKey if apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createProductStorageName(apiKey);cookieName.should.equal('mprtcl-prodv4_test_key');done();});it('should create a product storage name based on default mParticle storage version if no apiKey is passed in',function(done){var cookieName=mParticle.getInstance()._Helpers.createProductStorageName();cookieName.should.equal('mprtcl-prodv4');done();});});function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return {s:F,n:function n(){if(i>=o.length)return {done:true};return {done:false,value:o[i++]};},e:function e(_e){throw _e;},f:F};}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}var normalCompletion=true,didErr=false,err;return {s:function s(){it=it.call(o);},n:function n(){var step=it.next();normalCompletion=step.done;return step;},e:function e(_e2){didErr=true;err=_e2;},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]();}finally{if(didErr)throw err;}}};}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen);}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i=user1LastSeen).should.equal(true);currentUser.getFirstSeenTime().should.equal(120);clock.tick(20);var user1=mParticle.Identity.getUser('MPID1');user1.getFirstSeenTime().should.equal(user1FirstSeen);mockServer$a.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);mockServer$a.requests=[];mParticle.Identity.login();currentUser=mParticle.Identity.getCurrentUser();currentUser.getMPID().should.equal('MPID1');currentUser.getFirstSeenTime().should.equal(user1FirstSeen);(currentUser.getLastSeenTime()>user1LastSeen).should.equal(true);clock.restore();done();});it('List returned by Identity.getUsers() should be sorted by lastSeenTime, with nulls last',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{lst:200},2:{lst:400},3:{lst:300},4:{},5:{lst:700},cu:'1'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);var users=mParticle.Identity.getUsers();users.length.should.equal(5);users[0].getMPID().should.equal('1');users[1].getMPID().should.equal('5');users[2].getMPID().should.equal('2');users[3].getMPID().should.equal('3');users[4].getMPID().should.equal('4');Should(users[4].getLastSeenTime()).equal(null);done();});it('does not error when simultaneous identity calls are out',function(done){var errorMessages=[];mParticle._resetForTests(MPConfig);mParticle.config.logger={error:function error(msg){errorMessages.push(msg);}};mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.identityCallInFlight=true;mParticle.setLogLevel('warning');mParticle.Identity.login({userIdentities:{customerid:'test'}});errorMessages.length.should.equal(0);done();});it('Startup identity callback should include getPreviousUser()',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'test',les:new Date().getTime()},testMPID:{lst:100},testMPID2:{lst:200},cu:'testMPID'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;var identityResult;function identityCallback(result){identityResult=result;}mParticle.config.identityCallback=identityCallback;mParticle.init(apiKey,window.mParticle.config);identityResult.getUser().getMPID().should.equal('testMPID');Should(identityResult.getPreviousUser()).not.equal(null);Should(identityResult.getPreviousUser().getMPID()).equal('testMPID2');done();});it('Identity callback should include getPreviousUser()',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({testMPID:{lst:200},testMPID2:{lst:100},cu:'testMPID'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);var loginResult;function identityCallback(result){loginResult=result;}mParticle.Identity.login({},identityCallback);mParticle.Identity.getCurrentUser().getMPID().should.equal('testMPID');loginResult.getUser().getMPID().should.equal('testMPID');Should(loginResult.getPreviousUser()).not.equal(null);loginResult.getPreviousUser().getMPID().should.equal('testMPID2');done();});it('should return the correct user for Previous User',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{lst:200},2:{lst:400},3:{lst:300},4:{lst:600},5:{lst:100},cu:'1'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);mockServer$a.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'1',is_logged_in:false})]);var identityResult;mParticle.Identity.identify({},function(result){identityResult=result;});identityResult.getUser().getMPID().should.equal('1');identityResult.getPreviousUser().getMPID().should.equal('4');done();});it('Alias request should be received when API is called validly',function(done){mockServer$a.requests=[];var aliasRequest={destinationMpid:1,sourceMpid:2,startTime:3,endTime:4};mockServer$a.respondWith(urls.alias,[200,{},JSON.stringify({})]);mParticle.Identity.aliasUsers(aliasRequest);mockServer$a.requests.length.should.equal(1);var request=mockServer$a.requests[0];request.url.should.equal(urls.alias);var requestBody=JSON.parse(request.requestBody);Should(requestBody['request_id']).not.equal(null);Should(requestBody['request_type']).equal('alias');Should(requestBody['environment']).equal('production');Should(requestBody['api_key']).equal(mParticle.getInstance()._Store.devToken);var dataBody=requestBody['data'];Should(dataBody).not.equal(null);Should(dataBody['destination_mpid']).equal(1);Should(dataBody['source_mpid']).equal(2);Should(dataBody['start_unixtime_ms']).equal(3);Should(dataBody['end_unixtime_ms']).equal(4);done();});it('Alias request should include scope if specified',function(done){mockServer$a.requests=[];var aliasRequest={destinationMpid:1,sourceMpid:2,startTime:3,endTime:4,scope:'mpid'};mockServer$a.respondWith(urls.alias,[200,{},JSON.stringify({})]);mParticle.Identity.aliasUsers(aliasRequest);mockServer$a.requests.length.should.equal(1);var request=mockServer$a.requests[0];request.url.should.equal(urls.alias);var requestBody=JSON.parse(request.requestBody);var dataBody=requestBody['data'];Should(dataBody['scope']).equal('mpid');done();});it('Should reject malformed Alias Requests',function(done){mParticle.config.logLevel='verbose';var warnMessage=null;mParticle.config.logger={warning:function warning(msg){warnMessage=msg;}};mParticle.init(apiKey,window.mParticle.config);var callbackResult;//missing sourceMpid + var aliasRequest={destinationMpid:1,startTime:3,endTime:4};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue);Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingMpid);Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingMpid);callbackResult=null;warnMessage=null;//missing destinationMpid + aliasRequest={sourceMpid:2,startTime:3,endTime:4};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue);Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingMpid);Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingMpid);callbackResult=null;warnMessage=null;//same destinationMpid & sourceMpid + aliasRequest={destinationMpid:1,sourceMpid:1,startTime:3,endTime:4};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue);Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasNonUniqueMpid);Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasNonUniqueMpid);callbackResult=null;warnMessage=null;//endTime before startTime + aliasRequest={destinationMpid:1,sourceMpid:2,startTime:4,endTime:3};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue);Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasStartBeforeEndTime);Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasStartBeforeEndTime);callbackResult=null;warnMessage=null;//missing endTime and startTime + aliasRequest={destinationMpid:1,sourceMpid:2};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue);Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingTime);Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingTime);callbackResult=null;warnMessage=null;//sanity test, make sure properly formatted requests are accepted + aliasRequest={destinationMpid:1,sourceMpid:2,startTime:3,endTime:4};mockServer$a.respondWith(urls.alias,[200,{},JSON.stringify({})]);mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(200);Should(callbackResult.message).equal(undefined);Should(warnMessage).equal(null);callbackResult=null;done();});it('Should parse error info from Alias Requests',function(done){mParticle.init(apiKey,window.mParticle.config);var errorMessage='this is a sample error message';var callbackResult;mockServer$a.respondWith(urls.alias,[400,{},JSON.stringify({message:errorMessage,code:'ignored code'})]);var aliasRequest={destinationMpid:1,sourceMpid:2,startTime:3,endTime:4};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});callbackResult.httpCode.should.equal(400);callbackResult.message.should.equal(errorMessage);done();});it('Should properly create AliasRequest',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{fst:200,lst:400},cu:'2'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);var clock=sinon$1.useFakeTimers();clock.tick(1000);var destinationUser=mParticle.Identity.getCurrentUser();var sourceUser=mParticle.Identity.getUser('1');var aliasRequest=mParticle.Identity.createAliasRequest(sourceUser,destinationUser);Should(aliasRequest.sourceMpid).equal('1');Should(aliasRequest.destinationMpid).equal('2');Should(aliasRequest.startTime).equal(200);Should(aliasRequest.endTime).equal(400);clock.restore();done();});it('Should fill in missing fst and lst in createAliasRequest',function(done){mParticle._resetForTests(MPConfig);var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{fst:200,lst:400},2:{},cu:'3'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);var clock=sinon$1.useFakeTimers();clock.tick(1000);var destinationUser=mParticle.Identity.getCurrentUser();var sourceUser=mParticle.Identity.getUser('2');var aliasRequest=mParticle.Identity.createAliasRequest(sourceUser,destinationUser);Should(aliasRequest.sourceMpid).equal('2');Should(aliasRequest.destinationMpid).equal('3');//should grab the earliest fst out of any user if user does not have fst + Should(aliasRequest.startTime).equal(200);//should grab currentTime if user does not have lst + Should(aliasRequest.endTime).equal(1000);clock.restore();done();});it('Should fix startTime when default is outside max window create AliasRequest',function(done){mParticle._resetForTests(MPConfig);var millisPerDay=24*60*60*1000;var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{fst:200},cu:'2'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;//set max Alias startTime age to 1 day + mParticle.config.aliasMaxWindow=1;mParticle.init(apiKey,window.mParticle.config);var clock=sinon$1.useFakeTimers();clock.tick(millisPerDay*2);var destinationUser=mParticle.Identity.getCurrentUser();var sourceUser=mParticle.Identity.getUser('1');var aliasRequest=mParticle.Identity.createAliasRequest(sourceUser,destinationUser);Should(aliasRequest.sourceMpid).equal('1');Should(aliasRequest.destinationMpid).equal('2');var oldestAllowedStartTime=new Date().getTime()-mParticle.getInstance()._Store.SDKConfig.aliasMaxWindow*millisPerDay;Should(aliasRequest.startTime).equal(oldestAllowedStartTime);Should(aliasRequest.endTime).equal(new Date().getTime());clock.restore();done();});it('should warn if legal aliasRequest cannot be created with MParticleUser',function(done){var millisPerDay=24*60*60*1000;mParticle.config.logLevel='verbose';var warnMessage=null;mParticle.config.logger={warning:function warning(msg){warnMessage=msg;}};var cookies=JSON.stringify({gs:{sid:'fst Test',les:new Date().getTime()},1:{fst:200,lst:300},cu:'2'});setCookie(workspaceCookieName,cookies);mParticle.useCookieStorage=true;//set max Alias startTime age to 1 day + mParticle.config.aliasMaxWindow=1;mParticle.init(apiKey,window.mParticle.config);var clock=sinon$1.useFakeTimers();clock.tick(millisPerDay*2);var destinationUser=mParticle.Identity.getCurrentUser();var sourceUser=mParticle.Identity.getUser('1');var aliasRequest=mParticle.Identity.createAliasRequest(sourceUser,destinationUser);Should(aliasRequest.sourceMpid).equal('1');Should(aliasRequest.destinationMpid).equal('2');var oldestAllowedStartTime=new Date().getTime()-mParticle.getInstance()._Store.SDKConfig.aliasMaxWindow*millisPerDay;Should(aliasRequest.startTime).equal(oldestAllowedStartTime);Should(aliasRequest.endTime).equal(300);Should(warnMessage).equal('Source User has not been seen in the last '+mParticle.getInstance()._Store.SDKConfig.maxAliasWindow+' days, Alias Request will likely fail');clock.restore();done();});it("Alias request should have environment 'development' when isDevelopmentMode is true",function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.isDevelopmentMode=true;mParticle.init(apiKey,window.mParticle.config);mockServer$a.requests=[];var aliasRequest={destinationMpid:1,sourceMpid:2,startTime:3,endTime:4};mParticle.Identity.aliasUsers(aliasRequest);mockServer$a.requests.length.should.equal(1);var request=mockServer$a.requests[0];var requestBody=JSON.parse(request.requestBody);Should(requestBody['environment']).equal('development');done();});it('should set isFirtRun to false after an app is initialized',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.isFirstRun.should.equal(false);mockServer$a.respondWith(urls.login,[200,{},JSON.stringify({mpid:'otherMPID1',is_logged_in:false})]);mParticle.Identity.login({userIdentities:{customerid:'abc'}});var ls=mParticle.getInstance()._Persistence.getLocalStorage();ls['testMPID'].lst.should.not.equal(null);done();});it('should send back an httpCode of -1 when there is a no coverage (http code returns 0)',function(done){mParticle._resetForTests(MPConfig);var result;function identityCallback(response){result=response;}mockServer$a.respondWith(urls.identify,[0,{},JSON.stringify({body:null})]);mParticle.config.identityCallback=identityCallback;mParticle.init(apiKey,window.mParticle.config);result.httpCode.should.equal(-1);done();});it('should use the custom device id in known_identities when passed via setDeviceId',function(done){mParticle._resetForTests(MPConfig);mockServer$a.requests=[];mockServer$a.respondWith(urls.identify,[200,{},JSON.stringify({body:null})]);mParticle.init(apiKey,window.mParticle.config);var data=getIdentityEvent$1(mockServer$a.requests,'identify');data.known_identities.device_application_stamp.length.should.equal(36);mParticle.setDeviceId('foo-guid');mParticle.Identity.login({userIdentities:{customerid:'test'}});var data2=getIdentityEvent$1(mockServer$a.requests,'login');data2.known_identities.device_application_stamp.should.equal('foo-guid');done();});it('should use the custom device id in known_identities when set via mParticle.config',function(done){mParticle._resetForTests(MPConfig);mockServer$a.respondWith(urls.identify,[200,{},JSON.stringify({body:null})]);mockServer$a.requests=[];window.mParticle.config.deviceId='foo-guid';mParticle.init(apiKey,window.mParticle.config);var data=getIdentityEvent$1(mockServer$a.requests,'identify');data.known_identities.device_application_stamp.should.equal('foo-guid');done();});describe('Deprecate Cart',function(){afterEach(function(){sinon$1.restore();});it('should deprecate the user\'s cart',function(){mParticle.init(apiKey,window.mParticle.config);var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.getInstance().Identity.getCurrentUser().getCart();mParticle.Identity.getCurrentUser().getCart();bond.called.should.eql(true);bond.callCount.should.equal(2);bond.getCalls()[0].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart() will be removed in future releases');});it('should deprecate add',function(){mParticle.init(apiKey,window.mParticle.config);var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');var product=mParticle.eCommerce.createProduct('iPhone','12345',400);mParticle.getInstance().Identity.getCurrentUser().getCart().add(product);mParticle.Identity.getCurrentUser().getCart().add(product);bond.called.should.eql(true);// deprecates on both .getCart, then .add + bond.callCount.should.equal(4);bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().add() will be removed in future releases');});it('should deprecate remove',function(){mParticle.init(apiKey,window.mParticle.config);var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');var product=mParticle.eCommerce.createProduct('iPhone','12345',400);mParticle.getInstance().Identity.getCurrentUser().getCart().remove(product,true);mParticle.Identity.getCurrentUser().getCart().remove(product,true);bond.called.should.eql(true);// deprecates on both .getCart, then .add + bond.callCount.should.equal(4);bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().remove() will be removed in future releases');});it('should deprecate clear',function(){mParticle.init(apiKey,window.mParticle.config);var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.getInstance().Identity.getCurrentUser().getCart().clear();mParticle.Identity.getCurrentUser().getCart().clear();bond.called.should.eql(true);// deprecates on both .getCart, then .add + bond.callCount.should.equal(4);bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().clear() will be removed in future releases');});it('should deprecate getCartProducts',function(){mParticle.init(apiKey,window.mParticle.config);var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.getInstance().Identity.getCurrentUser().getCart().getCartProducts();mParticle.Identity.getCurrentUser().getCart().getCartProducts();bond.called.should.eql(true);// deprecates on both .getCart, then .add + bond.callCount.should.equal(4);bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases');});});});var getIdentityEvent=TestsCore.getIdentityEvent,findEventFromRequest$4=TestsCore.findEventFromRequest,findBatch$3=TestsCore.findBatch;var mockServer$9;describe('event logging',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);client.post(urls.events,200);delete mParticle._instances['default_instance'];mockServer$9=sinon$1.createFakeServer();mockServer$9.respondImmediately=true;mockServer$9.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){mockServer$9.restore();client.restore();mParticle._resetForTests(MPConfig);});it('should log an event',function(done){window.mParticle.logEvent('Test Event',mParticle.EventType.Navigation,{mykey:'myvalue'});var testEvent=findEventFromRequest$4(client._calls,'Test Event');var testEventBatch=findBatch$3(client._calls,'Test Event');testEvent.data.should.have.property('event_name','Test Event');testEvent.data.should.have.property('custom_event_type','navigation');testEvent.data.should.have.property('custom_attributes');testEvent.data.custom_attributes.should.have.property('mykey','myvalue');testEventBatch.should.have.property('mpid',testMPID);done();});it('should log an event with new device id when set on setDeviceId',function(done){window.mParticle.logEvent('Test Event',mParticle.EventType.Navigation,{mykey:'myvalue'});var testEventBatch=findBatch$3(client._calls,'Test Event');// this das should be the SDK auto generated one, which is 36 characters long + testEventBatch.mp_deviceid.should.have.length(36);mParticle.setDeviceId('foo-guid');window.mParticle.logEvent('Test Event2');var testEvent2Batch=findBatch$3(client._calls,'Test Event2');// das should be the one passed to setDeviceId() + testEvent2Batch.should.have.property('mp_deviceid','foo-guid');done();});it('should log an event with new device id when set via mParticle.config',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.deviceId='foo-guid';mParticle.init(apiKey,window.mParticle.config);window.mParticle.logEvent('Test Event');var testEventBatch=findBatch$3(client._calls,'Test Event');// this das should be the SDK auto generated one + testEventBatch.should.have.property('mp_deviceid','foo-guid');done();});it('should allow an event to bypass server upload',function(done){window.mParticle.logEvent('Test Standard Upload',mParticle.EventType.Navigation,{mykey:'myvalue'},{},{shouldUploadEvent:true});window.mParticle.logEvent('Test Upload Bypass',mParticle.EventType.Navigation,{mykey:'myvalue'},{},{shouldUploadEvent:false});var uploadEvent=findEventFromRequest$4(client._calls,'Test Standard Upload');var uploadEventBatch=findBatch$3(client._calls,'Test Standard Upload');var bypassedEvent=findEventFromRequest$4(client._calls,'Test Upload Bypass');uploadEvent.should.be.ok();uploadEvent.data.should.have.property('event_name','Test Standard Upload');uploadEvent.data.should.have.property('custom_event_type','navigation');uploadEvent.data.should.have.property('custom_attributes');uploadEvent.data.custom_attributes.should.have.property('mykey','myvalue');uploadEventBatch.should.have.property('mpid',testMPID);Should(bypassedEvent).not.be.ok();done();});it('should allow an event to bypass server upload via logBaseEvent',function(done){window.mParticle.logBaseEvent({name:'Test Standard Upload',messageType:MessageType$2.PageEvent,eventType:mParticle.EventType.Navigation,data:{mykey:'myvalue'},customFlags:{}},{shouldUploadEvent:true});window.mParticle.logBaseEvent({name:'Test Upload Bypass',messageType:MessageType$2.PageEvent,eventType:mParticle.EventType.Navigation,data:{mykey:'myvalue'},customFlags:{}},{shouldUploadEvent:false});var uploadEvent=findEventFromRequest$4(client._calls,'Test Standard Upload');var uploadEventBatch=findBatch$3(client._calls,'Test Standard Upload');var bypassedEvent=findEventFromRequest$4(client._calls,'Test Upload Bypass');uploadEvent.should.be.ok();uploadEvent.data.should.have.property('event_name','Test Standard Upload');uploadEvent.data.should.have.property('custom_event_type','navigation');uploadEvent.data.should.have.property('custom_attributes');uploadEvent.data.custom_attributes.should.have.property('mykey','myvalue');uploadEventBatch.should.have.property('mpid',testMPID);Should(bypassedEvent).not.be.ok();done();});it('should log an error',function(done){mParticle.logError('my error');var errorEvent=findEventFromRequest$4(client._calls,'my error');Should(errorEvent).be.ok();errorEvent.data.should.have.property('message','Error');errorEvent.data.should.have.property('custom_attributes');errorEvent.data.custom_attributes.should.have.property('m','my error');done();});it('should log an error with name, message, stack',function(done){var error=new Error('my error');error.stack='my stacktrace';mParticle.logError(error);var errorEvent=findEventFromRequest$4(client._calls,'my error');Should(errorEvent).be.ok();errorEvent.data.should.have.property('message','Error');errorEvent.data.should.have.property('custom_attributes');errorEvent.data.custom_attributes.should.have.property('m','my error');errorEvent.data.custom_attributes.should.have.property('s','Error');errorEvent.data.custom_attributes.should.have.property('t','my stacktrace');done();});it('should log an error with custom attrs',function(done){var error=new Error('my error');error.stack='my stacktrace';mParticle.logError(error,{location:'my path',myData:'my data'});var errorEvent=findEventFromRequest$4(client._calls,'my error');Should(errorEvent).be.ok();errorEvent.data.should.have.property('message','Error');errorEvent.data.should.have.property('custom_attributes');errorEvent.data.custom_attributes.should.have.property('location','my path');errorEvent.data.custom_attributes.should.have.property('myData','my data');done();});it('should sanitize error custom attrs',function(done){var bond=sinon$1.spy(mParticle.getInstance().Logger,'warning');mParticle.logError('my error',{invalid:['my invalid attr'],valid:10});var errorEvent=findEventFromRequest$4(client._calls,'my error');Should(errorEvent).be.ok();errorEvent.data.should.have.property('message','Error');errorEvent.data.should.have.property('custom_attributes');errorEvent.data.custom_attributes.should.have.property('valid',10);errorEvent.data.custom_attributes.should.not.have.property('invalid');bond.called.should.eql(true);bond.callCount.should.equal(1);bond.getCalls()[0].args[0].should.eql('For \'my error\', the corresponding attribute value of \'invalid\' must be a string, number, boolean, or null.');done();});it('should log an AST with firstRun = true when first visiting a page, and firstRun = false when reloading the page',function(done){var astEvent=findEventFromRequest$4(client._calls,'application_state_transition');astEvent.data.should.have.property('application_transition_type','application_initialized');astEvent.data.should.have.property('is_first_run',true);astEvent.data.should.have.property('is_upgrade',false);if(document.referrer&&document.referrer.length>0){astEvent.data.should.have.property('launch_referral',window.location.href);}client._calls=[];mParticle.init(apiKey,window.mParticle.config);var astEvent2=findEventFromRequest$4(client._calls,'application_state_transition');astEvent2.data.should.have.property('is_first_run',false);done();});it('should log an AST on init with firstRun = false when cookies already exist',function(done){// cookies currently exist, mParticle.init called from beforeEach + client._calls=[];// log second AST + mParticle.init(apiKey,window.mParticle.config);var astEvent=findEventFromRequest$4(client._calls,'application_state_transition');astEvent.data.should.have.property('is_first_run',false);done();});it('should log a page view',function(done){mParticle.logPageView();var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).be.ok();pageViewEvent.data.should.have.property('custom_attributes');pageViewEvent.data.custom_attributes.should.have.property('hostname',window.location.hostname);pageViewEvent.data.custom_attributes.should.have.property('title',window.document.title);done();});it('should log custom page view',function(done){mParticle.logPageView('My Page View',{testattr:1},{'MyCustom.Flag':'Test'});var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).be.ok();pageViewEvent.data.should.have.property('custom_attributes');pageViewEvent.data.should.have.property('screen_name','My Page View');pageViewEvent.data.custom_attributes.should.have.property('testattr',1);pageViewEvent.data.custom_flags.should.have.property('MyCustom.Flag','Test');done();});it('should pass custom flags in page views',function(done){mParticle.logPageView('test',null,{'MyCustom.Flag':'Test'});var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).be.ok();pageViewEvent.data.should.have.property('custom_flags');pageViewEvent.data.custom_flags.should.have.property('MyCustom.Flag','Test');done();});it('should allow a page view to bypass server upload',function(done){mParticle.logPageView('test bypass',null,null,{shouldUploadEvent:false});var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).not.be.ok();done();});it('should not log a PageView event if there are invalid attrs',function(done){mParticle.logPageView('test1','invalid',null);var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).not.be.ok();done();});it('should not log an event that has an invalid customFlags',function(done){mParticle.logPageView('test',null,'invalid');var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');Should(pageViewEvent).not.be.ok();done();});it('should log event with name PageView when an invalid event name is passed',function(done){client._calls=[];mParticle.logPageView(null);client._calls.length.should.equal(1);var pageViewEvent=findEventFromRequest$4(client._calls,'screen_view');pageViewEvent.data.screen_name.should.equal('PageView');client._calls=[];mParticle.logPageView({test:'test'});client._calls.length.should.equal(1);var pageViewEvent2=findEventFromRequest$4(client._calls,'screen_view');pageViewEvent2.data.screen_name.should.equal('PageView');client._calls=[];mParticle.logPageView([1,2,3]);client._calls.length.should.equal(1);var pageViewEvent3=findEventFromRequest$4(client._calls,'screen_view');pageViewEvent3.data.screen_name.should.equal('PageView');done();});it('should log opt out',function(done){mParticle.setOptOut(true);var optOutEvent=findEventFromRequest$4(client._calls,'opt_out');optOutEvent.event_type.should.equal('opt_out');optOutEvent.data.should.have.property('is_opted_out',true);done();});it('log event requires name',function(done){client._calls=[];mParticle.logEvent();client._calls.should.have.lengthOf(0);done();});it('log event requires valid event type',function(done){client._calls=[];mParticle.logEvent('test',100);client._calls.should.have.lengthOf(0);done();});it('event attributes must be object',function(done){mParticle.logEvent('Test Event',null,1);var testEvent=findEventFromRequest$4(client._calls,'Test Event');testEvent.data.should.have.property('custom_attributes',null);done();});it('opting out should prevent events being sent',function(done){mParticle.setOptOut(true);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(0);done();});it('after logging optout, and reloading, events still should not be sent until opt out is enabled when using local storage',function(done){mParticle.setOptOut(true);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(0);mParticle.setOptOut(false);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(1);mParticle.setOptOut(true);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(0);done();});it('after logging optout, and reloading, events still should not be sent until opt out is enabled when using cookie storage',function(done){mParticle.config.useCookieStorage=true;mParticle.init(apiKey,window.mParticle.config);mParticle.setOptOut(true);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(0);mParticle.setOptOut(false);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(1);mParticle.setOptOut(true);mParticle.init(apiKey,window.mParticle.config);client._calls=[];mParticle.logEvent('test');client._calls.should.have.lengthOf(0);done();});it('should log logout event',function(done){mockServer$9.respondWith(urls.logout,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.Identity.logout();var data=getIdentityEvent(mockServer$9.requests,'logout');data.should.have.properties('client_sdk','environment','previous_mpid','request_id','request_timestamp_ms','context');done();});it('should log login event',function(done){mockServer$9.respondWith(urls.login,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.Identity.login();var data=getIdentityEvent(mockServer$9.requests,'login');data.should.have.properties('client_sdk','environment','previous_mpid','request_id','request_timestamp_ms','context');done();});it('should log modify event',function(done){mockServer$9.respondWith(urls.modify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.Identity.modify();var data=getIdentityEvent(mockServer$9.requests,'modify');data.should.have.properties('client_sdk','environment','identity_changes','request_id','request_timestamp_ms','context');done();});it('should send das with each event logged',function(done){window.mParticle.logEvent('Test Event');var testEventBatch=findBatch$3(client._calls,'Test Event');testEventBatch.should.have.property('mp_deviceid');testEventBatch.mp_deviceid.length.should.equal(36);done();});it('should send consent state with each event logged',function(done){var consentState=mParticle.Consent.createConsentState();consentState.addGDPRConsentState('foo purpose',mParticle.Consent.createGDPRConsent(true,10,'foo document','foo location','foo hardwareId'));mParticle.Identity.getCurrentUser().setConsentState(consentState);window.mParticle.logEvent('Test Event');var testEvent=findBatch$3(client._calls,'Test Event');testEvent.should.have.property('consent_state');testEvent.consent_state.should.have.property('gdpr');testEvent.consent_state.gdpr.should.have.property('foo purpose');var purpose=testEvent.consent_state.gdpr['foo purpose'];purpose.should.have.property('timestamp_unixtime_ms',10);purpose.should.have.property('document','foo document');purpose.should.have.property('location','foo location');purpose.should.have.property('hardware_id','foo hardwareId');mParticle.Identity.getCurrentUser().setConsentState(null);window.mParticle.logEvent('Test Event2');var testEvent2=findBatch$3(client._calls,'Test Event2');testEvent2.should.have.property('consent_state',null);done();});it('should log integration attributes with each event',function(done){mParticle.setIntegrationAttribute(128,{MCID:'abcdefg'});mParticle.logEvent('Test Event');var testEvent=findBatch$3(client._calls,'Test Event');testEvent.should.have.property('integration_attributes');testEvent.integration_attributes.should.have.property('128');testEvent.integration_attributes['128'].should.have.property('MCID','abcdefg');done();});it('should run the callback once when tracking succeeds',function(done){var clock=sinon$1.useFakeTimers();mParticle.init(apiKey,window.mParticle.config);var successCallbackCalled=false;var numberTimesCalled=0;mParticle.startTrackingLocation(function(){numberTimesCalled+=1;successCallbackCalled=true;mParticle.logEvent('Test Event');});// mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000);successCallbackCalled.should.equal(true);var testEvent=findEventFromRequest$4(client._calls,'Test Event');testEvent.data.location.latitude.should.equal(52.5168);testEvent.data.location.longitude.should.equal(13.3889);client._calls=[];//this will hit the watch position again, but won't call the callback again + clock.tick(1000);numberTimesCalled.should.equal(1);testEvent=findEventFromRequest$4(client._calls,'Test Event');Should(testEvent).not.be.ok();clock.restore();done();});it('should run the callback once when tracking fails',function(done){var clock=sinon$1.useFakeTimers();mParticle.init(apiKey,window.mParticle.config);var successCallbackCalled=false;var numberTimesCalled=0;navigator.geolocation.shouldFail=true;mParticle.startTrackingLocation(function(){numberTimesCalled+=1;successCallbackCalled=true;mParticle.logEvent('Test Event');});// mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000);successCallbackCalled.should.equal(true);var testEvent=findEventFromRequest$4(client._calls,'Test Event');testEvent.data.should.have.property('location',null);client._calls=[];//this will hit the watch position again, but won't call the callback again + clock.tick(1000);numberTimesCalled.should.equal(1);testEvent=findEventFromRequest$4(client._calls,'Test Event');Should(testEvent).not.be.ok();navigator.geolocation.shouldFail=false;clock.restore();done();});it('should pass the found or existing position to the callback in startTrackingLocation',function(done){var clock=sinon$1.useFakeTimers();mParticle.init(apiKey,window.mParticle.config);var currentPosition;function callback(position){currentPosition=position;}mParticle.startTrackingLocation(callback);// mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000);var latitudeResult=52.5168;var longitudeResult=13.3889;currentPosition.coords.latitude.should.equal(latitudeResult);currentPosition.coords.longitude.should.equal(longitudeResult);clock.restore();done();});it('should run the callback if tracking already exists',function(done){var clock=sinon$1.useFakeTimers();mParticle.init(apiKey,window.mParticle.config);mParticle.startTrackingLocation();var successCallbackCalled=false;function callback(){successCallbackCalled=true;mParticle.logEvent('Test Event');}mParticle.startTrackingLocation(callback);// mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000);successCallbackCalled.should.equal(true);var testEvent=findEventFromRequest$4(client._calls,'Test Event');var latitudeResult=52.5168;var longitudeResult=13.3889;testEvent.data.location.latitude.should.equal(latitudeResult);testEvent.data.location.longitude.should.equal(longitudeResult);clock.restore();done();});it('should log appName in the payload on v3 endpoint when set on config prior to init',function(done){mParticle.config.appName='a name';mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.application_info.should.have.property('application_name','a name');delete window.mParticle.config.flags;done();});it('should log AST first_run as true on new page loads, and false for when a page has previously been loaded',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,mParticle.config);var batch=JSON.parse(client.lastOptions().body);batch.events[0].data.should.have.property('is_first_run',true);mParticle.init(apiKey,mParticle.config);var batch2=JSON.parse(client.lastOptions().body);batch2.events[0].data.should.have.property('is_first_run',false);delete window.mParticle.config.flags;done();});it('should log AST with launch_referral with a url',function(done){mParticle._resetForTests(MPConfig);mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.init(apiKey,mParticle.config);var batch=JSON.parse(client.lastOptions().body);batch.events[0].data.should.have.property('launch_referral');batch.events[0].data.launch_referral.should.startWith('http://localhost');delete window.mParticle.config.flags;done();});it('should log appName in the payload on v3 endpoint when set on config prior to init',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.init(apiKey,mParticle.config);mParticle.setAppName('another name');window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.application_info.should.have.property('application_name','another name');delete window.mParticle.config.flags;done();});it('should log a batch to v3 with data planning in the payload',function(done){mParticle.config.logLevel='verbose';mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.dataPlan={planId:'plan-slug',planVersion:10};mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.should.have.property('context');batch.context.should.have.property('data_plan');batch.context.data_plan.should.have.property('plan_version',10);batch.context.data_plan.should.have.property('plan_id','plan-slug');delete window.mParticle.config.flags;done();});it('should log a batch to v3 with no version if no version is passed',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.dataPlan={planId:'plan-slug'};mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.should.have.property('context');batch.context.should.have.property('data_plan');batch.context.data_plan.should.not.have.property('plan_version');batch.context.data_plan.should.have.property('plan_id','plan-slug');delete window.mParticle.config.flags;done();});it('should log a batch to v3 with no context if no data plan is passed',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.dataPlan={planVersion:10};mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.should.not.have.property('context');delete window.mParticle.config.flags;done();});it('should log an error if a non slug string is passed as the dataplan planId',function(done){var errorMessage;mParticle.config.logLevel='verbose';mParticle.config.logger={error:function error(msg){if(!errorMessage){errorMessage=msg;}}};mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.dataPlan={planId:'not a slug',planVersion:10};mParticle.init(apiKey,mParticle.config);window.mParticle.logEvent('Test Event');errorMessage.should.equal('Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)');var batch=JSON.parse(client.lastOptions().body);batch.should.not.have.property('context');delete window.mParticle.config.flags;done();});it('should log consent properly to v3 endpoint ',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.config.dataPlan={planVersion:10};mParticle.init(apiKey,mParticle.config);var user=mParticle.Identity.getCurrentUser();// Add to your consent state + var consentState=mParticle.Consent.createConsentState();var ccpa=mParticle.Consent.createCCPAConsent(true,Date.now(),"doc1","location1","hardwareid");consentState.setCCPAConsentState(ccpa);var location_collection_consent=mParticle.Consent.createGDPRConsent(true,Date.now(),"doc1","location1","hardwareid");// Add to your consent state + consentState.addGDPRConsentState("My GDPR Purpose",location_collection_consent);user.setConsentState(consentState);window.mParticle.logEvent('Test Event');var batch=JSON.parse(client.lastOptions().body);batch.should.have.property('consent_state');batch.consent_state.should.have.properties(['gdpr','ccpa']);batch.consent_state.gdpr.should.have.property('my gdpr purpose');batch.consent_state.gdpr['my gdpr purpose'].should.have.property('consented',true);batch.consent_state.gdpr['my gdpr purpose'].should.have.property('document','doc1');batch.consent_state.gdpr['my gdpr purpose'].should.have.property('location','location1');batch.consent_state.gdpr['my gdpr purpose'].should.have.property('hardware_id','hardwareid');batch.consent_state.gdpr['my gdpr purpose'].should.have.property('timestamp_unixtime_ms');batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('consented',true);batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('document','doc1');batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('location','location1');batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('hardware_id','hardwareid');batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('timestamp_unixtime_ms');delete window.mParticle.config.flags;done();});it('should sanitize transaction attributes in the payload on v3 endpoint',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.init(apiKey,mParticle.config);var product1=mParticle.eCommerce.createProduct('iphone','iphoneSKU',999,1);var product2=mParticle.eCommerce.createProduct('galaxy','galaxySKU',799,1);var transactionAttributes={Id:'foo-transaction-id',Revenue:'string',Tax:'string',Shipping:'string'};var customAttributes={sale:true};var customFlags={'Google.Category':'travel'};mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase,[product1,product2],customAttributes,customFlags,transactionAttributes);var batch=JSON.parse(client.lastOptions().body);batch.events[0].data.product_action.total_amount.should.equal(0);batch.events[0].data.product_action.shipping_amount.should.equal(0);batch.events[0].data.product_action.tax_amount.should.equal(0);delete window.mParticle.config.flags;done();});it('should sanitize product attributes in the payload on v3 endpoint',function(done){mParticle.config.flags={eventBatchingIntervalMillis:0};mParticle.init(apiKey,mParticle.config);var product1=mParticle.eCommerce.createProduct('iphone','iphoneSKU','string','string','variant','category','brand','string','coupon');var product2=mParticle.eCommerce.createProduct('galaxy','galaxySKU','string','string','variant','category','brand','string','coupon');var transactionAttributes={Id:'foo-transaction-id',Revenue:'string',Tax:'string',Shipping:'string'};var customAttributes={sale:true};var customFlags={'Google.Category':'travel'};mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase,[product1,product2],customAttributes,customFlags,transactionAttributes);var batch=JSON.parse(client.lastOptions().body);(batch.events[0].data.product_action.products[0].position===null).should.equal(true);batch.events[0].data.product_action.products[0].price.should.equal(0);batch.events[0].data.product_action.products[0].quantity.should.equal(0);batch.events[0].data.product_action.products[0].total_product_amount.should.equal(0);(batch.events[0].data.product_action.products[1].position===null).should.equal(true);batch.events[0].data.product_action.products[1].price.should.equal(0);batch.events[0].data.product_action.products[1].quantity.should.equal(0);batch.events[0].data.product_action.products[1].total_product_amount.should.equal(0);delete window.mParticle.config.flags;done();});});var getLocalStorageProducts=TestsCore.getLocalStorageProducts,forwarderDefaultConfiguration$1=TestsCore.forwarderDefaultConfiguration,findEventFromRequest$3=TestsCore.findEventFromRequest,MockForwarder$3=TestsCore.MockForwarder;var mockServer$8;describe('eCommerce',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);delete mParticle._instances['default_instance'];mockServer$8=sinon$1.createFakeServer();mockServer$8.respondImmediately=true;client.post(urls.events,200);mockServer$8.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){mockServer$8.restore();client.restore();mParticle._resetForTests(MPConfig);});it('should create ecommerce product',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400,2);product.should.have.property('Name','iPhone');product.should.have.property('Sku','12345');product.should.have.property('Price',400);product.should.have.property('Quantity',2);done();});it('should create transaction attributes',function(done){var transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);transactionAttributes.should.have.property('Id','12345');transactionAttributes.should.have.property('Affiliation','test-affiliation');transactionAttributes.should.have.property('CouponCode','coupon-code');transactionAttributes.should.have.property('Revenue',44334);transactionAttributes.should.have.property('Shipping',600);transactionAttributes.should.have.property('Tax',200);done();});it('should log ecommerce event',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345','400',2,'Plus','Phones','Apple',1,'my-coupon-code',{customkey:'customvalue'}),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mParticle.eCommerce.logPurchase(transactionAttributes,product);var purchaseEvent=findEventFromRequest$3(client._calls,'purchase');purchaseEvent.data.should.have.property('product_action');purchaseEvent.data.product_action.should.have.property('action','purchase');purchaseEvent.data.product_action.should.have.property('transaction_id','12345');purchaseEvent.data.product_action.should.have.property('affiliation','test-affiliation');purchaseEvent.data.product_action.should.have.property('coupon_code','coupon-code');purchaseEvent.data.product_action.should.have.property('total_amount',44334);purchaseEvent.data.product_action.should.have.property('shipping_amount',600);purchaseEvent.data.product_action.should.have.property('tax_amount',200);purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(1);purchaseEvent.data.product_action.products[0].should.have.property('id','12345');purchaseEvent.data.product_action.products[0].should.have.property('name','iPhone');purchaseEvent.data.product_action.products[0].should.have.property('price',400);purchaseEvent.data.product_action.products[0].should.have.property('quantity',2);purchaseEvent.data.product_action.products[0].should.have.property('brand','Apple');purchaseEvent.data.product_action.products[0].should.have.property('variant','Plus');purchaseEvent.data.product_action.products[0].should.have.property('category','Phones');purchaseEvent.data.product_action.products[0].should.have.property('total_product_amount',800);purchaseEvent.data.product_action.products[0].should.have.property('position',1);purchaseEvent.data.product_action.products[0].should.have.property('coupon_code','my-coupon-code');purchaseEvent.data.product_action.products[0].should.have.property('custom_attributes');purchaseEvent.data.product_action.products[0].custom_attributes.should.have.property('customkey','customvalue');done();});it('should not log a ecommerce event if there is a typo in the product action type',function(done){// fetchMock calls will have session start and AST events, we want to reset so that we can prove the product action type does not go through (length remains 0 after logging) + client._calls=[];var product=mParticle.eCommerce.createProduct('iPhone','12345','400');// At this point, mockServer.requests contains 3 requests - an identity, + // session start, and AST event. + // We empty it in order to prove the following event does not send an event + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Typo,// <------ will result in a null when converting the product action type as this is not a real value + [product]);client._calls.length.should.equal(0);done();});it('should log badly formed ecommerce event',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',Infinity,'2-foo','Plus','Phones','Apple','1-foo','my-coupon-code',{customkey:'customvalue'}),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code','44334-foo','600-foo','200-foo');mParticle.eCommerce.logPurchase(transactionAttributes,product);var purchaseEvent=findEventFromRequest$3(client._calls,'purchase');purchaseEvent.data.should.have.property('product_action');purchaseEvent.data.product_action.should.have.property('action','purchase');purchaseEvent.data.product_action.should.have.property('transaction_id','12345');purchaseEvent.data.product_action.should.have.property('affiliation','test-affiliation');purchaseEvent.data.product_action.should.have.property('coupon_code','coupon-code');purchaseEvent.data.product_action.should.have.property('total_amount',0);purchaseEvent.data.product_action.should.have.property('shipping_amount',0);purchaseEvent.data.product_action.should.have.property('tax_amount',0);purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(1);purchaseEvent.data.product_action.products[0].should.have.property('id','12345');purchaseEvent.data.product_action.products[0].should.have.property('name','iPhone');purchaseEvent.data.product_action.products[0].should.have.property('price',0);purchaseEvent.data.product_action.products[0].should.have.property('quantity',0);purchaseEvent.data.product_action.products[0].should.have.property('brand','Apple');purchaseEvent.data.product_action.products[0].should.have.property('variant','Plus');purchaseEvent.data.product_action.products[0].should.have.property('category','Phones');purchaseEvent.data.product_action.products[0].should.have.property('position',null);purchaseEvent.data.product_action.products[0].should.have.property('coupon_code','my-coupon-code');purchaseEvent.data.product_action.products[0].should.have.property('total_product_amount',0);purchaseEvent.data.product_action.products[0].should.have.property('custom_attributes');purchaseEvent.data.product_action.products[0].custom_attributes.should.have.property('customkey','customvalue');done();});it('should log identical events for logPurchase and logProductAction with product action type of `purchase`',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345','400',2,'Plus','Phones','Apple',1,'my-coupon-code',{customkey:'customvalue'}),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mParticle.eCommerce.logPurchase(transactionAttributes,product);var purchaseEvent1=findEventFromRequest$3(client._calls,'purchase');client._calls=[];mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase,product,null,null,transactionAttributes);var purchaseEvent2=findEventFromRequest$3(client._calls,'purchase');var productAction1=purchaseEvent1.data.product_action;var productAction2=purchaseEvent2.data.product_action;productAction1.action.should.equal(productAction2.action);productAction1.transaction_id.should.equal(productAction2.transaction_id);productAction1.affiliation.should.equal(productAction2.affiliation);productAction1.coupon_code.should.equal(productAction2.coupon_code);productAction1.total_amount.should.equal(productAction2.total_amount);productAction1.shipping_amount.should.equal(productAction2.shipping_amount);productAction1.tax_amount.should.equal(productAction2.tax_amount);productAction1.products.length.should.equal(productAction2.products.length);productAction1.products[0].name.should.equal(productAction2.products[0].name);productAction1.products[0].id.should.equal(productAction2.products[0].id);productAction1.products[0].price.should.equal(productAction2.products[0].price);productAction1.products[0].quantity.should.equal(productAction2.products[0].quantity);productAction1.products[0].brand.should.equal(productAction2.products[0].brand);productAction1.products[0].variant.should.equal(productAction2.products[0].variant);productAction1.products[0].category.should.equal(productAction2.products[0].category);productAction1.products[0].position.should.equal(productAction2.products[0].position);productAction1.products[0].coupon_code.should.equal(productAction2.products[0].coupon_code);productAction1.products[0].total_product_amount.should.equal(productAction2.products[0].total_product_amount);productAction1.products[0].custom_attributes.customkey.should.equal(productAction2.products[0].custom_attributes.customkey);done();});it('logPurchase should support array of products',function(done){var product1=mParticle.eCommerce.createProduct('iPhone','SKU1',1),product2=mParticle.eCommerce.createProduct('Android','SKU2',1),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345');mParticle.eCommerce.logPurchase(transactionAttributes,[product1,product2]);var purchaseEvent=findEventFromRequest$3(client._calls,'purchase');purchaseEvent.data.should.have.property('product_action');purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(2);purchaseEvent.data.product_action.products[0].should.have.property('name','iPhone');purchaseEvent.data.product_action.products[1].should.have.property('name','Android');done();});it('logRefund should support array of products',function(done){var product1=mParticle.eCommerce.createProduct('iPhone','SKU1',1),product2=mParticle.eCommerce.createProduct('Android','SKU2',1),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345');mParticle.eCommerce.logRefund(transactionAttributes,[product1,product2]);var refundEvent=findEventFromRequest$3(client._calls,'refund');refundEvent.data.should.have.property('product_action');refundEvent.data.product_action.should.have.property('products')["with"].lengthOf(2);refundEvent.data.product_action.products[0].should.have.property('name','iPhone');refundEvent.data.product_action.products[1].should.have.property('name','Android');done();});it('should create promotion',function(done){var promotion=mParticle.eCommerce.createPromotion('12345','my-creative','creative-name',1);Should(promotion).be.ok();promotion.should.have.property('Id','12345');promotion.should.have.property('Creative','my-creative');promotion.should.have.property('Name','creative-name');promotion.should.have.property('Position',1);done();});it('should log promotion click',function(done){var promotion=mParticle.eCommerce.createPromotion('12345','my-creative','creative-name',1);mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick,promotion);var promotionEvent=findEventFromRequest$3(client._calls,'click');Should(promotionEvent).be.ok();promotionEvent.data.promotion_action.should.have.property('action',PromotionActionType$1.PromotionClick);promotionEvent.data.promotion_action.should.have.property('promotions');promotionEvent.data.promotion_action.promotions[0].should.have.property('id','12345');promotionEvent.data.promotion_action.promotions[0].should.have.property('name','creative-name');promotionEvent.data.promotion_action.promotions[0].should.have.property('creative','my-creative');promotionEvent.data.promotion_action.promotions[0].should.have.property('position',1);done();});it('should allow multiple promotions to be logged at once',function(done){var promotion1=mParticle.eCommerce.createPromotion('12345','my-creative1','creative-name1',1);var promotion2=mParticle.eCommerce.createPromotion('67890','my-creative2','creative-name2',2);mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick,[promotion1,promotion2]);var promotionEvent=findEventFromRequest$3(client._calls,'click');Should(promotionEvent).be.ok();promotionEvent.data.promotion_action.should.have.property('action',PromotionActionType$1.PromotionClick);promotionEvent.data.promotion_action.should.have.property('promotions');promotionEvent.data.promotion_action.promotions.length.should.equal(2);promotionEvent.data.promotion_action.promotions[0].should.have.property('id','12345');promotionEvent.data.promotion_action.promotions[0].should.have.property('name','creative-name1');promotionEvent.data.promotion_action.promotions[0].should.have.property('creative','my-creative1');promotionEvent.data.promotion_action.promotions[0].should.have.property('position',1);promotionEvent.data.promotion_action.promotions[1].should.have.property('id','67890');promotionEvent.data.promotion_action.promotions[1].should.have.property('name','creative-name2');promotionEvent.data.promotion_action.promotions[1].should.have.property('creative','my-creative2');promotionEvent.data.promotion_action.promotions[1].should.have.property('position',2);done();});it('should allow an promotions to bypass server upload',function(done){var promotion=mParticle.eCommerce.createPromotion('12345','my-creative','creative-name',1);mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick,promotion,{},{},{shouldUploadEvent:false});var promotionEvent=findEventFromRequest$3(client._calls,'click');Should(promotionEvent).not.be.ok();done();});it('should create impression',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400),impression=mParticle.eCommerce.createImpression('impression-name',product);impression.should.have.property('Name','impression-name');impression.should.have.property('Product');impression.Product.should.have.property('Sku','12345');done();});it('should log impression event',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400),impression=mParticle.eCommerce.createImpression('impression-name',product);mParticle.eCommerce.logImpression(impression);var impressionEvent=findEventFromRequest$3(client._calls,'impression');Should(impressionEvent).be.ok();impressionEvent.data.should.have.property('product_impressions')["with"].lengthOf(1);impressionEvent.data.product_impressions[0].should.have.property('product_impression_list','impression-name');impressionEvent.data.product_impressions[0].should.have.property('products')["with"].lengthOf(1);impressionEvent.data.product_impressions[0].products[0].should.have.property('id','12345');done();});it('should allow an impression to bypass server upload',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400),impression=mParticle.eCommerce.createImpression('impression-name',product);mParticle.eCommerce.logImpression(impression,null,null,{shouldUploadEvent:false});var impressionEvent=findEventFromRequest$3(client._calls,'impression');Should(impressionEvent).not.be.ok();done();});it('should log multiple impression when an array of impressions is passed',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400),impression=mParticle.eCommerce.createImpression('impression-name1',product),product2=mParticle.eCommerce.createProduct('Android','23456',200),impression2=mParticle.eCommerce.createImpression('impression-name2',product2);mParticle.eCommerce.logImpression([impression,impression2]);var impressionEvent=findEventFromRequest$3(client._calls,'impression');Should(impressionEvent).be.ok();impressionEvent.data.should.have.property('product_impressions')["with"].lengthOf(2);impressionEvent.data.product_impressions[0].should.have.property('product_impression_list','impression-name1');impressionEvent.data.product_impressions[0].should.have.property('products')["with"].lengthOf(1);impressionEvent.data.product_impressions[0].products[0].should.have.property('id','12345');impressionEvent.data.product_impressions[1].should.have.property('product_impression_list','impression-name2');impressionEvent.data.product_impressions[1].should.have.property('products')["with"].lengthOf(1);impressionEvent.data.product_impressions[1].products[0].should.have.property('id','23456');done();});it('should log ecommerce refund',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400,2,'Apple','Plus','Phones'),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mParticle.eCommerce.logRefund(transactionAttributes,product);var refundEvent=findEventFromRequest$3(client._calls,'refund');Should(refundEvent).be.ok();refundEvent.data.should.have.property('product_action');refundEvent.data.product_action.should.have.property('action','refund');refundEvent.data.product_action.should.have.property('transaction_id','12345');refundEvent.data.product_action.should.have.property('affiliation','test-affiliation');refundEvent.data.product_action.should.have.property('coupon_code','coupon-code');refundEvent.data.product_action.should.have.property('total_amount',44334);refundEvent.data.product_action.should.have.property('shipping_amount',600);refundEvent.data.product_action.should.have.property('tax_amount',200);refundEvent.data.product_action.products.should.have.length(1);refundEvent.data.product_action.products[0].should.have.property('id','12345');refundEvent.data.product_action.products[0].should.have.property('name','iPhone');refundEvent.data.product_action.products[0].should.have.property('price',400);refundEvent.data.product_action.products[0].should.have.property('quantity',2);refundEvent.data.product_action.products[0].should.have.property('brand','Phones');refundEvent.data.product_action.products[0].should.have.property('variant','Apple');refundEvent.data.product_action.products[0].should.have.property('category','Plus');refundEvent.data.product_action.products[0].should.have.property('total_product_amount',800);done();});it('should log identical events for logRefund and logProductAction with a product action of `refund`',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345','400',2,'Plus','Phones','Apple',1,'my-coupon-code',{customkey:'customvalue'}),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mParticle.eCommerce.logRefund(transactionAttributes,product);var refundEvent1=findEventFromRequest$3(client._calls,'refund');client._calls=[];mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Refund,product,null,null,transactionAttributes);var refundEvent2=findEventFromRequest$3(client._calls,'refund');Should(refundEvent1).be.ok();Should(refundEvent2).be.ok();refundEvent1.data.product_action.action.should.equal(refundEvent2.data.product_action.action);refundEvent1.data.product_action.transaction_id.should.equal(refundEvent2.data.product_action.transaction_id);refundEvent1.data.product_action.affiliation.should.equal(refundEvent2.data.product_action.affiliation);refundEvent1.data.product_action.coupon_code.should.equal(refundEvent2.data.product_action.coupon_code);refundEvent1.data.product_action.total_amount.should.equal(refundEvent2.data.product_action.total_amount);refundEvent1.data.product_action.shipping_amount.should.equal(refundEvent2.data.product_action.shipping_amount);refundEvent1.data.product_action.tax_amount.should.equal(refundEvent2.data.product_action.tax_amount);refundEvent1.data.product_action.products.length.should.equal(refundEvent2.data.product_action.products.length);refundEvent1.data.product_action.products[0].id.should.equal(refundEvent2.data.product_action.products[0].id);refundEvent1.data.product_action.products[0].price.should.equal(refundEvent2.data.product_action.products[0].price);refundEvent1.data.product_action.products[0].quantity.should.equal(refundEvent2.data.product_action.products[0].quantity);refundEvent1.data.product_action.products[0].brand.should.equal(refundEvent2.data.product_action.products[0].brand);refundEvent1.data.product_action.products[0].variant.should.equal(refundEvent2.data.product_action.products[0].variant);refundEvent1.data.product_action.products[0].category.should.equal(refundEvent2.data.product_action.products[0].category);refundEvent1.data.product_action.products[0].position.should.equal(refundEvent2.data.product_action.products[0].position);done();});it('should allow a product action to bypass server upload',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345','400',2,'Plus','Phones','Apple',1,'my-coupon-code',{customkey:'customvalue'}),transactionAttributes=mParticle.eCommerce.createTransactionAttributes('12345','test-affiliation','coupon-code',44334,600,200);mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase,product,null,null,transactionAttributes,{shouldUploadEvent:false});var event=findEventFromRequest$3(client._calls,'purchase');Should(event).not.be.ok();done();});it('should add products to cart',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400);mParticle.eCommerce.Cart.add(product,true);var addToCartEvent=findEventFromRequest$3(client._calls,'add_to_cart');addToCartEvent.data.should.have.property('product_action');addToCartEvent.data.product_action.should.have.property('action','add_to_cart');addToCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(1);addToCartEvent.data.product_action.products[0].should.have.property('id','12345');done();});it('should remove products to cart',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400);mParticle.eCommerce.Cart.add(product);mParticle.eCommerce.Cart.remove({Sku:'12345'},true);var removeFromCartEvent=findEventFromRequest$3(client._calls,'remove_from_cart');removeFromCartEvent.data.should.have.property('product_action');removeFromCartEvent.data.product_action.should.have.property('action','remove_from_cart');removeFromCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(1);removeFromCartEvent.data.product_action.products[0].should.have.property('id','12345');done();});it('should update cart products in cookies after adding/removing product to/from a cart and clearing cart',function(done){var product=mParticle.eCommerce.createProduct('iPhone','12345',400);mParticle.eCommerce.Cart.add(product);var products1=getLocalStorageProducts();products1[testMPID].cp[0].should.have.properties(['Name','Sku','Price']);mParticle.eCommerce.Cart.remove(product);var products2=getLocalStorageProducts();products2[testMPID].cp.length.should.equal(0);mParticle.eCommerce.Cart.add(product);var products3=getLocalStorageProducts();products3[testMPID].cp[0].should.have.properties(['Name','Sku','Price']);mParticle.eCommerce.Cart.clear();var products4=getLocalStorageProducts();products4[testMPID].cp.length.should.equal(0);done();});it('should not add the (config.maxProducts + 1st) item to cookie cartItems and only send cookie cartProducts when logging',function(done){mParticle.config.maxProducts=10;mParticle.config.workspaceToken=workspaceToken;mParticle.init(apiKey,window.mParticle.config);var product=mParticle.eCommerce.createProduct('Product','12345',400);for(var i=0;i500;Should(updated).be.ok();done();},timeout);});it('should not sync cookies when last date is within frequencyCap',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.pixelConfigs=[pixelSettings];setLocalStorage();mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){mockServer$7.requests=[];var data=mParticle.getInstance()._Persistence.getLocalStorage();data[testMPID].csd.should.have.property(5,mParticle.getInstance()._Persistence.getLocalStorage().testMPID.csd['5']);Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1);done();},timeout);});it('should sync cookies when mpid changes',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var data1=mParticle.getInstance()._Persistence.getLocalStorage();mockServer$7.respondWith(urls.login,[200,{},JSON.stringify({mpid:'otherMPID',is_logged_in:false})]);mParticle.Identity.login();setTimeout(function(){var data2=mParticle.getInstance()._Persistence.getLocalStorage();data1[testMPID].csd[5].should.be.ok();data2['otherMPID'].csd[5].should.be.ok();Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1);done();},timeout);},timeout);});it('should not sync cookies when pixelSettings.isDebug is false, pixelSettings.isProduction is true, and mParticle.config.isDevelopmentMode is true',function(done){var pixelSettings={name:'TestPixel',moduleId:5,esId:24053,isDebug:false,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'',redirectUrl:''};mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=true;window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var data1=mParticle.getInstance()._Persistence.getLocalStorage();Object.keys(data1[testMPID]).should.not.have.property('csd');Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(0);done();},500);});it('should not sync cookies when pixelSettings.isDebug is true, pixelSettings.isProduction is false, and mParticle.config.isDevelopmentMode is false',function(done){var pixelSettings={name:'TestPixel',moduleId:5,esId:24053,isDebug:true,isProduction:false,settings:{},frequencyCap:14,pixelUrl:'',redirectUrl:''};mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var data1=mParticle.getInstance()._Persistence.getLocalStorage();data1[testMPID].should.not.have.property('csd');Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(0);done();},timeout);});it('should replace mpID properly',function(done){var result=mParticle.getInstance()._CookieSyncManager.replaceMPID('www.google.com?mpid=%%mpid%%?foo=bar',123);result.should.equal('www.google.com?mpid=123?foo=bar');done();});it("should remove 'amp;' from the URLs",function(done){var result=mParticle.getInstance()._CookieSyncManager.replaceAmp('www.google.com?mpid=%%mpid%%&foo=bar');result.should.equal('www.google.com?mpid=%%mpid%%&foo=bar');done();});it('parse and capture pixel settings properly from backend',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.requestConfig=true;// create some cookies + mParticle.init(apiKey,window.mParticle.config);var mockForwarder=new MockForwarder$2('DynamicYield',128);var mockForwarder2=new MockForwarder$2('Adobe',124);mockForwarder.register(window.mParticle.config);mockForwarder2.register(window.mParticle.config);var forwarderConfigurationResult={pixelConfigs:[{name:'TestPixel',moduleId:5,esId:24053,isDebug:false,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'',redirectUrl:''}]};mockServer$7.respondWith(urls.config,[200,{},JSON.stringify(forwarderConfigurationResult)]);mockServer$7.requests=[];// add pixels to preInitConfig + mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){mParticle.getInstance()._Store.pixelConfigurations.length.should.equal(1);mockServer$7.respondWith(urls.login,[200,{},JSON.stringify({mpid:'MPID1',is_logged_in:false})]);// force the preInit cookie configurations to fire + mParticle.Identity.login({userIdentities:{customerid:'abc'}});setTimeout(function(){var cookies=getLocalStorage$2();Object.keys(cookies['MPID1'].csd).length.should.equal(1);done();},timeout);},timeout);});var MockUser=function MockUser(){var consentState=null;return {setConsentState:function setConsentState(state){consentState=state;},getConsentState:function getConsentState(){return consentState;}};};it('should perform a cookiesync when consent is not configured on the cookiesync setting',function(done){mParticle._resetForTests(MPConfig);pixelSettings.filteringConsentRuleValues={};window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1);var data=mParticle.getInstance()._Persistence.getLocalStorage();data[testMPID].csd.should.have.property('5');done();},timeout);});it('should return false for isEnabledForUserConsent when consent is configured but no user is passed',function(done){mParticle._resetForTests(MPConfig);var enableCookieSync=true;var consented=false;var filteringConsentRuleValues={includeOnMatch:enableCookieSync,values:[{consentPurpose:'123',hasConsented:consented}]};var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,null);enabled.should.not.be.ok();done();});it("should disable cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is rejected",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should disable cookie sync if 'Do Not Forward' when 'Consent Accepted' is selected and user consent is given",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should enable cookie sync if 'Only Forward' when 'Consent Rejected' is selected and user consent is rejected",function(done){var includeOnMatch=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should enable cookie sync if 'Only Forward' when 'Consent Given'is selected and user consent is given",function(done){var includeOnMatch=true;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should disable cookie sync if 'Only Forward' on 'Consent Given' is selected and user consent is not given",function(done){var includeOnMatch=true;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsented=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsented));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should perform a cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is given",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsented=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsented));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should perform a cookie sync if 'Do Not Forward' when 'Consent Given' is selected and user consent is rejected",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var userConsented=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsented));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should perform a cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is given",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var userConsented=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(userConsented));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should not perform a cookie sync if 'Do Not Forward' if CCPA is 'Not Present' is selected and user CCPA is not present",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var ccpaPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should not perform a cookie sync if 'Do Not Forward' if CCPA is 'Present' is selected and user CCPA is present",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var ccpaPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should perform a cookie sync if 'Only Forward' if CCPA is 'Not Present' is selected and user CCPA is not present",function(done){var includeOnMatch=true;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var ccpaPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should perform a cookie sync if 'Only Forward' when CCPA is 'Present' is selected and user CCPA is present",function(done){var includeOnMatch=true;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var ccpaPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should not perform a cookie sync if 'Only Forward' when CCPA is 'Present' is selected and CCPA is not present",function(done){var includeOnMatch=true;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var ccpaPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.not.be.ok();done();});it("should perform a cookie sync if 'Do Not Forward' if CCPA is 'Present' is selected and user CCPA is not present",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;var ccpaPresent=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it("should perform a cookie sync if 'Do Not Forward' if CCPA is 'Not Present' is selected and user CCPA is present",function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;var ccpaPresent=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;var filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};var consentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent));var user=MockUser();user.setConsentState(consentState);var enabled=mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues,user);enabled.should.be.ok();done();});it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when accepting consent is required',function(done){var includeOnMatch=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;pixelSettings.filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var localStorage=mParticle.getInstance()._Persistence.getLocalStorage();localStorage.testMPID.should.not.have.property('csd');var falseConsentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(false));mParticle.Identity.getCurrentUser().setConsentState(falseConsentState);setTimeout(function(){var noCookieSyncLS=mParticle.getInstance()._Persistence.getLocalStorage();noCookieSyncLS.testMPID.should.not.have.property('csd');var trueConsentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(true));mParticle.Identity.getCurrentUser().setConsentState(trueConsentState);setTimeout(function(){var cookieSyncLS=mParticle.getInstance()._Persistence.getLocalStorage();cookieSyncLS.testMPID.should.have.property('csd');cookieSyncLS.testMPID.csd.should.have.property(5);done();},timeout);},timeout);},timeout);});it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when consent is rejected',function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;pixelSettings.filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('1'+'foo purpose 1'),hasConsented:consented}]};window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var localStorage=mParticle.getInstance()._Persistence.getLocalStorage();localStorage.testMPID.should.not.have.property('csd');var falseConsentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(false));mParticle.Identity.getCurrentUser().setConsentState(falseConsentState);setTimeout(function(){var newLocalStorage=mParticle.getInstance()._Persistence.getLocalStorage();newLocalStorage.testMPID.should.not.have.property('csd');var trueConsentState=mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1',mParticle.getInstance().Consent.createGDPRConsent(true));mParticle.Identity.getCurrentUser().setConsentState(trueConsentState);setTimeout(function(){newLocalStorage=mParticle.getInstance()._Persistence.getLocalStorage();newLocalStorage.testMPID.should.have.property('csd');newLocalStorage.testMPID.csd.should.have.property(5);done();},timeout);},timeout);},timeout);});it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when accepting consent is required',function(done){var includeOnMatch=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;pixelSettings.filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var localStorage=mParticle.getInstance()._Persistence.getLocalStorage();localStorage.testMPID.should.not.have.property('csd');var falseConsentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(// false to show that it doesn't perform a cookie sync + mParticle.getInstance().Consent.createCCPAConsent(false));mParticle.Identity.getCurrentUser().setConsentState(falseConsentState);setTimeout(function(){var noCookieSyncLS=mParticle.getInstance()._Persistence.getLocalStorage();noCookieSyncLS.testMPID.should.not.have.property('csd');var trueConsentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(// false to show that it doesn't perform a cookie sync + mParticle.getInstance().Consent.createCCPAConsent(true));mParticle.Identity.getCurrentUser().setConsentState(trueConsentState);setTimeout(function(){var cookieSyncLS=mParticle.getInstance()._Persistence.getLocalStorage();cookieSyncLS.testMPID.should.have.property('csd');cookieSyncLS.testMPID.csd.should.have.property(5);done();},timeout);},timeout);},timeout);});it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when consent is rejected',function(done){var includeOnMatch=false;// 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented=false;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;pixelSettings.filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};window.mParticle.config.pixelConfigs=[pixelSettings];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var localStorage=mParticle.getInstance()._Persistence.getLocalStorage();localStorage.testMPID.should.not.have.property('csd');var falseConsentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(false));mParticle.Identity.getCurrentUser().setConsentState(falseConsentState);setTimeout(function(){var newLocalStorage=mParticle.getInstance()._Persistence.getLocalStorage();newLocalStorage.testMPID.should.not.have.property('csd');var trueConsentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(true));mParticle.Identity.getCurrentUser().setConsentState(trueConsentState);setTimeout(function(){newLocalStorage=mParticle.getInstance()._Persistence.getLocalStorage();newLocalStorage.testMPID.should.have.property('csd');newLocalStorage.testMPID.csd.should.have.property(5);done();},timeout);},timeout);},timeout);});it('should allow some cookie syncs to occur and others to not occur if there are multiple pixels with varying consent levels',function(done){// This test has 2 pixelSettings. pixelSettings1 requires consent pixelSettings2 does not. When mparticle initializes, the pixelSettings2 should fire and pixelSettings1 shouldn't. + // After the appropriate consent is saved to the huser, pixelSettings1 will fire. + var includeOnMatch=true;// 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented=true;mParticle._resetForTests(MPConfig);mParticle.config.isDevelopmentMode=false;// pixelSetting1 has consent required, and so should only perform a cookiesync after consent is saved to the user + var pixelSettings1={name:'TestPixel',moduleId:1,esId:24053,isDebug:true,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'',redirectUrl:''};pixelSettings1.filteringConsentRuleValues={includeOnMatch:includeOnMatch,values:[{consentPurpose:mParticle.generateHash('2'+'data_sale_opt_out'),hasConsented:consented}]};// pixelSetting2 does not have any consent required, and so should always perform a cookiesync + var pixelSettings2={name:'TestPixel2',moduleId:2,esId:24053,isDebug:true,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'',redirectUrl:''};window.mParticle.config.pixelConfigs=[pixelSettings1,pixelSettings2];mParticle.init(apiKey,window.mParticle.config);setTimeout(function(){var localStorage=mParticle.getInstance()._Persistence.getLocalStorage();localStorage.testMPID.should.have.property('csd');// Performs a cookie sync for 2 but not 1 + localStorage.testMPID.csd.should.not.have.property(1);localStorage.testMPID.csd.should.have.property(2);var trueConsentState=mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(true));mParticle.Identity.getCurrentUser().setConsentState(trueConsentState);setTimeout(function(){var newLocalStorage=mParticle.getInstance()._Persistence.getLocalStorage();newLocalStorage.testMPID.should.have.property('csd');// Now has both cookie syncs because the appropriate consent was added + newLocalStorage.testMPID.csd.should.have.property(2);newLocalStorage.testMPID.csd.should.have.property(1);done();},timeout);},timeout);});});var findEventFromRequest$2=TestsCore.findEventFromRequest,findBatch$2=TestsCore.findBatch,getLocalStorage$1=TestsCore.getLocalStorage,MockForwarder$1=TestsCore.MockForwarder;var mockServer$6;describe('identities and attributes',function(){beforeEach(function(){mockServer$6=sinon$1.createFakeServer();mockServer$6.respondImmediately=true;client.post(urls.events,200);mockServer$6.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){mockServer$6.restore();client.restore();});it('should set user attribute',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$1();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');event.should.have.property('user_attributes');event.user_attributes.should.have.property('gender','male');var cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('gender','male');done();});it('should set user attribute be case insensitive',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$1();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','male');mParticle.Identity.getCurrentUser().setUserAttribute('gender','female');mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');var cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('gender','female');event.should.have.property('user_attributes');event.user_attributes.should.have.property('gender','female');event.user_attributes.should.not.have.property('Gender');mParticle.Identity.getCurrentUser().setUserAttribute('Gender','male');mParticle.logEvent('test user attributes2');var event2=findBatch$2(client._calls,'test user attributes2');event2.user_attributes.should.have.property('Gender','male');event2.user_attributes.should.not.have.property('gender');cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('Gender','male');done();});it('should set multiple user attributes with setUserAttributes',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$1();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributes({gender:'male',age:21});mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');var cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('gender','male');cookies[testMPID].ua.should.have.property('age',21);event.should.have.property('user_attributes');event.user_attributes.should.have.property('gender','male');event.user_attributes.should.have.property('age',21);done();});it('should remove user attribute',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$1();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().removeUserAttribute('gender');mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');event.user_attributes.should.not.have.property('gender');var cookies=getLocalStorage$1();Should(cookies[testMPID].ua).not.be.ok();done();});it('should remove user attribute case insensitive',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder$1();mockForwarder.register(window.mParticle.config);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('Gender','male');mParticle.Identity.getCurrentUser().removeUserAttribute('gender');mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');event.user_attributes.should.not.have.property('Gender');var cookies=getLocalStorage$1();Should(cookies[testMPID].ua).not.be.ok();done();});it('should set session attribute',function(done){mParticle.setSessionAttribute('name','test');mParticle.logEvent('test event');var event=findEventFromRequest$2(client._calls,'test event');Should(event.data.custom_attributes).equal(null);mParticle.endSession();var sessionEndEvent=findEventFromRequest$2(client._calls,'session_end');sessionEndEvent.data.custom_attributes.should.have.property('name','test');done();});it('should set session attribute case insensitive',function(done){mParticle.setSessionAttribute('name','test');mParticle.setSessionAttribute('Name','test1');mParticle.endSession();var sessionEndEvent=findEventFromRequest$2(client._calls,'session_end');sessionEndEvent.data.custom_attributes.should.have.property('name','test1');sessionEndEvent.data.custom_attributes.should.not.have.property('Name');done();});it("should not set a session attribute's key as an object or array)",function(done){mParticle.setSessionAttribute({key:'value'},'test');mParticle.endSession();var sessionEndEvent1=findEventFromRequest$2(client._calls,'session_end');mParticle.startNewSession();client._calls=[];mParticle.setSessionAttribute(['test'],'test');mParticle.endSession();var sessionEndEvent2=findEventFromRequest$2(client._calls,'session_end');Object.keys(sessionEndEvent1.data.custom_attributes).length.should.equal(0);Object.keys(sessionEndEvent2.data.custom_attributes).length.should.equal(0);done();});it('should remove session attributes when session ends',function(done){mParticle.startNewSession();mParticle.setSessionAttribute('name','test');mParticle.endSession();client._calls=[];mParticle.startNewSession();mParticle.endSession();var sessionEndEvent=findEventFromRequest$2(client._calls,'session_end');sessionEndEvent.data.custom_attributes.should.not.have.property('name');done();});it('should set and log position',function(done){mParticle.setPosition(34.134103,-118.321694);mParticle.logEvent('Test Event');var event=findEventFromRequest$2(client._calls,'Test Event');event.data.should.have.property('location');event.data.location.should.have.property('latitude',34.134103);event.data.location.should.have.property('longitude',-118.321694);done();});it('should set user tag',function(done){mParticle.Identity.getCurrentUser().setUserTag('test');mParticle.logEvent('Test Event');var event=findBatch$2(client._calls,'Test Event');event.should.have.property('user_attributes');event.user_attributes.should.have.property('test',null);var cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('test');done();});it('should set user tag case insensitive',function(done){mParticle.Identity.getCurrentUser().setUserTag('Test');mParticle.Identity.getCurrentUser().setUserTag('test');mParticle.logEvent('Test Event');var event=findBatch$2(client._calls,'Test Event');event.should.have.property('user_attributes');event.user_attributes.should.not.have.property('Test');event.user_attributes.should.have.property('test');var cookies=getLocalStorage$1();cookies[testMPID].ua.should.have.property('test');done();});it('should remove user tag',function(done){mParticle.Identity.getCurrentUser().setUserTag('test');mParticle.Identity.getCurrentUser().removeUserTag('test');mParticle.logEvent('test event');var event=findBatch$2(client._calls,'test event');event.should.have.property('user_attributes');event.user_attributes.should.not.have.property('test');var cookies=getLocalStorage$1();Should(cookies[testMPID].ua).not.be.ok();done();});it('should remove user tag case insensitive',function(done){mParticle.Identity.getCurrentUser().setUserTag('Test');mParticle.Identity.getCurrentUser().removeUserTag('test');mParticle.logEvent('test event');var event=findBatch$2(client._calls,'test event');event.should.have.property('user_attributes');event.user_attributes.should.not.have.property('Test');var cookies=getLocalStorage$1();Should(cookies[testMPID].ua).not.be.ok();done();});it('should set user attribute list',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');event.should.have.property('user_attributes');event.user_attributes.should.have.property('numbers',[1,2,3,4,5]);var cookies=getLocalStorage$1();cookies[testMPID].ua.numbers.length.should.equal(5);done();});it('should set user attribute list case insensitive',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);mParticle.Identity.getCurrentUser().setUserAttributeList('Numbers',[1,2,3,4,5,6]);mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');var cookies=getLocalStorage$1();event.should.have.property('user_attributes');event.user_attributes.should.have.property('Numbers',[1,2,3,4,5,6]);event.user_attributes.should.not.have.property('numbers');cookies[testMPID].ua.Numbers.length.should.equal(6);mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);mParticle.logEvent('test user attributes2');var event2=findBatch$2(client._calls,'test user attributes2');var cookies3=getLocalStorage$1();event2.user_attributes.should.have.property('numbers',[1,2,3,4,5]);event2.user_attributes.should.not.have.property('Numbers');cookies3[testMPID].ua.numbers.length.should.equal(5);done();});it('should make a copy of user attribute list',function(done){var list=[1,2,3,4,5];mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',list);list.push(6);mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');var cookies=getLocalStorage$1();cookies[testMPID].ua.numbers.length.should.equal(5);event.should.have.property('user_attributes');event.user_attributes.should.have.property('numbers')["with"].lengthOf(5);done();});it('should remove all user attributes',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);mParticle.Identity.getCurrentUser().removeAllUserAttributes();mParticle.logEvent('test user attributes');var event=findBatch$2(client._calls,'test user attributes');var cookies=getLocalStorage$1();event.should.have.property('user_attributes',{});Should(cookies[testMPID].ua).not.be.ok();done();});it('should get user attribute lists',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);var userAttributes=mParticle.Identity.getCurrentUser().getUserAttributesLists();userAttributes.should.have.property('numbers');userAttributes.should.not.have.property('gender');done();});it('should copy when calling get user attribute lists',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);var userAttributes=mParticle.Identity.getCurrentUser().getUserAttributesLists();userAttributes['numbers'].push(6);var userAttributes1=mParticle.Identity.getCurrentUser().getUserAttributesLists();userAttributes1['numbers'].should.have.lengthOf(5);done();});it('should copy when calling get user attributes',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().setUserAttributeList('numbers',[1,2,3,4,5]);var userAttributes=mParticle.Identity.getCurrentUser().getAllUserAttributes();userAttributes.blah='test';userAttributes['numbers'].push(6);var userAttributes1=mParticle.Identity.getCurrentUser().getAllUserAttributes();userAttributes1['numbers'].should.have.lengthOf(5);userAttributes1.should.not.have.property('blah');done();});it('should get all user attributes',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('test','123');mParticle.Identity.getCurrentUser().setUserAttribute('another test','blah');var attrs=mParticle.Identity.getCurrentUser().getAllUserAttributes();attrs.should.have.property('test','123');attrs.should.have.property('another test','blah');done();});it('should not set user attribute list if value is not array',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttributeList('mykey',1234);var attrs=mParticle.Identity.getCurrentUser().getAllUserAttributes();attrs.should.not.have.property('mykey');done();});it('should not set bad session attribute value',function(done){mParticle.setSessionAttribute('name',{bad:'bad'});mParticle.endSession();var sessionEndEvent=findEventFromRequest$2(client._calls,'session_end');sessionEndEvent.data.custom_attributes.should.not.have.property('name');done();});it('should not set a bad user attribute key or value',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('gender',{bad:'bad'});mParticle.logEvent('test bad user attributes1');var event1=findBatch$2(client._calls,'test bad user attributes1');mParticle.Identity.getCurrentUser().setUserAttribute('gender',['bad','bad','bad']);mParticle.logEvent('test bad user attributes2');var event2=findBatch$2(client._calls,'test bad user attributes2');mParticle.Identity.getCurrentUser().setUserAttribute({bad:'bad'},'male');mParticle.logEvent('test bad user attributes3');var event3=findBatch$2(client._calls,'test bad user attributes3');mParticle.Identity.getCurrentUser().setUserAttribute(['bad','bad','bad'],'female');mParticle.logEvent('test bad user attributes4');var event4=findBatch$2(client._calls,'test bad user attributes4');mParticle.Identity.getCurrentUser().setUserAttribute(null,'female');mParticle.logEvent('test bad user attributes5');var event5=findBatch$2(client._calls,'test bad user attributes5');mParticle.Identity.getCurrentUser().setUserAttribute(undefined,'female');mParticle.logEvent('test bad user attributes6');var event6=findBatch$2(client._calls,'test bad user attributes6');event1.should.have.property('user_attributes');event1.user_attributes.should.not.have.property('gender');event2.should.have.property('user_attributes');event2.user_attributes.should.not.have.property('gender');event3.should.have.property('user_attributes');event3.user_attributes.should.not.have.property('gender');event4.should.have.property('user_attributes');event4.user_attributes.should.not.have.property('gender');event5.should.have.property('user_attributes');event5.user_attributes.should.not.have.property('gender');event6.should.have.property('user_attributes');event6.user_attributes.should.not.have.property('gender');done();});it('should get cart products',function(done){var product1=mParticle.eCommerce.createProduct('iPhone','SKU1',1),product2=mParticle.eCommerce.createProduct('Android','SKU2',1);mParticle.eCommerce.Cart.add([product1,product2]);var cartProducts=mParticle.Identity.getCurrentUser().getCart().getCartProducts();cartProducts.length.should.equal(2);JSON.stringify(cartProducts[0]).should.equal(JSON.stringify(product1));JSON.stringify(cartProducts[1]).should.equal(JSON.stringify(product2));done();});it('should send user attribute change requests when setting new attributes',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);// set a new attribute, age + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('age','25');var body=JSON.parse(client.lastOptions().body);body.user_attributes.should.have.property('age','25');var event=body.events[0];event.should.be.ok();event.event_type.should.equal('user_attribute_change');event.data["new"].should.equal('25');(event.data.old===null).should.equal(true);event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(true);// change age attribute + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('age','30');body=JSON.parse(client.lastOptions().body);body.user_attributes.should.have.property('age','30');event=body.events[0];event.event_type.should.equal('user_attribute_change');event.data["new"].should.equal('30');event.data.old.should.equal('25');event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(false);// removes age attribute + client._calls=[];mParticle.Identity.getCurrentUser().removeUserAttribute('age');body=JSON.parse(client.lastOptions().body);body.user_attributes.should.not.have.property('age');event=body.events[0];event.event_type.should.equal('user_attribute_change');(event.data["new"]===null).should.equal(true);event.data.old.should.equal('30');event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(true);event.data.is_new_attribute.should.equal(false);// set a user attribute list + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttributeList('age',['test1','test2']);body=JSON.parse(client.lastOptions().body);body.user_attributes.age[0].should.equal('test1');body.user_attributes.age[1].should.equal('test2');event=body.events[0];event.event_type.should.equal('user_attribute_change');var obj={test1:true,test2:true};event.data["new"].forEach(function(userAttr){obj[userAttr].should.equal(true);});(event.data.old===null).should.equal(true);event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(true);// changes ordering of above attribute list + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttributeList('age',['test2','test1']);body=JSON.parse(client.lastOptions().body);body.user_attributes.age[0].should.equal('test2');body.user_attributes.age[1].should.equal('test1');event=JSON.parse(client.lastOptions().body).events[0];event.event_type.should.equal('user_attribute_change');obj={test1:true,test2:true};event.data["new"].forEach(function(userAttr){obj[userAttr].should.equal(true);});(event.data.old[0]==='test1').should.equal(true);(event.data.old[1]==='test2').should.equal(true);event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(false);delete window.mParticle.config.flags;done();});it('should send user attribute change requests for the MPID it is being set on',function(done){mParticle._resetForTests(MPConfig);mParticle.init(apiKey,window.mParticle.config);mParticle.Identity.getCurrentUser().setUserAttribute('age','25');var testMPID=mParticle.Identity.getCurrentUser().getMPID();var body=JSON.parse(client.lastOptions().body);body.mpid.should.equal(testMPID);var event=body.events[0];event.event_type.should.equal('user_attribute_change');event.data["new"].should.equal('25');Should(event.data.old).equal(null);event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(true);// new user logs in + var loginUser={userIdentities:{customerid:'customerid1'}};mockServer$6.respondWith(urls.login,[200,{},JSON.stringify({mpid:'anotherMPID',is_logged_in:true})]);mParticle.Identity.login(loginUser);var users=mParticle.Identity.getUsers();users.length.should.equal(2);var anotherMPIDUser=users[0];var testMPIDUser=users[1];anotherMPIDUser.getMPID().should.equal('anotherMPID');testMPIDUser.getMPID().should.equal('testMPID');anotherMPIDUser.setUserAttribute('age','30');body=JSON.parse(client.lastOptions().body);event=body.events[0];body.mpid.should.equal(anotherMPIDUser.getMPID());event.event_type.should.equal('user_attribute_change');event.data["new"].should.equal('30');Should(event.data.old).equal(null);event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(true);testMPIDUser.setUserAttribute('age','20');body=JSON.parse(client.lastOptions().body);body.mpid.should.equal(testMPIDUser.getMPID());event=body.events[0];event.event_type.should.equal('user_attribute_change');event.data["new"].should.equal('20');event.data.old.should.equal('25');event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(false);event.data.is_new_attribute.should.equal(false);// remove user attribute + anotherMPIDUser.removeUserAttribute('age');body=JSON.parse(client.lastOptions().body);body.mpid.should.equal(anotherMPIDUser.getMPID());event=body.events[0];event.event_type.should.equal('user_attribute_change');Should(event.data["new"]).equal(null);event.data.old.should.equal('30');event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(true);event.data.is_new_attribute.should.equal(false);testMPIDUser.removeUserAttribute('age');body=JSON.parse(client.lastOptions().body);body.mpid.should.equal(testMPIDUser.getMPID());event=body.events[0];event.event_type.should.equal('user_attribute_change');Should(event.data["new"]).equal(null);event.data.old.should.equal('20');event.data.user_attribute_name.should.equal('age');event.data.deleted.should.equal(true);event.data.is_new_attribute.should.equal(false);delete window.mParticle.config.flags;done();});it('should send user identity change requests when setting new identities on new users',function(done){mParticle._resetForTests(MPConfig);client._calls=[];window.mParticle.config.identifyRequest={userIdentities:{email:'initial@gmail.com'}};mParticle.init(apiKey,window.mParticle.config);JSON.parse(client.lastOptions().body).user_identities.should.have.property('email','initial@gmail.com');mParticle.logEvent('testAfterInit');JSON.parse(client.lastOptions().body).user_identities.should.have.property('email','initial@gmail.com');client.calls().forEach(function(call){JSON.parse(call[1].body).user_identities.should.have.property('email','initial@gmail.com');});mockServer$6.respondWith(urls.login,[200,{},JSON.stringify({mpid:'anotherMPID',is_logged_in:true})]);client._calls=[];// anonymous user is in storage, new user logs in + var loginUser={userIdentities:{customerid:'customerid1'}};mParticle.Identity.login(loginUser);var body=JSON.parse(client.lastOptions().body);// should be the new MPID + body.mpid.should.equal('anotherMPID');body.user_identities.should.have.property('customer_id','customerid1');body.user_identities.should.not.have.property('email');var event=body.events[0];event.should.be.ok();event.event_type.should.equal('user_identity_change');event.data["new"].identity_type.should.equal('customer_id');event.data["new"].identity.should.equal('customerid1');_typeof(event.data["new"].timestamp_unixtime_ms).should.equal('number');event.data["new"].created_this_batch.should.equal(true);event.data.old.identity_type.should.equal('customer_id');(event.data.old.identity===null).should.equal(true);_typeof(event.data.old.timestamp_unixtime_ms).should.equal('number');event.data.old.created_this_batch.should.equal(false);mParticle.logEvent('testAfterLogin');body=JSON.parse(client.lastOptions().body);body.user_identities.should.have.property('customer_id','customerid1');body.user_identities.should.not.have.property('email');// change customerid creates an identity change event + var modifyUser={userIdentities:{customerid:'customerid2'}};mockServer$6.respondWith('https://identity.mparticle.com/v1/anotherMPID/modify',[200,{},JSON.stringify({mpid:'anotherMPID',is_logged_in:true})]);mParticle.Identity.modify(modifyUser);var body2=JSON.parse(client.lastOptions().body);body2.mpid.should.equal('anotherMPID');body2.user_identities.should.have.property('customer_id','customerid2');body2.user_identities.should.not.have.property('email');var event2=body2.events[0];event2.should.be.ok();event2.event_type.should.equal('user_identity_change');event2.data["new"].identity_type.should.equal('customer_id');event2.data["new"].identity.should.equal('customerid2');_typeof(event2.data["new"].timestamp_unixtime_ms).should.equal('number');event2.data["new"].created_this_batch.should.equal(false);event2.data.old.identity_type.should.equal('customer_id');event2.data.old.identity.should.equal('customerid1');_typeof(event2.data.old.timestamp_unixtime_ms).should.equal('number');event2.data.old.created_this_batch.should.equal(false);// Adding a new identity to the current user will create an identity change event + var modifyUser2={userIdentities:{customerid:'customerid2',email:'test@test.com'}};client._calls=[];mParticle.Identity.modify(modifyUser2);var body3=JSON.parse(client.lastOptions().body);body3.mpid.should.equal('anotherMPID');var event3=body3.events[0];event3.should.be.ok();event3.event_type.should.equal('user_identity_change');event3.data["new"].identity_type.should.equal('email');event3.data["new"].identity.should.equal('test@test.com');_typeof(event3.data["new"].timestamp_unixtime_ms).should.equal('number');event3.data["new"].created_this_batch.should.equal(true);event3.data.old.identity_type.should.equal('email');(event3.data.old.identity===null).should.equal(true);_typeof(event3.data.old.timestamp_unixtime_ms).should.equal('number');event3.data.old.created_this_batch.should.equal(false);// logout with an other will create only a change event for the other + var logoutUser={userIdentities:{other:'other1'}};client._calls=[];mockServer$6.respondWith(urls.logout,[200,{},JSON.stringify({mpid:'mpid2',is_logged_in:false})]);mParticle.Identity.logout(logoutUser);//only call is for `other` change event, not for previous ID types of email and customerid + client._calls.length.should.equal(1);var body4=JSON.parse(client.lastOptions().body);body4.mpid.should.equal('mpid2');var event4=body4.events[0];event4.should.be.ok();event4.event_type.should.equal('user_identity_change');event4.data["new"].identity_type.should.equal('other');event4.data["new"].identity.should.equal('other1');_typeof(event4.data["new"].timestamp_unixtime_ms).should.equal('number');event4.data["new"].created_this_batch.should.equal(true);event4.data.old.identity_type.should.equal('other');(event4.data.old.identity===null).should.equal(true);_typeof(event4.data.old.timestamp_unixtime_ms).should.equal('number');event4.data.old.created_this_batch.should.equal(false);mParticle.logEvent('testAfterLogout');var body5=JSON.parse(client.lastOptions().body);body5.mpid.should.equal('mpid2');Object.keys(body5.user_identities).length.should.equal(1);body5.user_identities.should.have.property('other','other1');done();});it('should send historical UIs on batches when MPID changes',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.identifyRequest={userIdentities:{email:'initial@gmail.com'}};window.mParticle.config.flags={EventBatchingIntervalMillis:0};mParticle.init(apiKey,window.mParticle.config);mockServer$6.respondWith(urls.login,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:true})]);// on identity strategy where MPID remains the same from anonymous to login + var loginUser={userIdentities:{customerid:'customerid1'}};mParticle.Identity.login(loginUser);var batch=JSON.parse(client.lastOptions().body);batch.mpid.should.equal(testMPID);batch.user_identities.should.have.property('email','initial@gmail.com');batch.user_identities.should.have.property('customer_id','customerid1');var logoutUser={userIdentities:{other:'other1'}};mockServer$6.respondWith(urls.logout,[200,{},JSON.stringify({mpid:'mpid2',is_logged_in:false})]);mParticle.Identity.logout(logoutUser);batch=JSON.parse(client.lastOptions().body);batch.mpid.should.equal('mpid2');batch.user_identities.should.have.property('other','other1');batch.user_identities.should.not.have.property('email');batch.user_identities.should.not.have.property('customer_id');client._calls=[];// log back in with previous MPID, but with only a single UI, all UIs should be on batch + mockServer$6.respondWith(urls.login,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:true})]);mParticle.Identity.login(loginUser);// switching back to logged in user shoudl not result in any UIC events + Should(client.lastOptions()).not.be.ok();mParticle.logEvent('event after logging back in');batch=JSON.parse(client.lastOptions().body);batch.mpid.should.equal(testMPID);batch.user_identities.should.have.property('email','initial@gmail.com');batch.user_identities.should.have.property('customer_id','customerid1');done();});it('should not send user attribute change requests when user attribute already set with same value with false values',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.flags={EventBatchingIntervalMillis:0};mParticle.init(apiKey,window.mParticle.config);// set a new attribute, age + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('age','25');var body1=JSON.parse(client.lastOptions().body);body1.user_attributes.should.have.property('age','25');var event1=body1.events[0];event1.should.be.ok();event1.event_type.should.equal('user_attribute_change');event1.data["new"].should.equal('25');(event1.data.old===null).should.equal(true);event1.data.user_attribute_name.should.equal('age');event1.data.deleted.should.equal(false);event1.data.is_new_attribute.should.equal(true);// test setting attributes with 'false' values (i.e false, 0 and '') + // check for UAC event for testFalse: fasle when set for first time + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testFalse',false);var body2=JSON.parse(client.lastOptions().body);body2.user_attributes.should.have.property('testFalse',false);var event2=body2.events[0];event2.should.be.ok();event2.event_type.should.equal('user_attribute_change');event2.data["new"].should.equal(false);(event2.data.old===null).should.equal(true);event2.data.user_attribute_name.should.equal('testFalse');event2.data.deleted.should.equal(false);event2.data.is_new_attribute.should.equal(true);// check for UAC event for testEmptyString: '' when set for first time + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString','');var body3=JSON.parse(client.lastOptions().body);body3.user_attributes.should.have.property('testEmptyString','');var event3=body3.events[0];event3.should.be.ok();event3.event_type.should.equal('user_attribute_change');event3.data["new"].should.equal('');(event3.data.old===null).should.equal(true);event3.data.user_attribute_name.should.equal('testEmptyString');event3.data.deleted.should.equal(false);event3.data.is_new_attribute.should.equal(true);// check for UAC event for testZero: 0 when set for first time + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testZero',0);var body4=JSON.parse(client.lastOptions().body);body4.user_attributes.should.have.property('testZero',0);var event4=body4.events[0];event4.should.be.ok();event4.event_type.should.equal('user_attribute_change');event4.data["new"].should.equal(0);(event4.data.old===null).should.equal(true);event4.data.user_attribute_name.should.equal('testZero');event4.data.deleted.should.equal(false);event4.data.is_new_attribute.should.equal(true);// confirm user attributes previously set already exist for user + var userAttributes=mParticle.Identity.getCurrentUser().getAllUserAttributes();userAttributes.should.have.property('age');userAttributes.should.have.property('testFalse');userAttributes.should.have.property('testEmptyString');userAttributes.should.have.property('testZero');// re-set all previous attributes with the same values + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('age','25');mParticle.Identity.getCurrentUser().setUserAttribute('testFalse',false);mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString','');mParticle.Identity.getCurrentUser().setUserAttribute('testZero',0);(client.lastOptions()===undefined).should.equal(true);(client._calls.length===0).should.equal(true);done();});it('should send user attribute change event when setting different falsey values',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.flags={EventBatchingIntervalMillis:0};mParticle.init(apiKey,window.mParticle.config);// set initial test attribute with 'falsey' value to 0 + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey',0);var body1=JSON.parse(client.lastOptions().body);body1.user_attributes.should.have.property('testFalsey',0);var event1=body1.events[0];event1.should.be.ok();event1.event_type.should.equal('user_attribute_change');event1.data["new"].should.equal(0);(event1.data.old===null).should.equal(true);event1.data.user_attribute_name.should.equal('testFalsey');event1.data.deleted.should.equal(false);event1.data.is_new_attribute.should.equal(true);// re-set same test attribute with 'falsey' value to '' + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey','');var body2=JSON.parse(client.lastOptions().body);body2.user_attributes.should.have.property('testFalsey','');var event2=body2.events[0];event2.should.be.ok();event2.event_type.should.equal('user_attribute_change');event2.data["new"].should.equal('');event2.data.old.should.equal(0);event2.data.user_attribute_name.should.equal('testFalsey');event2.data.deleted.should.equal(false);event2.data.is_new_attribute.should.equal(false);// re-set same test attribute with 'falsey' value to false + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey',false);var body3=JSON.parse(client.lastOptions().body);body3.user_attributes.should.have.property('testFalsey',false);var event3=body3.events[0];event3.should.be.ok();event3.event_type.should.equal('user_attribute_change');event3.data["new"].should.equal(false);event3.data.old.should.equal('');event3.data.user_attribute_name.should.equal('testFalsey');event3.data.deleted.should.equal(false);event3.data.is_new_attribute.should.equal(false);// re-set same test attribute with 'falsey' value to original value 0 + client._calls=[];mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey',0);var body4=JSON.parse(client.lastOptions().body);body4.user_attributes.should.have.property('testFalsey',0);var event4=body4.events[0];event4.should.be.ok();event4.event_type.should.equal('user_attribute_change');event4.data["new"].should.equal(0);event4.data.old.should.equal(false);event4.data.user_attribute_name.should.equal('testFalsey');event4.data.deleted.should.equal(false);event4.data.is_new_attribute.should.equal(false);done();});});var getLocalStorage=TestsCore.getLocalStorage,mParticleIOS=TestsCore.mParticleIOS,mParticleAndroid=TestsCore.mParticleAndroid,HTTPCodes=Constants.HTTPCodes;describe('native-sdk methods',function(){describe('Helper methods',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);delete window.mParticleAndroid_bridgeName_v2;delete window.webkit;delete window.mParticle.uiwebviewBridgeName;delete mParticle.requiredWebviewBridgeName;delete mParticle.minWebviewBridgeVersion;delete mParticle.isIOS;mParticle.init(apiKey,window.mParticle.config);mParticle.config={};window.mParticleAndroid=null;window.mParticle.isIOS=null;});after(function(){delete window.mParticleAndroid_bridgeName_v2;delete window.webkit;delete window.mParticle.uiwebviewBridgeName;delete mParticle.requiredWebviewBridgeName;delete mParticle.minWebviewBridgeVersion;delete mParticle.isIOS;});it('isBridgeV2Available returns false if no bridges exist on window',function(done){mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false);done();});it('isBridgeV2Available returns true if iOS bridge messageHandler bridge exists on window',function(done){mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false);window.webkit={messageHandlers:{mParticle_bridgeName_v2:{postMessage:null}}};mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true);delete window.webkit;done();});it('isBridgeV2Available returns true if iOS bridge nonMessageHandler bridge exists on window',function(done){mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false);window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true);delete window.webkit;done();});it('isBridgeV2Available returns true if Android bridge exists on window',function(done){mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false);window.mParticleAndroid_bridgeName_v2=new mParticleAndroid();mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true);delete window.mParticleAndroid_bridgeName_v2;done();});it('isWebviewEnabled returns true if there is no v2Bridge, and minWebviewBridgeVersion is 1, and v1 bridge is available',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=1;mParticle.config.isIOS=true;mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',window.mParticle.config.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is an Android bridge, minWebviewBridgeVersion is 2',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;mParticle.init(apiKey,window.mParticle.config);// window.mParticle.config.minWebviewBridgeVersion = 2; + window.mParticleAndroid_bridgeName_v2=new mParticleAndroid();mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',window.mParticle.config.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is an iOS bridge, minWebviewBridgeVersion is 2',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;window.webkit={messageHandlers:{mParticle_bridgeName_v2:{postMessage:null}}};mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',window.mParticle.config.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2',function(done){mParticle.minWebviewBridgeVersion=2;window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2',function(done){mParticle.minWebviewBridgeVersion=2;window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns false if there is a v1 Android bridge, and minWebviewBridgeVersion is 2',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;mParticle.init(apiKey,window.mParticle.config);window.mParticleAndroid=new mParticleAndroid();mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',window.mParticle.config.minWebviewBridgeVersion).should.equal(false);done();});it('isWebviewEnabled returns false if there is a v1 iOS bridge, and minWebviewBridgeVersion is 2',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;mParticle.init(apiKey,window.mParticle.config);mParticle.isIOS=true;mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',window.mParticle.config.minWebviewBridgeVersion).should.equal(false);delete mParticle.isIOS;done();});it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.mParticleAndroid_bridgeName_v2=new mParticleAndroid();mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.webkit={messageHandlers:{mParticle_bridgeName_v2:{postMessage:null}}};mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);delete mParticle.isIOS;done();});it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.mParticleAndroid_bridgeName_v2=new mParticleAndroid();mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.webkit={messageHandlers:{mParticle_bridgeName_v2:{postMessage:null}}};mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists',function(done){mParticle.minWebviewBridgeVersion=1;window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName',mParticle.minWebviewBridgeVersion).should.equal(true);done();});it('isWebviewEnabled returns false if there is an unmatched requiredWebviewBridgeName, even if bridge 1 exists and min version is 1',function(done){mParticle.minWebviewBridgeVersion=1;mParticle.requiredWebviewBridgeName='nonmatching';window.mParticle.uiwebviewBridgeName='mParticle_bridgeName_v2';mParticle.isIOS=true;mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled(mParticle.requiredWebviewBridgeName,mParticle.minWebviewBridgeVersion).should.equal(false);delete mParticle.isIOS;done();});});describe('bridge version 1',function(){beforeEach(function(){mParticle._resetForTests(MPConfig);window.mParticleAndroid=null;window.mParticle.isIOS=null;window.mParticleAndroid=new mParticleAndroid();window.mParticle.config.minWebviewBridgeVersion=1;mParticle.init(apiKey,window.mParticle.config);});it('should set mParitcle._Store.SDKConfig.isIOS to true when mParticle.isIOS is true',function(done){mParticle._resetForTests(MPConfig);mParticle.isIOS=true;mParticle.init(apiKey,window.mParticle.config);mParticle.getInstance()._Store.SDKConfig.isIOS.should.equal(true);done();});it('invoke setSessionAttributes of $src_key/$src_env of apikey/\'webview\' to the Android\'s on init if apiKey is available',function(done){mParticle._resetForTests(MPConfig);window.mParticleAndroid=new mParticleAndroid();window.mParticle.init(apiKey,window.mParticle.config);window.mParticleAndroid.sessionAttrData.length.should.equal(2);JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('key','$src_env');JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('value','webview');JSON.parse(window.mParticleAndroid.sessionAttrData[1]).should.have.property('key','$src_key');JSON.parse(window.mParticleAndroid.sessionAttrData[1]).should.have.property('value',apiKey);done();});it('invoke only setSessionAttributes of $src_key/$src_env if apikey is missing from webview',function(done){mParticle._resetForTests(MPConfig);window.mParticleAndroid=new mParticleAndroid();window.mParticle.init(null,window.mParticle.config);window.mParticleAndroid.sessionAttrData.length.should.equal(1);JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('key','$src_env');JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('value','webview');done();});it('should invoke setSessionAttributes on Android and pass through proper data',function(done){window.mParticleAndroid.resetSessionAttrData();mParticle.setSessionAttribute('key','value');window.mParticleAndroid.setSessionAttributeCalled.should.equal(true);window.mParticleAndroid.sessionAttrData[0].should.equal(JSON.stringify({key:'key',value:'value'}));done();});it('should invoke logEvent on Android and pass through proper event',function(done){mParticle.logEvent('testEvent');window.mParticleAndroid.logEventCalled.should.equal(true);_typeof(window.mParticleAndroid.event).should.equal('string');JSON.parse(window.mParticleAndroid.event).should.have.properties(['EventName','EventCategory','EventAttributes','EventDataType','OptOut']);done();});it('should invoke setAttribute on Android and pass through proper data',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');window.mParticleAndroid.setUserAttributeCalled.should.equal(true);window.mParticleAndroid.userAttrData[0].should.equal(JSON.stringify({key:'key',value:'value'}));window.mParticleAndroid.resetUserAttributes();done();});it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes',function(done){mParticle.Identity.getCurrentUser().setUserAttributes({gender:'male',age:21});window.mParticleAndroid.setUserAttributeCalled.should.equal(true);window.mParticleAndroid.userAttrData[0].should.equal(JSON.stringify({key:'gender',value:'male'}));window.mParticleAndroid.userAttrData[1].should.equal(JSON.stringify({key:'age',value:21}));done();});it('should invoke removeAttributes on native SDK',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');mParticle.Identity.getCurrentUser().removeUserAttribute('key');window.mParticleAndroid.setUserAttributeCalled.should.equal(true);window.mParticleAndroid.removeUserAttributeCalled.should.equal(true);done();});// TBD _ ask will/peter about add to cart array vs product? + it('should invoke native sdk method addToCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);var product2=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.add(product);window.mParticleAndroid.should.have.property('addToCartCalled',true);window.mParticleAndroid.addedToCartItem.should.equal(JSON.stringify([product]));window.mParticleAndroid.clearCart();mParticle.eCommerce.Cart.add([product,product2]);window.mParticleAndroid.addedToCartItem.should.equal(JSON.stringify([product,product2]));done();});it('should invoke native sdk method removeFromCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.add(product);mParticle.eCommerce.Cart.remove(product);window.mParticleAndroid.should.have.property('removeFromCartCalled',true);window.mParticleAndroid.removedFromCartItem.should.equal(JSON.stringify(product));done();});it('should invoke native sdk method clearCart',function(done){mParticle.eCommerce.Cart.clear();window.mParticleAndroid.should.have.property('clearCartCalled',true);done();});it('should not sync cookies when in a mobile web view for Android',function(done){var pixelSettings={name:'AdobeEventForwarder',moduleId:5,esId:24053,isDebug:true,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'http://www.yahoo.com',redirectUrl:''};mParticle.configurePixel(pixelSettings);mParticle.init(apiKey,window.mParticle.config);var data=getLocalStorage();Should(data).not.be.ok();done();});it('should send a JSON object to the native SDK\'s Identity methods',function(done){var result,identityAPIRequest={userIdentities:{customerid:'123',email:'test@gmail.com'}};var callback=function callback(resp){result=resp;};mParticle.Identity.login(identityAPIRequest,callback);result.body.should.equal('Login request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.logout(identityAPIRequest,callback);result.body.should.equal('Logout request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.modify(identityAPIRequest,callback);result.body.should.equal('Modify request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.identify(identityAPIRequest,callback);result.body.should.equal('Identify request sent to native sdk');result.httpCode.should.equal(-5);var JSONData=JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest));window.mParticleAndroid.loginData.should.equal(JSONData);window.mParticleAndroid.logoutData.should.equal(JSONData);window.mParticleAndroid.modifyData.should.equal(JSONData);done();});it('should send events via the mParticle.ready method ',function(done){mParticle.ready(function(){mParticle.logEvent('test');});window.mParticleAndroid.logEventCalled.should.equal(true);JSON.parse(window.mParticleAndroid.event).EventName.should.equal('test');done();});});describe('bridge version 2',function(){describe('android',function(){var mParticleAndroidV2Bridge;beforeEach(function(){window.mParticleAndroid=null;window.mParticle.isIOS=null;mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;window.mParticle.config.requiredWebviewBridgeName='bridgeName';window.mParticleAndroid_bridgeName_v2=new mParticleAndroid();mParticleAndroidV2Bridge=window.mParticleAndroid_bridgeName_v2;window.mParticle.init(apiKey,window.mParticle.config);mParticle.config={};});afterEach(function(){delete window.mParticle.config;delete window.mParticleAndroid_bridgeName_v2;});it('should invoke logEvent on Android and pass through proper event',function(done){mParticle.logEvent('testEvent');mParticleAndroidV2Bridge.logEventCalled.should.equal(true);_typeof(mParticleAndroidV2Bridge.event).should.equal('string');JSON.parse(mParticleAndroidV2Bridge.event).should.have.properties(['EventName','EventCategory','EventAttributes','EventDataType','OptOut']);done();});it('should invoke setAttribute on Android and pass through proper data',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true);mParticleAndroidV2Bridge.userAttrData[0].should.equal(JSON.stringify({key:'key',value:'value'}));mParticleAndroidV2Bridge.resetUserAttributes();done();});it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes',function(done){mParticle.Identity.getCurrentUser().setUserAttributes({gender:'male',age:21});mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true);mParticleAndroidV2Bridge.userAttrData[0].should.equal(JSON.stringify({key:'gender',value:'male'}));mParticleAndroidV2Bridge.userAttrData[1].should.equal(JSON.stringify({key:'age',value:21}));mParticleAndroidV2Bridge.resetUserAttributes();done();});it('should invoke removeAttributes on Android',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');mParticle.Identity.getCurrentUser().removeUserAttribute('key');mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true);mParticleAndroidV2Bridge.removeUserAttributeCalled.should.equal(true);done();});it('should invoke setSessionAttributes on Android and pass through proper data',function(done){mParticle.setSessionAttribute('key','value');mParticleAndroidV2Bridge.setSessionAttributeCalled.should.equal(true);mParticleAndroidV2Bridge.sessionAttrData[2].should.equal(JSON.stringify({key:'key',value:'value'}));done();});it('should invoke Android method addToCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);var product2=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.add(product);mParticleAndroidV2Bridge.should.have.property('addToCartCalled',true);mParticleAndroidV2Bridge.addedToCartItem.should.equal(JSON.stringify([product]));mParticleAndroidV2Bridge.clearCart();mParticle.eCommerce.Cart.add([product,product2]);mParticleAndroidV2Bridge.addedToCartItem.should.equal(JSON.stringify([product,product2]));done();});it('should invoke Android method removeFromCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.add(product);mParticle.eCommerce.Cart.remove(product);mParticleAndroidV2Bridge.should.have.property('removeFromCartCalled',true);mParticleAndroidV2Bridge.removedFromCartItem.should.equal(JSON.stringify(product));mParticleAndroidV2Bridge.should.have.property('removeFromCartCalled',true);done();});it('should invoke Android method clearCart',function(done){mParticle.eCommerce.Cart.clear();mParticleAndroidV2Bridge.should.have.property('clearCartCalled',true);done();});it('should not sync cookies when in a mobile web view for Android',function(done){var pixelSettings={name:'AdobeEventForwarder',moduleId:5,esId:24053,isDebug:true,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'http://www.yahoo.com',redirectUrl:''};mParticle.configurePixel(pixelSettings);var data=getLocalStorage();Should(data).not.be.ok();done();});it('should send a JSON object to the Android\'s Identity methods',function(done){var result,identityAPIRequest={userIdentities:{customerid:'123',email:'test@gmail.com'}};var callback=function callback(resp){result=resp;};mParticle.Identity.login(identityAPIRequest,callback);result.body.should.equal('Login request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.logout(identityAPIRequest,callback);result.body.should.equal('Logout request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.modify(identityAPIRequest,callback);result.body.should.equal('Modify request sent to native sdk');result.httpCode.should.equal(-5);result=null;mParticle.Identity.identify(identityAPIRequest,callback);result.body.should.equal('Identify request sent to native sdk');result.httpCode.should.equal(-5);var JSONData=JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest));mParticleAndroidV2Bridge.loginData.should.equal(JSONData);mParticleAndroidV2Bridge.logoutData.should.equal(JSONData);mParticleAndroidV2Bridge.modifyData.should.equal(JSONData);done();});it('should send a JSON object to the Android\'s Alias method',function(done){var callbackResult;var aliasRequest={destinationMpid:'101',sourceMpid:'202',startTime:300,endTime:400};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});mParticleAndroidV2Bridge.aliasUsers.should.equal('{"DestinationMpid":"101","SourceMpid":"202","StartUnixtimeMs":300,"EndUnixtimeMs":400}');callbackResult.httpCode.should.equal(HTTPCodes.nativeIdentityRequest);callbackResult.message.should.equal('Alias request sent to native sdk');done();});it('should send events via the mParticle.ready method ',function(done){mParticle.ready(function(){mParticle.logEvent('test');});mParticleAndroidV2Bridge.logEventCalled.should.equal(true);JSON.parse(mParticleAndroidV2Bridge.event).EventName.should.equal('test');done();});it('should send an event with a product list when calling logPurchase',function(done){var product=mParticle.eCommerce.createProduct('product1','sku',10,1);var product2=mParticle.eCommerce.createProduct('product2','sku',10,1);mParticle.eCommerce.Cart.add([product,product2]);var transactionAttributes=mParticle.eCommerce.createTransactionAttributes('TAid1','aff1','coupon',1798,10,5);var clearCartBoolean=true;var customAttributes={value:10};var customFlags={foo:'bar'};mParticleAndroidV2Bridge.data=[];mParticle.eCommerce.logPurchase(transactionAttributes,[product,product2],clearCartBoolean,customAttributes,customFlags);JSON.parse(mParticleAndroidV2Bridge.event).ProductAction.ProductList[0].Name.should.equal('product1');JSON.parse(mParticleAndroidV2Bridge.event).ProductAction.ProductList[1].Name.should.equal('product2');done();});it('should invoke upload on native SDK',function(done){mParticle.upload();mParticleAndroidV2Bridge.uploadCalled.should.equal(true);done();});});describe('iOS',function(){var mParticleIOSV2Bridge;beforeEach(function(){window.mParticleAndroid=null;window.mParticle.isIOS=null;mParticle._resetForTests(MPConfig);window.mParticle.config.minWebviewBridgeVersion=2;window.mParticle.config.requiredWebviewBridgeName='bridgeName';window.webkit={messageHandlers:{mParticle_bridgeName_v2:new mParticleIOS()}};mParticleIOSV2Bridge=window.webkit.messageHandlers.mParticle_bridgeName_v2;mParticle.enableWebviewBridge=true;window.mParticle.init(apiKey,window.mParticle.config);mParticle.config={};mParticleIOSV2Bridge.reset();});afterEach(function(){delete window.webkit;delete mParticle.requiredWebviewBridgeName;delete mParticle.enableWebviewBridge;});it('should invoke logEvent on iOS SDK and pass through proper event',function(done){mParticle.logEvent('testEvent');JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('logEvent');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.properties(['EventName','EventCategory','EventAttributes','EventDataType','OptOut']);done();});it('should invoke setAttribute on iOS SDK and pass through proper data',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key','key');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value','value');done();});it('should invoke setAttribute on iOS SDK and pass through proper data when invoking setUserAttributes',function(done){mParticle.Identity.getCurrentUser().setUserAttributes({gender:'male',age:21});JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key','gender');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value','male');JSON.parse(mParticleIOSV2Bridge.data[1]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[1]).path.should.equal('setUserAttribute');JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('key','age');JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('value',21);done();});it('should invoke removeAttributes on iOS SDK',function(done){mParticle.Identity.getCurrentUser().setUserAttribute('key','value');mParticle.Identity.getCurrentUser().removeUserAttribute('key');JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key','key');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value','value');JSON.parse(mParticleIOSV2Bridge.data[1]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[1]).path.should.equal('removeUserAttribute');JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('key','key');JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('value',null);done();});it('should invoke setSessionAttributes on ios SDK and pass through proper data',function(done){mParticle.setSessionAttribute('key','value');JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setSessionAttribute');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key','key');JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value','value');done();});it('should invoke ios sdk method addToCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);var product2=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.add(product);JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart');JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product]));mParticleIOSV2Bridge.reset();mParticle.eCommerce.Cart.add([product,product2]);JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart');JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product,product2]));done();});it('should invoke ios sdk method removeFromCart',function(done){var product=mParticle.eCommerce.createProduct('name','sku',10,1);mParticle.eCommerce.Cart.remove(product);JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('removeFromCart');JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify(product));done();});it('should invoke ios sdk method clearCart',function(done){mParticle.eCommerce.Cart.clear();JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('clearCart');done();});it('should not sync cookies when in a mobile web view',function(done){var pixelSettings={name:'AdobeEventForwarder',moduleId:5,esId:24053,isDebug:true,isProduction:true,settings:{},frequencyCap:14,pixelUrl:'http://www.yahoo.com',redirectUrl:''};mParticle.configurePixel(pixelSettings);var data=getLocalStorage();Should(data).not.be.ok();done();});it('should send a JSON object to the ios SDK\'s Identity methods',function(done){var result,identityAPIRequest={userIdentities:{customerid:'123',email:'test@gmail.com'}};var callback=function callback(resp){result=resp;};var JSONData=JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest));mParticle.Identity.login(identityAPIRequest,callback);result.body.should.equal('Login request sent to native sdk');result.httpCode.should.equal(-5);result=null;JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData);mParticleIOSV2Bridge.reset();mParticle.Identity.logout(identityAPIRequest,callback);result.body.should.equal('Logout request sent to native sdk');result.httpCode.should.equal(-5);result=null;JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData);mParticleIOSV2Bridge.reset();mParticle.Identity.modify(identityAPIRequest,callback);result.body.should.equal('Modify request sent to native sdk');result.httpCode.should.equal(-5);result=null;JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData);mParticleIOSV2Bridge.reset();mParticle.Identity.identify(identityAPIRequest,callback);result.body.should.equal('Identify request sent to native sdk');result.httpCode.should.equal(-5);JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData);mParticleIOSV2Bridge.reset();done();});it('should send a JSON object to the iOS SDK\'s Alias method',function(done){var callbackResult;var aliasRequest={destinationMpid:'101',sourceMpid:'202',startTime:300,endTime:400};mParticle.Identity.aliasUsers(aliasRequest,function(callback){callbackResult=callback;});JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('aliasUsers');JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal('{"DestinationMpid":"101","SourceMpid":"202","StartUnixtimeMs":300,"EndUnixtimeMs":400}');mParticleIOSV2Bridge.reset();callbackResult.httpCode.should.equal(HTTPCodes.nativeIdentityRequest);callbackResult.message.should.equal('Alias request sent to native sdk');done();});it('should send events via the mParticle.ready method ',function(done){mParticle.ready(function(){mParticle.logEvent('test');});JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('EventName','test');done();});it('should send an event with a product list when calling logPurchase',function(done){var product=mParticle.eCommerce.createProduct('product1','sku',10,1);var product2=mParticle.eCommerce.createProduct('product2','sku',10,1);mParticle.eCommerce.Cart.add([product,product2]);JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart');JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product,product2]));var transactionAttributes=mParticle.eCommerce.createTransactionAttributes('TAid1','aff1','coupon',1798,10,5);var clearCartBoolean=true;var customAttributes={value:10};var customFlags={foo:'bar'};mParticleIOSV2Bridge.data=[];mParticle.eCommerce.logPurchase(transactionAttributes,[product,product2],clearCartBoolean,customAttributes,customFlags);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('logEvent');JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList.length.should.equal(2);JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList[0].Name.should.equal('product1');JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList[1].Name.should.equal('product2');done();});it('should invoke upload on iOS SDK',function(done){mParticle.upload();JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path','value']);JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('upload');(JSON.parse(mParticleIOSV2Bridge.data[0]).value===null).should.equal(true);done();});});});});var BadBoolean=0;var BadNumberAsString=10;var BadStringBoolean='foo bar';var EmptyObjectAsPrivacyConsentState={};var EmptyStringAsPrivacyConsentState='';var findBatch$1=TestsCore.findBatch;var mockServer$5;var mParticle$4=window.mParticle;describe('Consent',function(){beforeEach(function(){client.post(urls.events,200);mockServer$5=sinon$1.createFakeServer();mockServer$5.respondImmediately=true;mockServer$5.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle$4.init(apiKey,window.mParticle.config);});afterEach(function(){mockServer$5.restore();client.restore();mParticle$4._resetForTests(MPConfig);});it('Should not create consent object without consented boolean',function(done){var consent=mParticle$4.Consent.createGDPRConsent(null);expect(consent===null).to.be.ok;consent=mParticle$4.Consent.createGDPRConsent(BadBoolean);consent=mParticle$4.Consent.createGDPRConsent(BadStringBoolean);expect(consent===null).to.be.ok;done();});it('Should create basic consent object with only consented boolean',function(done){var consent=mParticle$4.Consent.createGDPRConsent(true);expect(consent).to.be.ok;consent.Consented.should.equal(true);consent=mParticle$4.Consent.createGDPRConsent(false);expect(consent).to.be.ok;consent.Consented.should.equal(false);done();});it('Should not create consent object with invalid document',function(done){var badDocument=123;var consent=mParticle$4.getInstance().Consent.createGDPRConsent(true,123,badDocument);expect(consent===null).to.be.ok;done();});it('Should not create consent object with invalid location',function(done){var badLocation=123;var consent=mParticle$4.getInstance().Consent.createGDPRConsent(true,123,'foo document',badLocation);expect(consent===null).to.be.ok;done();});it('Should not create consent object with invalid hardware id',function(done){var badHardwareId=123;var consent=mParticle$4.getInstance().Consent.createGDPRConsent(true,123,'foo document','foo location',badHardwareId);expect(consent===null).to.be.ok;done();});it('Should set current timestamp if none given',function(done){var date=Date.now();var consent=mParticle$4.Consent.createGDPRConsent(true);expect(consent.Timestamp).to.be.greaterThanOrEqual(date);done();});it('Should create complete object',function(done){var consent=mParticle$4.getInstance().Consent.createGDPRConsent(true,10,'foo document','foo location','foo hardware id');expect(consent).to.be.ok;consent.should.have.property('Consented',true);consent.should.have.property('Timestamp',10);consent.should.have.property('ConsentDocument','foo document');consent.should.have.property('Location','foo location');consent.should.have.property('HardwareId','foo hardware id');done();});it('Should create basic ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;done();});it('Should add GDPR ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar',mParticle$4.Consent.createGDPRConsent(false));expect(consentState.getGDPRConsentState()).to.have.property('foo');// FIXME: getGDPRConsentState should return a dictionary of consent states + // rather than a consent state + expect(consentState.getGDPRConsentState().foo).to.have.property('Consented',true);// Test is verifying that attribute GDPR does not exist in ConsentState + // but this makes TypeScript mad. + expect(consentState.GDPR===undefined).to.be.ok;expect(consentState.getGDPRConsentState()).to.have.property('bar');expect(consentState.getGDPRConsentState().bar).to.have.property('Consented',false);done();});it('Should replace GDPR ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();var consentState2=mParticle$4.getInstance().Consent.createConsentState();consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true));consentState2.addGDPRConsentState('bar',mParticle$4.Consent.createGDPRConsent(false));consentState2.addGDPRConsentState('baz',mParticle$4.Consent.createGDPRConsent(false));consentState.getGDPRConsentState().should.have.property('foo');consentState2.getGDPRConsentState().should.have.property('bar');consentState2.getGDPRConsentState().should.have.property('baz');consentState.setGDPRConsentState(consentState2.getGDPRConsentState());consentState.getGDPRConsentState().should.not.have.property('foo');consentState.getGDPRConsentState().should.have.property('bar');consentState.getGDPRConsentState().should.have.property('baz');done();});it('should not be able to modify GDPR ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar',mParticle$4.Consent.createGDPRConsent(false));consentState.getGDPRConsentState().should.have.property('foo');delete consentState.getGDPRConsentState().foo;consentState.getGDPRConsentState().should.have.property('foo');done();});it('Should copy GDPR ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar',mParticle$4.Consent.createGDPRConsent(false));var consentState2=mParticle$4.getInstance().Consent.createConsentState(consentState);consentState2.addGDPRConsentState('baz',mParticle$4.Consent.createGDPRConsent(false));expect(consentState.getGDPRConsentState()).to.have.property('foo');expect(consentState.getGDPRConsentState().foo).to.have.property('Consented',true);consentState.getGDPRConsentState().should.have.property('bar');expect(consentState.getGDPRConsentState().bar).to.have.property('Consented',false);consentState.getGDPRConsentState().should.not.have.property('baz');consentState2.getGDPRConsentState().should.have.property('foo');expect(consentState2.getGDPRConsentState().foo).to.have.property('Consented',true);consentState2.getGDPRConsentState().should.have.property('bar');expect(consentState2.getGDPRConsentState().bar).to.have.property('Consented',false);consentState2.getGDPRConsentState().should.have.property('baz');expect(consentState2.getGDPRConsentState().baz).to.have.property('Consented',false);done();});it('Should remove GDPR ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar',mParticle$4.Consent.createGDPRConsent(false));consentState.getGDPRConsentState().should.have.property('foo');consentState.getGDPRConsentState().should.have.property('bar');consentState.removeGDPRConsentState('bar');consentState.getGDPRConsentState().should.not.have.property('bar');consentState.getGDPRConsentState().should.have.property('foo');done();});it('Should normalize GDPR consent purposes on add',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true,1)).addGDPRConsentState('bar ',mParticle$4.Consent.createGDPRConsent(true,2)).addGDPRConsentState('BAZ ',mParticle$4.Consent.createGDPRConsent(false,3)).addGDPRConsentState(' ',mParticle$4.Consent.createGDPRConsent(false,4));var gdprConsentState=consentState.getGDPRConsentState();expect(gdprConsentState).to.have.property('foo');expect(gdprConsentState).to.have.property('bar');expect(gdprConsentState).to.have.property('baz');expect(gdprConsentState).to.not.have.property(' ');expect(gdprConsentState.foo).to.have.property('Timestamp',1);expect(gdprConsentState).to.not.have.property('bar ');expect(gdprConsentState.bar).to.have.property('Timestamp',2);expect(gdprConsentState).to.not.have.property('BAZ ');expect(gdprConsentState.baz).to.have.property('Timestamp',3);done();});it('Should normalize GDPR consent purposes on remove',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true,1)).addGDPRConsentState('bar ',mParticle$4.Consent.createGDPRConsent(true,2)).addGDPRConsentState('BAZ ',mParticle$4.Consent.createGDPRConsent(false,3));var gdprConsentState=consentState.getGDPRConsentState();expect(gdprConsentState).to.have.property('foo');expect(gdprConsentState).to.have.property('bar');expect(gdprConsentState).to.have.property('baz');consentState.removeGDPRConsentState('FOO');consentState.removeGDPRConsentState('bAr ');consentState.removeGDPRConsentState(' bAz ');// Fetch an updated version of the consent state to verify attributes were removed + var gdprConsentStateUpdate=consentState.getGDPRConsentState();expect(gdprConsentStateUpdate).to.not.have.property('foo');expect(gdprConsentStateUpdate).to.not.have.property('bar');expect(gdprConsentStateUpdate).to.not.have.property('baz');done();});it('Should not set junk GDPR object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.addGDPRConsentState('foo',mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar',EmptyObjectAsPrivacyConsentState).addGDPRConsentState('baz',EmptyStringAsPrivacyConsentState).addGDPRConsentState(BadNumberAsString,EmptyObjectAsPrivacyConsentState);expect(consentState.getGDPRConsentState()).to.have.property('foo');expect(consentState.getGDPRConsentState()).to.not.have.property('bar');expect(consentState.getGDPRConsentState()).to.not.have.property('baz');expect(consentState.getGDPRConsentState()).to.not.have.property(10);done();});it('Should toJson/fromJson complete Consent State object',function(done){var consent1=mParticle$4.getInstance().Consent.createGDPRConsent(true,10,'foo document','foo location','foo hardware id');var consent2=mParticle$4.getInstance().Consent.createGDPRConsent(false,5,'foo document 2','foo location 2','foo hardware id 2');var consentState=mParticle$4.getInstance().Consent.createConsentState();consentState.addGDPRConsentState('foo',consent1);consentState.addGDPRConsentState('bar',consent2);var consentStateCopy=mParticle$4.getInstance()._Consent.ConsentSerialization.fromMinifiedJsonObject(mParticle$4.getInstance()._Consent.ConsentSerialization.toMinifiedJsonObject(consentState));consentStateCopy.getGDPRConsentState().should.have.property('foo');var consentCopy1=consentStateCopy.getGDPRConsentState().foo;consentCopy1.should.have.property('Consented',true);consentCopy1.should.have.property('Timestamp',10);consentCopy1.should.have.property('ConsentDocument','foo document');consentCopy1.should.have.property('Location','foo location');consentCopy1.should.have.property('HardwareId','foo hardware id');consentStateCopy.getGDPRConsentState().should.have.property('bar');var consentCopy2=consentStateCopy.getGDPRConsentState().bar;consentCopy2.should.have.property('Consented',false);consentCopy2.should.have.property('Timestamp',5);consentCopy2.should.have.property('ConsentDocument','foo document 2');consentCopy2.should.have.property('Location','foo location 2');consentCopy2.should.have.property('HardwareId','foo hardware id 2');done();});it('Should not create a CCPA consent object without consented boolean',function(done){var consent=mParticle$4.Consent.createCCPAConsent(null);expect(consent===null).to.be.ok;consent=mParticle$4.Consent.createCCPAConsent(BadBoolean);consent=mParticle$4.Consent.createCCPAConsent(BadStringBoolean);expect(consent===null).to.be.ok;done();});it('Should create basic consent object with only consented boolean',function(done){var consent=mParticle$4.Consent.createCCPAConsent(true);expect(consent).to.be.ok;consent.Consented.should.equal(true);consent=mParticle$4.Consent.createCCPAConsent(false);expect(consent).to.be.ok;consent.Consented.should.equal(false);done();});it('Should not create consent object with invalid document',function(done){var badDocument=123;var consent=mParticle$4.getInstance().Consent.createCCPAConsent(true,123,badDocument);expect(consent===null).to.be.ok;done();});it('Should not create consent object with invalid location',function(done){var badLocation=123;var consent=mParticle$4.getInstance().Consent.createCCPAConsent(true,123,'foo document',badLocation);expect(consent===null).to.be.ok;done();});it('Should not create consent object with invalid hardware id',function(done){var badHardwareId=123;var consent=mParticle$4.getInstance().Consent.createCCPAConsent(true,123,'foo document','foo location',badHardwareId);expect(consent===null).to.be.ok;done();});it('Should set current timestamp if none given',function(done){var date=Date.now();var consent=mParticle$4.Consent.createCCPAConsent(true);expect(consent.Timestamp).to.be.greaterThanOrEqual(date);done();});it('Should create complete CCPA consent object',function(done){var consent=mParticle$4.getInstance().Consent.createCCPAConsent(true,10,'foo document','foo location','foo hardware id');expect(consent).to.be.ok;consent.should.have.property('Consented',true);consent.should.have.property('Timestamp',10);consent.should.have.property('ConsentDocument','foo document');consent.should.have.property('Location','foo location');consent.should.have.property('HardwareId','foo hardware id');done();});it('Should set CCPA ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false));expect(consentState.getCCPAConsentState()).to.have.property('Consented');expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument');expect(consentState.getCCPAConsentState()).to.have.property('HardwareId');expect(consentState.getCCPAConsentState()).to.have.property('Location');expect(consentState.getCCPAConsentState()).to.have.property('Timestamp');done();});it('Should remove CCPA ConsentState object',function(done){var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false));expect(consentState.getCCPAConsentState()).to.have.property('Consented');expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument');expect(consentState.getCCPAConsentState()).to.have.property('HardwareId');expect(consentState.getCCPAConsentState()).to.have.property('Location');expect(consentState.getCCPAConsentState()).to.have.property('Timestamp');consentState.removeCCPAConsentState();expect(consentState.getCCPAConsentState()===undefined).to.equal(true);done();});it('should have CCPA in payload',function(done){var consentState=mParticle$4.Consent.createConsentState();var timestamp=new Date().getTime();var ccpaConsent=mParticle$4.Consent.createCCPAConsent(true,timestamp,'consentDoc','location','hardware');consentState.setCCPAConsentState(ccpaConsent);var user=mParticle$4.Identity.getCurrentUser();user.setConsentState(consentState);mParticle$4.logEvent('Test Event');var testEvent=findBatch$1(client._calls,'Test Event');testEvent.should.have.property('consent_state');testEvent.consent_state.should.have.property('ccpa');testEvent.consent_state.ccpa.should.have.property('data_sale_opt_out');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('consented',true);testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('timestamp_unixtime_ms',timestamp);testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('document','consentDoc');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('location','location');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('hardware_id','hardware');done();});it('should have CCPA and GDPR in payload',function(done){var consentState=mParticle$4.Consent.createConsentState();var timestamp=new Date().getTime();var ccpaConsent=mParticle$4.Consent.createCCPAConsent(true,timestamp,'consentDoc','location','hardware');var gdprConsent=mParticle$4.Consent.createGDPRConsent(false,timestamp,'consentDoc','location','hardware');consentState.setCCPAConsentState(ccpaConsent);consentState.addGDPRConsentState('test purpose',gdprConsent);var user=mParticle$4.Identity.getCurrentUser();user.setConsentState(consentState);mParticle$4.logEvent('Test Event');var testEvent=findBatch$1(client._calls,'Test Event');testEvent.should.have.property('consent_state');testEvent.consent_state.should.have.property('ccpa');testEvent.consent_state.ccpa.should.have.property('data_sale_opt_out');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('consented',true);testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('timestamp_unixtime_ms',timestamp);testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('document','consentDoc');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('location','location');testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('hardware_id','hardware');testEvent.consent_state.should.have.property('gdpr');testEvent.consent_state.gdpr.should.have.property('test purpose');testEvent.consent_state.gdpr['test purpose'].should.have.property('consented',false);testEvent.consent_state.gdpr['test purpose'].should.have.property('timestamp_unixtime_ms',timestamp);testEvent.consent_state.gdpr['test purpose'].should.have.property('document','consentDoc');testEvent.consent_state.gdpr['test purpose'].should.have.property('location','location');testEvent.consent_state.gdpr['test purpose'].should.have.property('hardware_id','hardware');done();});// TODO: Deprecate in next major version + it('Should log deprecated message when using removeCCPAState',function(done){var bond=sinon$1.spy(mParticle$4.getInstance().Logger,'warning');var consentState=mParticle$4.getInstance().Consent.createConsentState();expect(consentState).to.be.ok;consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false));expect(consentState.getCCPAConsentState()).to.have.property('Consented');expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument');expect(consentState.getCCPAConsentState()).to.have.property('HardwareId');expect(consentState.getCCPAConsentState()).to.have.property('Location');expect(consentState.getCCPAConsentState()).to.have.property('Timestamp');// FIXME: Remove when deprecating removeCCPAState + consentState.removeCCPAState();(consentState.getCCPAConsentState()===undefined).should.equal(true);bond.called.should.eql(true);bond.getCalls()[0].args[0].should.eql('removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead');done();});});var mockServer$4;var mParticle$3=window.mParticle;var ServerModel=mParticle$3.getInstance()._ServerModel;describe('ServerModel',function(){beforeEach(function(){});describe('#appendUserInfo',function(){it('should append User Identities and Attributes to event',function(){var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4'}};},getAllUserAttributes:function getAllUserAttributes(){return {'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return {gdpr:{'test-purpose':{consented:true,timestamp:11111,consent_document:'gdpr-doc',location:'test-gdpr-location',hardwareId:'test-gdpr-hardware'}},ccpa:{data_sale_opt_out:{consented:false,timestamp:22222,consent_document:'ccpa-doc',location:'test-ccpa-location',hardwareId:'test-ccpa-hardware'}}};}};// TODO: We should move some of the event samples into a reusable module + // or set up an event factory + var event={EventName:'Test Event',MPID:'',IsFirstRun:true,DeviceId:'test-device',EventCategory:0,SourceMessageId:'test-source-message-id',SDKVersion:'test-version',SessionId:'test-session-id',SessionStartDate:0,Timestamp:0,EventDataType:0,Debug:true,CurrencyCode:'USD'};ServerModel.appendUserInfo(user,event);expect(event.MPID).to.equal('98765');expect(event.ConsentState).to.eql({gdpr:{'test-purpose':{consented:true,timestamp:11111,consent_document:'gdpr-doc',location:'test-gdpr-location',hardwareId:'test-gdpr-hardware'}},ccpa:{data_sale_opt_out:{consented:false,timestamp:22222,consent_document:'ccpa-doc',location:'test-ccpa-location',hardwareId:'test-ccpa-hardware'}}});expect(event.UserAttributes).to.eql({'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']});expect(event.UserIdentities).to.eql([{Identity:'foo-other',Type:0},{Identity:'1234567',Type:1},{Identity:'foo-email',Type:7},{Identity:'foo-other2',Type:10},{Identity:'foo-other3',Type:11},{Identity:'foo-other4',Type:12}]);});it('sets User Attributes and Identities to null if user is empty',function(){var event={};ServerModel.appendUserInfo(null,event);expect(event.MPID).to.eql(null);expect(event.ConsentState).to.eql(null);expect(event.UserIdentities).to.eql(null);expect(event.UserAttributes).to.eql(null);});it('returns undefined if event is empty',function(){expect(ServerModel.appendUserInfo({},null)).to.be.undefined;});it('returns early if event MPID matches User MPID',function(){var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{}};},getAllUserAttributes:function getAllUserAttributes(){return null;},getMPID:function getMPID(){return '123456';},getConsentState:function getConsentState(){return null;}};var event={MPID:'123456'};ServerModel.appendUserInfo(user,event);expect(event.MPID).to.equal('123456');// Verify to make sure we didn't add anything unnecessary to the event + expect(Object.keys(event).length).to.equal(1);});it('updates event MPID with User MPID',function(){var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{}};},getAllUserAttributes:function getAllUserAttributes(){return null;},getMPID:function getMPID(){return '123456';},getConsentState:function getConsentState(){return null;}};var event={MPID:'555666777'};ServerModel.appendUserInfo(user,event);expect(event.MPID).to.equal('123456');});it('returns early if event and user are not valid',function(){expect(ServerModel.appendUserInfo(null,null)).to.be.undefined;});});describe('#convertToConsentStateDTO',function(){it('should convert Consent State with GDPR to a DTO',function(){var consentState={getGDPRConsentState:function getGDPRConsentState(){return {'test-gdpr-purpose':{Consented:true,Timestamp:12345,ConsentDocument:'gdpr-doc',Location:'test-gdpr-location',HardwareId:'test-gdpr-hardware-id'}};},getCCPAConsentState:function getCCPAConsentState(){}};var expectedDTO={gdpr:{'test-gdpr-purpose':{c:true,d:'gdpr-doc',h:'test-gdpr-hardware-id',l:'test-gdpr-location',ts:12345}}};expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO);});it('should convert Consent State with CCPA to a DTO',function(){var consentState={getGDPRConsentState:function getGDPRConsentState(){},getCCPAConsentState:function getCCPAConsentState(){return {Consented:false,Timestamp:67890,ConsentDocument:'ccpa-doc',Location:'test-ccpa-location',HardwareId:'test-ccpa-hardware-id'};}};var expectedDTO={ccpa:{data_sale_opt_out:{c:false,d:'ccpa-doc',h:'test-ccpa-hardware-id',l:'test-ccpa-location',ts:67890}}};expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO);});it('should convert Consent State with both GDPR and CCPA to a DTO',function(){var consentState={getGDPRConsentState:function getGDPRConsentState(){return {'test-gdpr-purpose':{Consented:true,Timestamp:12345,ConsentDocument:'gdpr-doc',Location:'test-gdpr-location',HardwareId:'test-gdpr-hardware-id'}};},getCCPAConsentState:function getCCPAConsentState(){return {Consented:false,Timestamp:67890,ConsentDocument:'ccpa-doc',Location:'test-ccpa-location',HardwareId:'test-ccpa-hardware-id'};}};var expectedDTO={gdpr:{'test-gdpr-purpose':{c:true,d:'gdpr-doc',h:'test-gdpr-hardware-id',l:'test-gdpr-location',ts:12345}},ccpa:{data_sale_opt_out:{c:false,d:'ccpa-doc',h:'test-ccpa-hardware-id',l:'test-ccpa-location',ts:67890}}};expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO);});it('returns null if Consent State is null',function(){expect(ServerModel.convertToConsentStateV2DTO(null)).to.eql(null);});});describe('#createEventObject',function(){beforeEach(function(){// TODO: Create Event Object is tightly coupled with mp Init and Store + // This should be refactored to make the function more pure + mockServer$4=sinon$1.createFakeServer();mockServer$4.respondImmediately=true;mockServer$4.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle$3.init(apiKey,mParticle$3.config);});afterEach(function(){mockServer$4.restore();});it('should create an event object without a user',function(){var mPStore=mParticle$3.getInstance()._Store;var event={name:'Test Event',messageType:Types.MessageType.PageEvent,eventType:Types.EventType.Navigation,data:{foo:'bar',bizz:'bazz'},sourceMessageId:'test-source-message-id',customFlags:{custom:'flag'},userAttributeChanges:{UserAttributeName:'$Age',New:'42',Old:'37',Deleted:false,IsNewAttribute:false},userIdentityChanges:{New:{IdentityType:Types.IdentityType.Other2,Identity:'new_identity',Timestamp:1668194307,CreatedThisBatch:false},Old:{IdentityType:Types.IdentityType.Other,Identity:'old_identity',Timestamp:1668193307,CreatedThisBatch:false}}};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject.EventName,'EventName').to.equal('Test Event');expect(actualEventObject.EventCategory,'EventCategory').to.equal(Types.EventType.Navigation);expect(actualEventObject.EventAttributes,'EventCategory').to.eql({foo:'bar',bizz:'bazz'});expect(actualEventObject.EventDataType,'EventDataType').to.equal(Types.MessageType.PageEvent);expect(actualEventObject.CustomFlags,'CustomFlags').to.eql({custom:'flag'});expect(actualEventObject.UserAttributeChanges,'UserAttributeChanges').to.eql({UserAttributeName:'$Age',New:'42',Old:'37',Deleted:false,IsNewAttribute:false});expect(actualEventObject.UserIdentityChanges,'UserrIdentityChanges').to.eql({New:{IdentityType:Types.IdentityType.Other2,Identity:'new_identity',Timestamp:1668194307,CreatedThisBatch:false},Old:{IdentityType:Types.IdentityType.Other,Identity:'old_identity',Timestamp:1668193307,CreatedThisBatch:false}});expect(actualEventObject.Store,'Store').to.eql({});expect(actualEventObject.SDKVersion,'SDKVersion').to.equal(Constants.sdkVersion);expect(actualEventObject.SessionId,'SessionId').to.equal(mPStore.sessionId);expect(actualEventObject.SessionStartDate,'SessionStartDate').to.equal(mPStore.sessionStartDate.getTime());expect(actualEventObject.Debug,'Debug').to.equal(false);expect(actualEventObject.Location,'Location').to.equal(null);expect(actualEventObject.OptOut,'OptOut').to.equal(null);expect(actualEventObject.ExpandedEventCount,'ExpandedEventCount').to.equal(0);expect(actualEventObject.AppVersion,'AppVersion').to.equal(undefined);expect(actualEventObject.AppName,'AppName').to.equal(undefined);expect(actualEventObject.Package,'Package').to.equal(undefined);expect(actualEventObject.ClientGeneratedId,'ClientGeneratedId').to.equal(mPStore.clientId);expect(actualEventObject.DeviceId,'DeviceId').to.equal(mPStore.deviceId);expect(actualEventObject.IntegrationAttributes,'IntegrationAttributes').to.eql({});// TODO: Should this default to USD? + expect(actualEventObject.CurrencyCode,'CurrencyCode').to.equal(null);expect(actualEventObject.DataPlan,'DataPlan').to.eql({});expect(actualEventObject.Timestamp,'Timestamp').to.equal(mPStore.dateLastEventSent.getTime());});it('should create an event object with a user',function(){var event={name:'Test Event',messageType:Types.MessageType.PageEvent,eventType:Types.EventType.Navigation,data:{foo:'bar',bizz:'bazz'},sourceMessageId:'test-source-message-id',customFlags:{custom:'flag'},userAttributeChanges:{UserAttributeName:'$Age',New:'42',Old:'37',Deleted:false,IsNewAttribute:false},userIdentityChanges:{New:{IdentityType:Types.IdentityType.Other2,Identity:'new_identity',Timestamp:1668194307,CreatedThisBatch:false},Old:{IdentityType:Types.IdentityType.Other,Identity:'old_identity',Timestamp:1668193307,CreatedThisBatch:false}}};var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4'}};},getAllUserAttributes:function getAllUserAttributes(){return {'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return {gdpr:{'test-purpose':{consented:true,timestamp:11111,consent_document:'gdpr-doc',location:'test-gdpr-location',hardwareId:'test-gdpr-hardware'}},ccpa:{data_sale_opt_out:{consented:false,timestamp:22222,consent_document:'ccpa-doc',location:'test-ccpa-location',hardwareId:'test-ccpa-hardware'}}};}};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event,user);expect(actualEventObject.MPID,'MPID').to.equal('98765');expect(actualEventObject.ConsentState,'ConsentState').to.eql({gdpr:{'test-purpose':{consented:true,timestamp:11111,consent_document:'gdpr-doc',location:'test-gdpr-location',hardwareId:'test-gdpr-hardware'}},ccpa:{data_sale_opt_out:{consented:false,timestamp:22222,consent_document:'ccpa-doc',location:'test-ccpa-location',hardwareId:'test-ccpa-hardware'}}});expect(actualEventObject.UserAttributes).to.eql({'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']});expect(actualEventObject.UserIdentities).to.eql([{Identity:'foo-other',Type:0},{Identity:'1234567',Type:1},{Identity:'foo-email',Type:7},{Identity:'foo-other2',Type:10},{Identity:'foo-other3',Type:11},{Identity:'foo-other4',Type:12}]);});it('should set necessary attributes if MessageType is SessionEnd',function(){var mPStore=mParticle$3.getInstance()._Store;mPStore.sessionAttributes={fooSessionAttr:'session-foo',barSessionAttr:'session-bar'};var event={name:'Test Event',messageType:Types.MessageType.SessionEnd,eventType:Types.EventType.Other,data:{fooEventAttr:'bar',barEventAttr:'bazz'}};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject.currentSessionMPIDs,'currentSessionMPIDs').to.eql(['testMPID']);// A SessionEnd event appends SessionLength + expect(actualEventObject).to.have.property('SessionLength');// A SessionEnd event should ignore Event Attributes and use Session Attributes instead + expect(actualEventObject.EventAttributes,'EventAttributes').to.eql({fooSessionAttr:'session-foo',barSessionAttr:'session-bar'});expect(actualEventObject.EventAttributes,'EventAttributes').to.not.have.property('fooEventAttr');expect(actualEventObject.EventAttributes,'EventAttributes').to.not.have.property('barEventAttr');// A SessionEnd event resets currentSessionMPIDs and sessionStartDate. When a new session starts, these are filled again + expect(mPStore.currentSessionMPIDs).to.eql([]);expect(mPStore.sessionStartDate).to.eql(null);});it('should set necessary attributes if MessageType is AppStateTransition',function(){var event={name:'Test Event',messageType:Types.MessageType.AppStateTransition,eventType:Types.EventType.Other};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject.IsFirstRun,'IsFirstRun').to.eql(false);expect(actualEventObject.LaunchReferral,'LaunchRefferral').to.eql(window.location.href);});it('should generate a sourceMessageId if one is not provided',function(){var event={name:'Test Event',sourceMessageId:null,messageType:Types.MessageType.CustomEvent,eventType:Types.EventType.Other};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject.SourceMessageId,'SourceMessageId').to.not.equal(null);});it('returns null if _Store does not have a sessionId',function(){var mPStore=mParticle$3.getInstance()._Store;mPStore.sessionId=null;var event={name:'Test Opt Out Event',messageType:Types.MessageType.CustomEvent};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject).to.equal(null);});it('returns null if _Store has Webview Bridge Disabled',function(){var mPStore=mParticle$3.getInstance()._Store;mPStore.sessionId=null;mPStore.webviewBridgeEnabled=false;var event={name:'Test Opt Out Event',messageType:Types.MessageType.CustomEvent};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject).to.equal(null);});it('returns null if event is invalid',function(){var event={};expect(ServerModel.createEventObject(event)).to.eql(null);});it('should support toEventAPIObject',function(){var eventAPIObject={EventName:'Test Event Object Override',EventCategory:Types.EventType.Media,EventDataType:Types.MessageType.Media};var event={name:'Test Event Object',messageType:Types.MessageType.PageEvent,eventType:Types.EventType.Other,toEventAPIObject:function toEventAPIObject(){return eventAPIObject;}};var actualEventObject=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(actualEventObject.EventName,'EventName').to.equal('Test Event Object Override');expect(actualEventObject.EventCategory,'EventCategory').to.equal(Types.EventType.Media);expect(actualEventObject.EventDataType,'EventDataType').to.equal(Types.MessageType.Media);});});describe('#convertEventToDTO',function(){it('should convert an event to a DTO',function(){var uploadObject={EventName:'test-name',EventCategory:Types.EventType.Navigation,EventAttributes:{},UserAttributes:{},UserIdentities:[],IntegrationAttributes:[],Store:{},SDKVersion:'1.2.3',SessionId:'test-session-id',SessionLength:33000,SessionStartDate:11111,EventDataType:Types.MessageType.PageEvent,Debug:true,Timestamp:22222,Location:{lat:123445,lng:323232},OptOut:false,AppVersion:'test-app.1235',ClientGeneratedId:'test-client-id',DeviceId:'test-device',MPID:'test-mpid',ExpandedEventCount:0,currentSessionMPIDs:['test-mpids']};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.n,'event.EventName (n)').to.equal('test-name');expect(actualDTO.et,'event.EventType (et)').to.equal(Types.EventType.Navigation);expect(actualDTO.ua,'event.UserAttributes (ua)').to.eql({});expect(actualDTO.ui,'event.UserIdentities (ui)').to.eql([]);expect(actualDTO.ia,'event.IntegrationAttributes (ia)').to.eql([]);expect(actualDTO.str,'event.Store (str)').to.eql({});expect(actualDTO.attrs,'event.EventAttributes (attrs)').to.eql({});expect(actualDTO.sdk,'event.SDKVersion (sdk)').to.equal('1.2.3');expect(actualDTO.sid,'event.SessionId (sid)').to.equal('test-session-id');expect(actualDTO.sl,'event.SessionLength (sl)').to.equal(33000);expect(actualDTO.ssd,'event.SessionStartDate (ssd)').to.equal(11111);expect(actualDTO.dt,'event.EventDataType (dt)').to.equal(Types.MessageType.PageEvent);expect(actualDTO.dbg,'event.Debug (dbg)').to.equal(true);expect(actualDTO.ct,'event.TimeStamp (ct)').to.equal(22222);expect(actualDTO.lc,'event.Location (lc)').to.eql({lat:123445,lng:323232});expect(actualDTO.o,'event.OptOut (o)').to.equal(false);expect(actualDTO.eec,'event.ExpandedEventCount (eec)').to.equal(0);expect(actualDTO.av,'event.AppVersion (av)').to.equal('test-app.1235');expect(actualDTO.cgid,'event.ClientGeneratedId (cgid)').to.equal('test-client-id');expect(actualDTO.das,'event.DeviceId (das)').to.equal('test-device');expect(actualDTO.mpid,'event.MPID (mpid)').to.equal('test-mpid');expect(actualDTO.smpids,'event.currentSessionMPIDs (smpids)').to.eql(['test-mpids']);});it('should add data plan id and version to DTO',function(){var uploadObject={DataPlan:{PlanId:'test-data-plan',PlanVersion:3}};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.dp_id,'event.DataPlan.PlanId (dp_id)').to.equal('test-data-plan');expect(actualDTO.dp_v,'event.DataPlan.PlanVersion (dp_v)').to.equal(3);});it('should add consent state to DTO',function(){var uploadObject={ConsentState:{getGDPRConsentState:function getGDPRConsentState(){return {'test-gdpr-purpose':{Consented:true,Timestamp:12345,ConsentDocument:'gdpr-doc',Location:'test-gdpr-location',HardwareId:'test-gdpr-hardware-id'}};},getCCPAConsentState:function getCCPAConsentState(){return {Consented:false,Timestamp:67890,ConsentDocument:'ccpa-doc',Location:'test-ccpa-location',HardwareId:'test-ccpa-hardware-id'};}}};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.con,'event.ConsentState (con)').to.eql({gdpr:{'test-gdpr-purpose':{c:true,d:'gdpr-doc',h:'test-gdpr-hardware-id',l:'test-gdpr-location',ts:12345}},ccpa:{data_sale_opt_out:{c:false,d:'ccpa-doc',h:'test-ccpa-hardware-id',l:'test-ccpa-location',ts:67890}}});});it('should add AST data to DTO',function(){var uploadObject={EventDataType:Types.MessageType.AppStateTransition,IsFirstRun:true,LaunchReferral:'https://mparticle.com/test-referral',EventAttributes:{foo:'bar'// TODO: test will nullify these + }};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.fr,'event.IsFirstRun (fr)').to.equal(true);expect(actualDTO.iu,'event.isUpgrade').to.equal(false);expect(actualDTO.at,'event.ApplicationTransitionType.AppInit (at)').to.equal(Types.ApplicationTransitionType.AppInit);expect(actualDTO.lr,'event.LaunchReferral (lr)').to.equal('https://mparticle.com/test-referral');expect(actualDTO.attrs,'event.EventAttributes (attrs)').to.eql(null);});it('should add custom flags to DTO',function(){var uploadObject={CustomFlags:{foo:'bar',fizz:['bizz','buzz',37,true],answer:42,isCustom:false}};var expectedFlags={foo:['bar'],fizz:['bizz','buzz','37','true'],answer:['42'],isCustom:['false']};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.flags).to.eql(expectedFlags);});it('should add shopping cart to DTO',function(){var uploadObject={CurrencyCode:'USD',EventDataType:Types.MessageType.Commerce,ShoppingCart:{ProductList:[{Sku:'SKU-12345',Name:'Some Item',Price:'42',Quantity:'3',Brand:'mParticle',Variant:'blue',Category:'product',Position:1,CouponCode:'FIDDY',TotalAmount:'41.50',Attributes:{foo:'bar',fizz:'bizz'}},{Sku:'SKU-67890',Name:'Some Other Item',Price:'37',Quantity:'5',Brand:'mParticle',Variant:'red',Category:'not-product',Position:2,CouponCode:'FIDDY',TotalAmount:'36.50',Attributes:{fizz:'buzz'}}]}};var expectedShoppingCart={pl:[{id:'SKU-12345',nm:'Some Item',pr:42,qt:3,br:'mParticle',va:'blue',ca:'product',ps:1,cc:'FIDDY',tpa:41.5,attrs:{foo:'bar',fizz:'bizz'}},{id:'SKU-67890',nm:'Some Other Item',pr:37,qt:5,br:'mParticle',va:'red',ca:'not-product',ps:2,cc:'FIDDY',tpa:36.5,attrs:{fizz:'buzz'}}]};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.cu).to.equal('USD');expect(actualDTO.sc).to.eql(expectedShoppingCart);});it('should add empty array to DTO if shopping cart is empty',function(){var uploadObject={CurrencyCode:'USD',EventDataType:Types.MessageType.Commerce,ShoppingCart:{}};var expectedShoppingCart={pl:[]};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.cu).to.equal('USD');expect(actualDTO.sc).to.eql(expectedShoppingCart);});it('should add product action to DTO',function(){var uploadObject={CurrencyCode:'USD',EventDataType:Types.MessageType.Commerce,ProductAction:{ProductActionType:Types.ProductActionType.AddToCart,CheckoutStep:42,CheckoutOptions:'test-checkout-option',TransactionId:'id',Affiliation:'affiliation',CouponCode:'couponCode',Revenue:'revenue',Shipping:'shipping',Tax:'tax',TotalAmount:'350.42',ShippingAmount:'40.42',TaxAmount:'3.50',ProductList:[{Sku:'SKU-12345',Name:'Some Item',Price:'42',Quantity:'3',Brand:'mParticle',Variant:'blue',Category:'product',Position:1,CouponCode:'FIDDY',TotalAmount:'41.50',Attributes:{foo:'bar',fizz:'bizz'}},{Sku:'SKU-67890',Name:'Some Other Item',Price:'37',Quantity:'5',Brand:'mParticle',Variant:'red',Category:'not-product',Position:2,CouponCode:'FIDDY',TotalAmount:'36.50',Attributes:{fizz:'buzz'}}]}};var expectedProducts=[{id:'SKU-12345',nm:'Some Item',pr:42,qt:3,br:'mParticle',va:'blue',ca:'product',ps:1,cc:'FIDDY',tpa:41.5,attrs:{foo:'bar',fizz:'bizz'}},{id:'SKU-67890',nm:'Some Other Item',pr:37,qt:5,br:'mParticle',va:'red',ca:'not-product',ps:2,cc:'FIDDY',tpa:36.5,attrs:{fizz:'buzz'}}];var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.cu).to.equal('USD');expect(actualDTO.pd.an,'ActionName').to.equal(Types.ProductActionType.AddToCart);expect(actualDTO.pd.cs,'CheckoutStep').to.equal(42);expect(actualDTO.pd.co,'CheckoutOptions').to.equal('test-checkout-option');expect(actualDTO.pd.ti,'TransactionId').to.equal('id');expect(actualDTO.pd.ta,'Affiliation').to.equal('affiliation');expect(actualDTO.pd.tcc,'CouponCode').to.equal('couponCode');expect(actualDTO.pd.tr,'TotalAmount').to.equal(350.42);expect(actualDTO.pd.ts,'ShippingAmount').to.equal(40.42);expect(actualDTO.pd.tt,'TaxAmount').to.equal(3.5);expect(actualDTO.pd.pl,'ProductList').to.eql(expectedProducts);});it('should add promotion action to DTO',function(){var uploadObject={CurrencyCode:'USD',EventDataType:Types.MessageType.Commerce,PromotionAction:{PromotionActionType:Types.PromotionActionType.PromotionView,PromotionList:[{Id:'12345',Name:'Some Item',Creative:'this-thing',Position:1},{Id:'67890',Name:'Some Other Item',Creative:'that-thing',Position:2}]}};var expectedPromotion=[{id:'12345',nm:'Some Item',cr:'this-thing',ps:1},{id:'67890',nm:'Some Other Item',cr:'that-thing',ps:2}];var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.cu).to.equal('USD');expect(actualDTO.pm.an,'ActionName').to.equal(Types.PromotionActionType.PromotionView);expect(actualDTO.pm.pl,'ProductList').to.eql(expectedPromotion);});it('should add product impression to DTO',function(){var uploadObject={CurrencyCode:'USD',EventDataType:Types.MessageType.Commerce,ProductImpressions:[{ProductImpressionList:'test-product-impression',ProductList:[{Sku:'SKU-12345',Name:'Some Item',Price:'42',Quantity:'3',Brand:'mParticle',Variant:'blue',Category:'product',Position:1,CouponCode:'FIDDY',TotalAmount:'41.50',Attributes:{foo:'bar',fizz:'bizz'}},{Sku:'SKU-67890',Name:'Some Other Item',Price:'37',Quantity:'5',Brand:'mParticle',Variant:'red',Category:'not-product',Position:2,CouponCode:'FIDDY',TotalAmount:'36.50',Attributes:{fizz:'buzz'}}]}]};var expectedProducts=[{id:'SKU-12345',nm:'Some Item',pr:42,qt:3,br:'mParticle',va:'blue',ca:'product',ps:1,cc:'FIDDY',tpa:41.5,attrs:{foo:'bar',fizz:'bizz'}},{id:'SKU-67890',nm:'Some Other Item',pr:37,qt:5,br:'mParticle',va:'red',ca:'not-product',ps:2,cc:'FIDDY',tpa:36.5,attrs:{fizz:'buzz'}}];var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.cu).to.equal('USD');expect(actualDTO.pi[0].pil,'ProductImpressionList').to.equal('test-product-impression');expect(actualDTO.pi[0].pl,'ProductList').to.eql(expectedProducts);});it('should add profile to DTO',function(){var uploadObject={EventDataType:Types.MessageType.Profile,ProfileMessageType:Types.ProfileMessageType.Logout};var actualDTO=ServerModel.convertEventToV2DTO(uploadObject);expect(actualDTO.pet).to.equal(Types.ProfileMessageType.Logout);});});describe('Integration Tests',function(){var event={messageType:Types.MessageType.PageEvent,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};beforeEach(function(){mockServer$4=sinon$1.createFakeServer();mockServer$4.respondImmediately=true;mockServer$4.respondWith(urls.identify,[200,{},JSON.stringify({mpid:testMPID,is_logged_in:false})]);mParticle$3.init(apiKey,mParticle$3.config);});afterEach(function(){mockServer$4.restore();});it('Should not convert data plan object to server DTO when no id or version is set',function(done){var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(event);var upload=window.mParticle.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent);upload.should.not.have.property('dp_id');upload.should.not.have.property('dp_v');done();});it('Should convert data plan id to server DTO',function(done){mParticle$3._resetForTests();mParticle$3.config.dataPlan={planId:'plan-slug'};mParticle$3.init('foo',mParticle$3.config);var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);var upload=mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent);upload.should.have.property('dp_id','plan-slug');upload.should.not.have.property('dp_v');done();});it('Should not convert data plan object to server DTO when no id is set',function(done){mParticle$3._resetForTests();mParticle$3.config.dataPlan={planVersion:5};mParticle$3.init('foo',mParticle$3.config);var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);var upload=mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent);upload.should.not.have.property('dp_id');upload.should.not.have.property('dp_v');done();});it('Should convert entire data plan object to server DTO',function(done){mParticle$3._resetForTests();mParticle$3.config.dataPlan={planId:'plan-slug',planVersion:10};mParticle$3.init('foo',mParticle$3.config);var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);var upload=mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent);upload.should.have.property('dp_id','plan-slug');upload.should.have.property('dp_v',10);done();});it('Should convert complete consent object',function(done){var consentState=mParticle$3.getInstance()._Consent.createConsentState();consentState.addGDPRConsentState('foo',mParticle$3.getInstance()._Consent.createPrivacyConsent(true,10,'foo document','foo location','foo hardware id'));// TODO: Resolve differences between SDKConsentState and ConsentState + // TODO: verify this tests passes + var consent=mParticle$3.getInstance()._ServerModel.convertToConsentStateV2DTO(consentState);expect(consent).to.be.ok;consent.should.have.property('gdpr');consent.gdpr.should.have.property('foo');consent.gdpr.foo.should.have.property('c',true);consent.gdpr.foo.should.have.property('ts',10);consent.gdpr.foo.should.have.property('d','foo document');consent.gdpr.foo.should.have.property('l','foo location');consent.gdpr.foo.should.have.property('h','foo hardware id');done();});it('Should not append user info when no user exists',function(done){mParticle$3.getInstance()._Store.should.be.ok;var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);sdkEvent.should.be.ok;expect(sdkEvent.UserIdentities).to.eql([]);expect(sdkEvent.UserAttributes).to.eql({});expect(sdkEvent.ConsentState===null).to.eql(true);done();});it('Should append all user info when user is present',function(done){mParticle$3.getInstance()._Store.should.be.ok;var consentState=mParticle$3.getInstance()._Consent.createConsentState();consentState.addGDPRConsentState('foo',mParticle$3.getInstance()._Consent.createPrivacyConsent(true,10,'foo document','foo location','foo hardware id'));var expectedUserIdentities=[{Identity:'foo-other',Type:0},{Identity:'1234567',Type:1},{Identity:'foo-email',Type:7},{Identity:'foo-other2',Type:10},{Identity:'foo-other3',Type:11},{Identity:'foo-other4',Type:12}];var expectedUserAttributes={'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};window.mParticle.getInstance().Identity.getCurrentUser=function(){return {getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4'}};},getAllUserAttributes:function getAllUserAttributes(){return {'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return consentState;}};};var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);expect(sdkEvent).to.be.ok;expect(sdkEvent.UserIdentities).to.eql(expectedUserIdentities);expect(sdkEvent.MPID).to.equal('98765');expect(sdkEvent.UserAttributes).to.eql(expectedUserAttributes);expect(sdkEvent.ConsentState).to.be.ok;done();});it('Should append identities when user is present',function(done){var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);sdkEvent.should.be.ok;expect(sdkEvent.UserIdentities).to.eql([]);var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4',not_a_valid_id:'foo'}};},getAllUserAttributes:function getAllUserAttributes(){return null;},getMPID:function getMPID(){return null;},getConsentState:function getConsentState(){return null;}};var identityMapping={};identityMapping[Types.IdentityType.CustomerId]='1234567';identityMapping[Types.IdentityType.Email]='foo-email';identityMapping[Types.IdentityType.Other]='foo-other';identityMapping[Types.IdentityType.Other2]='foo-other2';identityMapping[Types.IdentityType.Other3]='foo-other3';identityMapping[Types.IdentityType.Other4]='foo-other4';mParticle$3.getInstance()._ServerModel.appendUserInfo(user,sdkEvent);sdkEvent.UserIdentities.should.be.ok;sdkEvent.UserIdentities.length.should.equal(6);sdkEvent.UserIdentities.forEach(function(id){var type=id.Type;var value=id.Identity;identityMapping[type].should.equal(value);});done();});it('Should append user attributes when user present',function(done){var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);sdkEvent.should.be.ok;expect(sdkEvent.UserAttributes).to.eql({});var attributes={foo:'bar','foo-arr':['bar1','bar2']};var user={getUserIdentities:function getUserIdentities(){return {userIdentities:{}};},getAllUserAttributes:function getAllUserAttributes(){return attributes;},getMPID:function getMPID(){return null;},getConsentState:function getConsentState(){return null;}};mParticle$3.getInstance()._ServerModel.appendUserInfo(user,sdkEvent);expect(sdkEvent.UserAttributes).to.be.ok;expect(sdkEvent.UserAttributes).to.eql(attributes);done();});it('Should update mpid when user info is appended with a new mpid',function(done){var sdkEvent=mParticle$3.getInstance()._ServerModel.createEventObject(event);sdkEvent.should.be.ok;// By default, all tests instances have 'testMPID' + expect(sdkEvent.MPID).to.equal('testMPID');// TODO: this makes the compiler angry unless we make it hacky + var user={getUserIdentities:function getUserIdentities(){return {userIdentites:{}};},getAllUserAttributes:function getAllUserAttributes(){return null;},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return null;}};mParticle$3.getInstance()._ServerModel.appendUserInfo(user,sdkEvent);expect(sdkEvent.MPID).to.equal('98765');done();});it('convertEventToDTO should contain launch referral',function(done){var event={EventName:10,EventAttributes:null,SourceMessageId:'7efa0811-c716-4a1d-b8bf-dae90242849c',EventDataType:10,CustomFlags:{},IsFirstRun:false,LaunchReferral:'http://foo.bar/this/is/a/test',CurrencyCode:null,MPID:'testMPID',ConsentState:null,UserAttributes:{},UserIdentities:[],Store:{},SDKVersion:'2.14.0',SessionId:'43E9CB7B-A533-48A0-9D34-A9D51A4986F1',SessionStartDate:1630528189521,Debug:false,Location:null,OptOut:null,ExpandedEventCount:0,ClientGeneratedId:'abbaac60-6356-4cdb-88ab-ac63ffdc7b11',DeviceId:'f0164e59-ffe2-4c01-bd82-b1267096f8a1',IntegrationAttributes:{},DataPlan:{},Timestamp:1630528218899};var upload=mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(event);expect(upload.lr).to.equal('http://foo.bar/this/is/a/test');done();});});});describe('Create a batch from a base event',function(){var batchValidator=new _BatchValidator();var baseEvent={messageType:4,name:'testEvent'};it('creates a batch with base event ',function(done){var batch=batchValidator.returnBatch(baseEvent);expect(batch).to.have.property('environment').equal('production');expect(batch).to.have.property('source_request_id').equal('mockId');expect(batch).to.have.property('mpid').equal('0');expect(batch).to.have.property('timestamp_unixtime_ms');expect(batch).to.have.property('mp_deviceid');expect(batch).to.have.property('sdk_version');expect(batch).to.have.property('application_info');expect(batch).to.have.property('device_info');expect(batch).to.have.property('user_attributes');expect(batch).to.have.property('user_identities');expect(batch).to.have.property('consent_state');expect(batch).to.have.property('integration_attributes');expect(batch).to.have.property('events');expect(batch.events[0]).to.have.property('event_type','custom_event');expect(batch.events[0]).to.have.property('data');expect(batch.events[0].data).to.have.property('custom_event_type','unknown');expect(batch.events[0].data).to.have.property('custom_flags');expect(batch.events[0].data).to.have.property('event_name','testEvent');expect(batch.events[0].data).to.have.property('timestamp_unixtime_ms');expect(batch.events[0].data).to.have.property('session_uuid','mockSessionId');expect(batch.events[0].data).to.have.property('session_start_unixtime_ms');expect(batch.events[0].data).to.have.property('custom_attributes');expect(batch.events[0].data).to.have.property('location');baseEvent.eventType=1;batch=batchValidator.returnBatch(baseEvent);expect(batch.events[0].data).to.have.property('custom_event_type','navigation');baseEvent.data={attrFoo:'attrBar'};batch=batchValidator.returnBatch(baseEvent);expect(batch.events[0].data).to.have.property('custom_attributes');expect(batch.events[0].data.custom_attributes).to.have.property('attrFoo','attrBar');baseEvent.customFlags={flagFoo:'flagBar'};batch=batchValidator.returnBatch(baseEvent);expect(batch.events[0].data).to.have.property('custom_flags');expect(batch.events[0].data.custom_flags).to.have.property('flagFoo','flagBar');done();});});var forwarderDefaultConfiguration=TestsCore.forwarderDefaultConfiguration,MockForwarder=TestsCore.MockForwarder;var mockServer$3;describe('mParticleUser',function(){beforeEach(function(){// TODO - for some reason when these MPIDs are all testMPID, the following test breaks: + // onIdentifyComplete/onLoginComplete/onLogoutComplete/onModifyComplete + mockServer$3=sinon$1.createFakeServer();mockServer$3.respondImmediately=true;mockServer$3.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'testtest',is_logged_in:false})]);mockServer$3.respondWith(urls.login,[200,{},JSON.stringify({mpid:'testtest',is_logged_in:false})]);mockServer$3.respondWith(urls.logout,[200,{},JSON.stringify({mpid:'testtest',is_logged_in:false})]);mockServer$3.respondWith('https://identity.mparticle.com/v1/testtest/modify',[200,{},JSON.stringify({mpid:'testtest',is_logged_in:false})]);});afterEach(function(){mockServer$3.restore();});it('should call forwarder onUserIdentified method with a filtered user identity list',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration('MockForwarder',1);config1.userIdentityFilters=[4],window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);var userIdentityRequest={userIdentities:{google:'test',customerid:'id1',other:'id2'}};mParticle.Identity.login(userIdentityRequest);window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.not.have.property('google');window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.have.property('customerid','id1');window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.have.property('other','id2');done();});it('should call forwarder onUserIdentified method with a filtered user attributes list',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration('MockForwarder',1);config1.userAttributeFilters=[mParticle.generateHash('gender')];window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);var userIdentityRequest={userIdentities:{google:'test',customerid:'id1',other:'id2'}};mParticle.Identity.login(userIdentityRequest);mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.getCurrentUser().setUserAttribute('color','blue');mParticle.Identity.login(userIdentityRequest);window.MockForwarder1.instance.onUserIdentifiedUser.getAllUserAttributes().should.not.have.property('gender');window.MockForwarder1.instance.onUserIdentifiedUser.getAllUserAttributes().should.have.property('color','blue');done();});it('should call forwarder onIdentifyComplete/onLoginComplete/onLogoutComplete/onModifyComplete method with the proper identity method passed through',function(done){mParticle._resetForTests(MPConfig);var mockForwarder=new MockForwarder();mockForwarder.register(window.mParticle.config);var config1=forwarderDefaultConfiguration('MockForwarder',1);config1.userAttributeFilters=[mParticle.generateHash('gender')],window.mParticle.config.kitConfigs.push(config1);mParticle.init(apiKey,window.mParticle.config);var userIdentityRequest={userIdentities:{google:'test',customerid:'id1',other:'id2'}};mParticle.Identity.getCurrentUser().setUserAttribute('color','blue');mParticle.Identity.getCurrentUser().setUserAttribute('gender','male');mParticle.Identity.login(userIdentityRequest);window.MockForwarder1.instance.onLoginCompleteCalled.should.equal(true);window.MockForwarder1.instance.onLoginCompleteUser.getAllUserAttributes().should.not.have.property('gender');window.MockForwarder1.instance.onLoginCompleteUser.getAllUserAttributes().should.have.property('color','blue');mParticle.Identity.logout(userIdentityRequest);window.MockForwarder1.instance.onLogoutCompleteCalled.should.equal(true);window.MockForwarder1.instance.onLogoutCompleteUser.getAllUserAttributes().should.not.have.property('gender');window.MockForwarder1.instance.onLogoutCompleteUser.getAllUserAttributes().should.have.property('color','blue');mParticle.Identity.modify(userIdentityRequest);window.MockForwarder1.instance.onModifyCompleteCalled.should.equal(true);window.MockForwarder1.instance.onModifyCompleteUser.getAllUserAttributes().should.not.have.property('gender');window.MockForwarder1.instance.onModifyCompleteUser.getAllUserAttributes().should.have.property('color','blue');mParticle.Identity.identify(userIdentityRequest);window.MockForwarder1.instance.onIdentifyCompleteCalled.should.equal(true);window.MockForwarder1.instance.onIdentifyCompleteUser.getAllUserAttributes().should.not.have.property('gender');window.MockForwarder1.instance.onIdentifyCompleteUser.getAllUserAttributes().should.have.property('color','blue');done();});});var findEventFromRequest$1=TestsCore.findEventFromRequest,findBatch=TestsCore.findBatch;var mockServer$2;// Calls to /config are specific to only the self hosting environment + describe('/config self-hosting integration tests',function(){beforeEach(function(){client.post(urls.events,200);mockServer$2=sinon$1.createFakeServer();});afterEach(function(){client.restore();sinon$1.restore();});it('queues events in the eventQueue while /config is in flight, then processes them afterwards with correct MPID',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.requestConfig=true;window.mParticle.config.identifyRequest={userIdentities:{google:'google123'}};// start fake timer and mock server in order to mock when certain events happen + var clock=sinon$1.useFakeTimers();mockServer$2.autoRespond=true;mockServer$2.autoRespondAfter=100;mockServer$2.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'identifyMPID',is_logged_in:false})]);mockServer$2.respondWith(urls.config,[200,{},JSON.stringify({})]);mParticle.init(apiKey,window.mParticle.config);// log event before config and identify come back + mParticle.logEvent('Test');var event=findEventFromRequest$1(client._calls,'Test');Should(event).not.be.ok();// config and identify now get triggered, which runs through the event queue + clock.tick(300);event=findBatch(client._calls,'Test');event.should.be.ok();event.mpid.should.equal('identifyMPID');mockServer$2.restore();clock.restore();window.mParticle.config.requestConfig=false;done();});it('queued events contain login mpid instead of identify mpid when calling login immediately after mParticle initializes',function(done){var messages=[];mParticle._resetForTests(MPConfig);window.mParticle.config.requestConfig=true;window.mParticle.config.logLevel='verbose';delete window.mParticle.config.workspaceToken;mParticle.config.logger={verbose:function verbose(msg){messages.push(msg);}};window.mParticle.config.identifyRequest={userIdentities:{google:'google123'}};window.mParticle.config.identityCallback=function(){mParticle.logEvent('identify callback event');};// start fake timer and mock server + var clock=sinon$1.useFakeTimers();mockServer$2.autoRespond=true;mockServer$2.autoRespondAfter=100;mockServer$2.respondWith(urls.config,[200,{},JSON.stringify({workspaceToken:'workspaceTokenTest'})]);mockServer$2.respondWith(urls.identify,[200,{},JSON.stringify({mpid:'identifyMPID',is_logged_in:false})]);mockServer$2.respondWith(urls.login,[200,{},JSON.stringify({mpid:'loginMPID',is_logged_in:false})]);mParticle.init(apiKey,window.mParticle.config);// call login before mParticle.identify is triggered, which happens after config returns + mParticle.Identity.login({userIdentities:{customerid:'abc123'}});mParticle.logEvent('Test');// config triggers, login triggers immediately before identify + clock.tick(300);var event1=findBatch(client._calls,'Test');event1.mpid.should.equal('loginMPID');messages.indexOf('Parsing "login" identity response from server').should.be.above(0);// when login is in flight, identify will not run, but callback still will + messages.indexOf('Parsing "identify" identity response from server').should.equal(-1);var event2=findBatch(client._calls,'identify callback event',false,mockServer$2);event2.mpid.should.equal('loginMPID');mockServer$2.restore();clock.restore();localStorage.removeItem('mprtcl-v4_workspaceTokenTest');window.mParticle.config.requestConfig=false;done();});it('cookie name has workspace token in it in self hosting mode after config fetch',function(done){mParticle._resetForTests(MPConfig);window.mParticle.config.requestConfig=true;window.mParticle.config.logLevel='verbose';delete window.mParticle.config.workspaceToken;// start fake timer and mock server + var clock=sinon$1.useFakeTimers();mockServer$2.autoRespond=true;mockServer$2.autoRespondAfter=100;mockServer$2.respondWith(urls.config,[200,{},JSON.stringify({workspaceToken:'wtTest'})]);mParticle.init(apiKey,window.mParticle.config);clock.tick(300);var data=window.localStorage.getItem('mprtcl-v4_wtTest');(typeof data==='string').should.equal(true);mockServer$2.restore();clock.restore();window.mParticle.config.requestConfig=false;done();});});describe('Old model to batch model conversion',function(){beforeEach(function(){window.mParticle.init(apiKey,window.mParticle.config);});afterEach(function(){window.mParticle._resetForTests(MPConfig);});var batchDataTests=[{devmode:false},{devmode:true}];batchDataTests.forEach(function(params){it('Batch level conversion '+params,function(done){window.mParticle._resetForTests(MPConfig);window.mParticle.config.appVersion='a version';window.mParticle.config.appName='a name';window.mParticle.init(apiKey,window.mParticle.config);var batch=convertEvents(null,null,window.mParticle.getInstance());expect(batch).to.be["null"];batch=convertEvents(null,[],window.mParticle.getInstance());expect(batch).to.be["null"];window.mParticle.getInstance()._Store.sessionId='foo-session-id';window.mParticle.getInstance()._Store.isFirstRun=false;window.mParticle.getInstance()._Store.devToken='foo token';window.mParticle.getInstance()._Store.deviceId='a device id';window.mParticle.getInstance()._Store.SDKConfig.isDevelopmentMode=params.devmode;window.mParticle.getInstance().Identity.getCurrentUser=function(){return {getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4'}};},getAllUserAttributes:function getAllUserAttributes(){return {'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return null;}};};var publicEvent={messageType:Types.MessageType.PageEvent,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);console.log(sdkEvent);expect(sdkEvent).to.be.ok;batch=convertEvents('123',[sdkEvent,sdkEvent],window.mParticle.getInstance());expect(batch).to.be.ok;expect(batch.mpid).to.equal('123');expect(batch.environment).to.equal(params.devmode?'development':'production');expect(batch.application_info).to.be.ok;expect(batch.application_info.application_version).to.equal('a version');expect(batch.application_info.application_name).to.equal('a name');expect(batch.mp_deviceid).to.equal('a device id');expect(batch.user_attributes).to.be.ok;expect(batch.user_identities).to.be.ok;expect(batch.events).to.be.ok;expect(batch.events.length).to.equal(2);var batchEvent=batch.events[0];expect(batchEvent).to.be.ok;expect(batchEvent.data.event_name).to.equal('foo page');expect(batchEvent.data.custom_attributes).to.deep.equal({'foo-attr':'foo-val'});expect(batchEvent.data.custom_event_type).to.equal('navigation');expect(batchEvent.data.custom_flags).to.deep.equal({'foo-flag':'foo-flag-val'});expect(batchEvent.data.session_uuid).to.equal('foo-session-id');done();});});it('User attribute conversion ',function(done){window.mParticle.getInstance().Identity.getCurrentUser=function(){return {getUserIdentities:function getUserIdentities(){return {userIdentities:{}};},getAllUserAttributes:function getAllUserAttributes(){return {'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']};},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return null;}};};var publicEvent={messageType:Types.MessageType.PageEvent,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);expect(sdkEvent).to.be.ok;var batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.user_attributes).to.be.ok;expect(batch.user_attributes).to.deep.equal({'foo-user-attr':'foo-attr-value','foo-user-attr-list':['item1','item2']});done();});it('Data Plan Context conversion',function(done){var publicEvent={messageType:Types.MessageType.PageEvent,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation};var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);sdkEvent.DataPlan=null;var batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.undefined;sdkEvent.DataPlan={};batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.undefined;sdkEvent.DataPlan={PlanId:null};batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.undefined;sdkEvent.DataPlan={PlanId:null,PlanVersion:2};batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.undefined;sdkEvent.DataPlan={PlanId:"foo",PlanVersion:null};batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.ok;expect(batch.context.data_plan).to.be.ok;expect(batch.context.data_plan.plan_id).to.equal("foo");expect(batch.context.data_plan.plan_version).be.undefined;sdkEvent.DataPlan={PlanId:"foo",PlanVersion:4};batch=convertEvents('123',[sdkEvent],window.mParticle.getInstance());expect(batch.context).to.be.ok;expect(batch.context.data_plan).to.be.ok;expect(batch.context.data_plan.plan_id).to.equal("foo");expect(batch.context.data_plan.plan_version).be.equal(4);done();});it('User identity conversion ',function(done){window.mParticle.getInstance().Identity.getCurrentUser=function(){return {getUserIdentities:function getUserIdentities(){return {userIdentities:{customerid:'1234567',email:'foo-email',other:'foo-other',other2:'foo-other2',other3:'foo-other3',other4:'foo-other4'}};},getAllUserAttributes:function getAllUserAttributes(){return null;},getMPID:function getMPID(){return '98765';},getConsentState:function getConsentState(){return null;}};};var publicEvent={messageType:Types.MessageType.PageEvent,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);expect(sdkEvent).to.be.ok;var batch=convertEvents('123',[sdkEvent,sdkEvent],window.mParticle.getInstance());expect(batch.user_identities).to.be.ok;expect(batch.user_identities.customer_id).to.equal('1234567');expect(batch.user_identities.email).to.equal('foo-email');expect(batch.user_identities.other).to.equal('foo-other');expect(batch.user_identities.other_id_2).to.equal('foo-other2');expect(batch.user_identities.other_id_3).to.equal('foo-other3');expect(batch.user_identities.other_id_4).to.equal('foo-other4');done();});var baseEventConversion={1:dist.EventTypeEnum.sessionStart,2:dist.EventTypeEnum.sessionEnd,3:dist.EventTypeEnum.screenView,4:dist.EventTypeEnum.customEvent,5:dist.EventTypeEnum.crashReport,6:dist.EventTypeEnum.optOut,10:dist.EventTypeEnum.applicationStateTransition,16:dist.EventTypeEnum.commerceEvent};Object.keys(baseEventConversion).forEach(function(key){it('Base Event Conversion '+baseEventConversion[key],function(done){var event=convertEvent(null);expect(event).to.be["null"];var publicEvent={messageType:null,name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};var sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);event=convertEvent(sdkEvent);expect(event).to.be["null"];publicEvent={messageType:parseInt(key+'',10),name:'foo page',data:{'foo-attr':'foo-val'},eventType:Types.EventType.Navigation,customFlags:{'foo-flag':'foo-flag-val'}};sdkEvent=window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent);expect(sdkEvent).to.be.ok;event=convertEvent(sdkEvent);expect(event).to.be.ok;expect(event.event_type).to.equal(baseEventConversion[key]);done();});});it('Commerce Event Product Action convertion',function(done){var sdkEvent={EventName:'eCommerce - Purchase',EventCategory:16,EventAttributes:null,SDKVersion:'2.9.10',SourceMessageId:'testSMID',SessionId:'391D4CCE-E7F9-473E-B5CD-8566DEB17425',SessionStartDate:1569453582333,EventDataType:16,Debug:true,Location:null,OptOut:null,DeviceId:'47f10c9d-f962-4f8a-b92a-8add36f86078',CurrencyCode:null,MPID:'1053073459916128825',ConsentState:null,Timestamp:1569453613501,ProductAction:{ProductActionType:7,ProductList:[{Name:'item 1',Sku:'econ-1',Price:321,Quantity:1,Brand:'foo-brand',Variant:'foo-variant',Category:'foo-category',Position:1,CouponCode:'foo-coupon',TotalAmount:222,Attributes:{foo:'bar',foo2:'bar2'}},{Name:'item 2',Sku:'econ-2',Price:123,Quantity:2,Brand:'foo-brand',Variant:'foo-variant',Category:'foo-category',Position:2,CouponCode:'foo-coupon',TotalAmount:111,Attributes:{foo3:'bar3',foo4:'bar4'}}],TransactionId:'foo-transaction-id',TotalAmount:430.01,TaxAmount:31},IsFirstRun:false};var batch=convertEvents('1053073459916128825',[sdkEvent],window.mParticle.getInstance());expect(batch).to.be.ok;expect(batch.mpid).to.equal(sdkEvent.MPID);expect(batch.events.length).to.equal(1);var event=batch.events[0];expect(event).to.be.ok;expect(event.event_type).to.equal('commerce_event');expect(event.data.timestamp_unixtime_ms).to.equal(sdkEvent.Timestamp);expect(event.data.session_start_unixtime_ms).to.equal(sdkEvent.SessionStartDate);expect(event.data.product_action.action).to.equal('purchase');expect(event.data.product_action.products.length).to.equal(2);for(var i=0;i":"greater","|":"or","¢":"cent","£":"pound","¤":"currency","¥":"yen","©":"(c)","ª":"a","®":"(r)","º":"o","À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","Æ":"AE","Ç":"C","È":"E","É":"E","Ê":"E","Ë":"E","Ì":"I","Í":"I","Î":"I","Ï":"I","Ð":"D","Ñ":"N","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","Ù":"U","Ú":"U","Û":"U","Ü":"U","Ý":"Y","Þ":"TH","ß":"ss","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","æ":"ae","ç":"c","è":"e","é":"e","ê":"e","ë":"e","ì":"i","í":"i","î":"i","ï":"i","ð":"d","ñ":"n","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","ù":"u","ú":"u","û":"u","ü":"u","ý":"y","þ":"th","ÿ":"y","Ā":"A","ā":"a","Ă":"A","ă":"a","Ą":"A","ą":"a","Ć":"C","ć":"c","Č":"C","č":"c","Ď":"D","ď":"d","Đ":"DJ","đ":"dj","Ē":"E","ē":"e","Ė":"E","ė":"e","Ę":"e","ę":"e","Ě":"E","ě":"e","Ğ":"G","ğ":"g","Ģ":"G","ģ":"g","Ĩ":"I","ĩ":"i","Ī":"i","ī":"i","Į":"I","į":"i","İ":"I","ı":"i","Ķ":"k","ķ":"k","Ļ":"L","ļ":"l","Ľ":"L","ľ":"l","Ł":"L","ł":"l","Ń":"N","ń":"n","Ņ":"N","ņ":"n","Ň":"N","ň":"n","Ō":"O","ō":"o","Ő":"O","ő":"o","Œ":"OE","œ":"oe","Ŕ":"R","ŕ":"r","Ř":"R","ř":"r","Ś":"S","ś":"s","Ş":"S","ş":"s","Š":"S","š":"s","Ţ":"T","ţ":"t","Ť":"T","ť":"t","Ũ":"U","ũ":"u","Ū":"u","ū":"u","Ů":"U","ů":"u","Ű":"U","ű":"u","Ų":"U","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","ź":"z","Ż":"Z","ż":"z","Ž":"Z","ž":"z","Ə":"E","ƒ":"f","Ơ":"O","ơ":"o","Ư":"U","ư":"u","Lj":"LJ","lj":"lj","Nj":"NJ","nj":"nj","Ș":"S","ș":"s","Ț":"T","ț":"t","ə":"e","˚":"o","Ά":"A","Έ":"E","Ή":"H","Ί":"I","Ό":"O","Ύ":"Y","Ώ":"W","ΐ":"i","Α":"A","Β":"B","Γ":"G","Δ":"D","Ε":"E","Ζ":"Z","Η":"H","Θ":"8","Ι":"I","Κ":"K","Λ":"L","Μ":"M","Ν":"N","Ξ":"3","Ο":"O","Π":"P","Ρ":"R","Σ":"S","Τ":"T","Υ":"Y","Φ":"F","Χ":"X","Ψ":"PS","Ω":"W","Ϊ":"I","Ϋ":"Y","ά":"a","έ":"e","ή":"h","ί":"i","ΰ":"y","α":"a","β":"b","γ":"g","δ":"d","ε":"e","ζ":"z","η":"h","θ":"8","ι":"i","κ":"k","λ":"l","μ":"m","ν":"n","ξ":"3","ο":"o","π":"p","ρ":"r","ς":"s","σ":"s","τ":"t","υ":"y","φ":"f","χ":"x","ψ":"ps","ω":"w","ϊ":"i","ϋ":"y","ό":"o","ύ":"y","ώ":"w","Ё":"Yo","Ђ":"DJ","Є":"Ye","І":"I","Ї":"Yi","Ј":"J","Љ":"LJ","Њ":"NJ","Ћ":"C","Џ":"DZ","А":"A","Б":"B","В":"V","Г":"G","Д":"D","Е":"E","Ж":"Zh","З":"Z","И":"I","Й":"J","К":"K","Л":"L","М":"M","Н":"N","О":"O","П":"P","Р":"R","С":"S","Т":"T","У":"U","Ф":"F","Х":"H","Ц":"C","Ч":"Ch","Ш":"Sh","Щ":"Sh","Ъ":"U","Ы":"Y","Ь":"","Э":"E","Ю":"Yu","Я":"Ya","а":"a","б":"b","в":"v","г":"g","д":"d","е":"e","ж":"zh","з":"z","и":"i","й":"j","к":"k","л":"l","м":"m","н":"n","о":"o","п":"p","р":"r","с":"s","т":"t","у":"u","ф":"f","х":"h","ц":"c","ч":"ch","ш":"sh","щ":"sh","ъ":"u","ы":"y","ь":"","э":"e","ю":"yu","я":"ya","ё":"yo","ђ":"dj","є":"ye","і":"i","ї":"yi","ј":"j","љ":"lj","њ":"nj","ћ":"c","ѝ":"u","џ":"dz","Ґ":"G","ґ":"g","Ғ":"GH","ғ":"gh","Қ":"KH","қ":"kh","Ң":"NG","ң":"ng","Ү":"UE","ү":"ue","Ұ":"U","ұ":"u","Һ":"H","һ":"h","Ә":"AE","ә":"ae","Ө":"OE","ө":"oe","Ա":"A","Բ":"B","Գ":"G","Դ":"D","Ե":"E","Զ":"Z","Է":"E\'","Ը":"Y\'","Թ":"T\'","Ժ":"JH","Ի":"I","Լ":"L","Խ":"X","Ծ":"C\'","Կ":"K","Հ":"H","Ձ":"D\'","Ղ":"GH","Ճ":"TW","Մ":"M","Յ":"Y","Ն":"N","Շ":"SH","Չ":"CH","Պ":"P","Ջ":"J","Ռ":"R\'","Ս":"S","Վ":"V","Տ":"T","Ր":"R","Ց":"C","Փ":"P\'","Ք":"Q\'","Օ":"O\'\'","Ֆ":"F","և":"EV","ء":"a","آ":"aa","أ":"a","ؤ":"u","إ":"i","ئ":"e","ا":"a","ب":"b","ة":"h","ت":"t","ث":"th","ج":"j","ح":"h","خ":"kh","د":"d","ذ":"th","ر":"r","ز":"z","س":"s","ش":"sh","ص":"s","ض":"dh","ط":"t","ظ":"z","ع":"a","غ":"gh","ف":"f","ق":"q","ك":"k","ل":"l","م":"m","ن":"n","ه":"h","و":"w","ى":"a","ي":"y","ً":"an","ٌ":"on","ٍ":"en","َ":"a","ُ":"u","ِ":"e","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","پ":"p","چ":"ch","ژ":"zh","ک":"k","گ":"g","ی":"y","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","฿":"baht","ა":"a","ბ":"b","გ":"g","დ":"d","ე":"e","ვ":"v","ზ":"z","თ":"t","ი":"i","კ":"k","ლ":"l","მ":"m","ნ":"n","ო":"o","პ":"p","ჟ":"zh","რ":"r","ს":"s","ტ":"t","უ":"u","ფ":"f","ქ":"k","ღ":"gh","ყ":"q","შ":"sh","ჩ":"ch","ც":"ts","ძ":"dz","წ":"ts","ჭ":"ch","ხ":"kh","ჯ":"j","ჰ":"h","Ṣ":"S","ṣ":"s","Ẁ":"W","ẁ":"w","Ẃ":"W","ẃ":"w","Ẅ":"W","ẅ":"w","ẞ":"SS","Ạ":"A","ạ":"a","Ả":"A","ả":"a","Ấ":"A","ấ":"a","Ầ":"A","ầ":"a","Ẩ":"A","ẩ":"a","Ẫ":"A","ẫ":"a","Ậ":"A","ậ":"a","Ắ":"A","ắ":"a","Ằ":"A","ằ":"a","Ẳ":"A","ẳ":"a","Ẵ":"A","ẵ":"a","Ặ":"A","ặ":"a","Ẹ":"E","ẹ":"e","Ẻ":"E","ẻ":"e","Ẽ":"E","ẽ":"e","Ế":"E","ế":"e","Ề":"E","ề":"e","Ể":"E","ể":"e","Ễ":"E","ễ":"e","Ệ":"E","ệ":"e","Ỉ":"I","ỉ":"i","Ị":"I","ị":"i","Ọ":"O","ọ":"o","Ỏ":"O","ỏ":"o","Ố":"O","ố":"o","Ồ":"O","ồ":"o","Ổ":"O","ổ":"o","Ỗ":"O","ỗ":"o","Ộ":"O","ộ":"o","Ớ":"O","ớ":"o","Ờ":"O","ờ":"o","Ở":"O","ở":"o","Ỡ":"O","ỡ":"o","Ợ":"O","ợ":"o","Ụ":"U","ụ":"u","Ủ":"U","ủ":"u","Ứ":"U","ứ":"u","Ừ":"U","ừ":"u","Ử":"U","ử":"u","Ữ":"U","ữ":"u","Ự":"U","ự":"u","Ỳ":"Y","ỳ":"y","Ỵ":"Y","ỵ":"y","Ỷ":"Y","ỷ":"y","Ỹ":"Y","ỹ":"y","–":"-","‘":"\'","’":"\'","“":"\\\"","”":"\\\"","„":"\\\"","†":"+","•":"*","…":"...","₠":"ecu","₢":"cruzeiro","₣":"french franc","₤":"lira","₥":"mill","₦":"naira","₧":"peseta","₨":"rupee","₩":"won","₪":"new shequel","₫":"dong","€":"euro","₭":"kip","₮":"tugrik","₯":"drachma","₰":"penny","₱":"peso","₲":"guarani","₳":"austral","₴":"hryvnia","₵":"cedi","₸":"kazakhstani tenge","₹":"indian rupee","₺":"turkish lira","₽":"russian ruble","₿":"bitcoin","℠":"sm","™":"tm","∂":"d","∆":"delta","∑":"sum","∞":"infinity","♥":"love","元":"yuan","円":"yen","﷼":"rial","ﻵ":"laa","ﻷ":"laa","ﻹ":"lai","ﻻ":"la"}'); + var locales = JSON.parse('{"bg":{"Й":"Y","Ц":"Ts","Щ":"Sht","Ъ":"A","Ь":"Y","й":"y","ц":"ts","щ":"sht","ъ":"a","ь":"y"},"de":{"Ä":"AE","ä":"ae","Ö":"OE","ö":"oe","Ü":"UE","ü":"ue","ß":"ss","%":"prozent","&":"und","|":"oder","∑":"summe","∞":"unendlich","♥":"liebe"},"es":{"%":"por ciento","&":"y","<":"menor que",">":"mayor que","|":"o","¢":"centavos","£":"libras","¤":"moneda","₣":"francos","∑":"suma","∞":"infinito","♥":"amor"},"fr":{"%":"pourcent","&":"et","<":"plus petit",">":"plus grand","|":"ou","¢":"centime","£":"livre","¤":"devise","₣":"franc","∑":"somme","∞":"infini","♥":"amour"},"pt":{"%":"porcento","&":"e","<":"menor",">":"maior","|":"ou","¢":"centavo","∑":"soma","£":"libra","∞":"infinito","♥":"amor"},"uk":{"И":"Y","и":"y","Й":"Y","й":"y","Ц":"Ts","ц":"ts","Х":"Kh","х":"kh","Щ":"Shch","щ":"shch","Г":"H","г":"h"},"vi":{"Đ":"D","đ":"d"},"da":{"Ø":"OE","ø":"oe","Å":"AA","å":"aa","%":"procent","&":"og","|":"eller","$":"dollar","<":"mindre end",">":"større end"},"nb":{"&":"og","Å":"AA","Æ":"AE","Ø":"OE","å":"aa","æ":"ae","ø":"oe"},"it":{"&":"e"},"nl":{"&":"en"},"sv":{"&":"och","Å":"AA","Ä":"AE","Ö":"OE","å":"aa","ä":"ae","ö":"oe"}}'); + + function replace (string, options) { + if (typeof string !== 'string') { + throw new Error('slugify: string argument expected') + } + + options = (typeof options === 'string') + ? {replacement: options} + : options || {}; + + var locale = locales[options.locale] || {}; + + var replacement = options.replacement === undefined ? '-' : options.replacement; + + var trim = options.trim === undefined ? true : options.trim; + + var slug = string.normalize().split('') + // replace characters based on charMap + .reduce(function (result, ch) { + var appendChar = locale[ch]; + if (appendChar === undefined) appendChar = charMap[ch]; + if (appendChar === undefined) appendChar = ch; + if (appendChar === replacement) appendChar = ' '; + return result + appendChar + // remove not allowed characters + .replace(options.remove || /[^\w\s$*_+~.()'"!\-:@]+/g, '') + }, ''); + + if (options.strict) { + slug = slug.replace(/[^A-Za-z0-9\s]/g, ''); + } + + if (trim) { + slug = slug.trim(); + } + + // Replace spaces with replacement character, treating multiple consecutive + // spaces as a single space. + slug = slug.replace(/\s+/g, replacement); + + if (options.lower) { + slug = slug.toLowerCase(); + } + + return slug + } + + replace.extend = function (customMap) { + Object.assign(charMap, customMap); + }; + + return replace + })); + } (slugify$1, slugify$1.exports)); + + var slugifyExports = slugify$1.exports; + var slugify = /*@__PURE__*/getDefaultExportFromCjs(slugifyExports); + + var version = "2.23.4"; + + var Constants = { + sdkVersion: version, + sdkVendor: 'mparticle', + platform: 'web', + Messages: { + DeprecationMessages: { + MethodIsDeprecatedPostfix: 'is a deprecated method and will be removed in future releases', + AlternativeMethodPrefix: 'Please use the alternate method:' }, - - // fake promise - promise: promise, + ErrorMessages: { + NoToken: 'A token must be specified.', + EventNameInvalidType: 'Event name must be a valid string value.', + EventDataInvalidType: 'Event data must be a valid object hash.', + LoggingDisabled: 'Event logging is currently disabled.', + CookieParseError: 'Could not parse cookie', + EventEmpty: 'Event object is null or undefined, cancelling send', + APIRequestEmpty: 'APIRequest is null or undefined, cancelling send', + NoEventType: 'Event type must be specified.', + TransactionIdRequired: 'Transaction ID is required', + TransactionRequired: 'A transaction attributes object is required', + PromotionIdRequired: 'Promotion ID is required', + BadAttribute: 'Attribute value cannot be object or array', + BadKey: 'Key value cannot be object or array', + BadLogPurchase: 'Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions' + }, + InformationMessages: { + CookieSearch: 'Searching for cookie', + CookieFound: 'Cookie found, parsing values', + CookieNotFound: 'Cookies not found', + CookieSet: 'Setting cookie', + CookieSync: 'Performing cookie sync', + SendBegin: 'Starting to send event', + SendIdentityBegin: 'Starting to send event to identity server', + SendWindowsPhone: 'Sending event to Windows Phone container', + SendIOS: 'Calling iOS path: ', + SendAndroid: 'Calling Android JS interface method: ', + SendHttp: 'Sending event to mParticle HTTP service', + SendAliasHttp: 'Sending alias request to mParticle HTTP service', + SendIdentityHttp: 'Sending event to mParticle HTTP service', + StartingNewSession: 'Starting new Session', + StartingLogEvent: 'Starting to log event', + StartingLogOptOut: 'Starting to log user opt in/out', + StartingEndSession: 'Starting to end session', + StartingInitialization: 'Starting to initialize', + StartingLogCommerceEvent: 'Starting to log commerce event', + StartingAliasRequest: 'Starting to Alias MPIDs', + LoadingConfig: 'Loading configuration options', + AbandonLogEvent: 'Cannot log event, logging disabled or developer token not set', + AbandonAliasUsers: 'Cannot Alias Users, logging disabled or developer token not set', + AbandonStartSession: 'Cannot start session, logging disabled or developer token not set', + AbandonEndSession: 'Cannot end session, logging disabled or developer token not set', + NoSessionToEnd: 'Cannot end session, no active session found' + }, + ValidationMessages: { + ModifyIdentityRequestUserIdentitiesPresent: 'identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again', + IdentityRequesetInvalidKey: 'There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.', + OnUserAliasType: 'The onUserAlias value must be a function.', + UserIdentities: 'The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.', + UserIdentitiesInvalidKey: 'There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.', + UserIdentitiesInvalidValues: 'All user identity values must be strings or null. Request not sent to server. Please fix and try again.', + AliasMissingMpid: 'Alias Request must contain both a destinationMpid and a sourceMpid', + AliasNonUniqueMpid: "Alias Request's destinationMpid and sourceMpid must be unique", + AliasMissingTime: 'Alias Request must have both a startTime and an endTime', + AliasStartBeforeEndTime: "Alias Request's endTime must be later than its startTime" + } + }, + NativeSdkPaths: { + LogEvent: 'logEvent', + SetUserTag: 'setUserTag', + RemoveUserTag: 'removeUserTag', + SetUserAttribute: 'setUserAttribute', + RemoveUserAttribute: 'removeUserAttribute', + SetSessionAttribute: 'setSessionAttribute', + AddToCart: 'addToCart', + RemoveFromCart: 'removeFromCart', + ClearCart: 'clearCart', + LogOut: 'logOut', + SetUserAttributeList: 'setUserAttributeList', + RemoveAllUserAttributes: 'removeAllUserAttributes', + GetUserAttributesLists: 'getUserAttributesLists', + GetAllUserAttributes: 'getAllUserAttributes', + Identify: 'identify', + Logout: 'logout', + Login: 'login', + Modify: 'modify', + Alias: 'aliasUsers', + Upload: 'upload' + }, + StorageNames: { + localStorageName: 'mprtcl-api', + localStorageNameV3: 'mprtcl-v3', + cookieName: 'mprtcl-api', + cookieNameV2: 'mprtcl-v2', + cookieNameV3: 'mprtcl-v3', + localStorageNameV4: 'mprtcl-v4', + localStorageProductsV4: 'mprtcl-prodv4', + cookieNameV4: 'mprtcl-v4', + currentStorageName: 'mprtcl-v4', + currentStorageProductsName: 'mprtcl-prodv4' + }, + DefaultConfig: { + cookieDomain: null, + cookieExpiration: 365, + logLevel: null, + timeout: 300, + sessionTimeout: 30, + maxProducts: 20, + forwarderStatsTimeout: 5000, + integrationDelayTimeout: 5000, + maxCookieSize: 3000, + aliasMaxWindow: 90, + uploadInterval: 0 // Maximum milliseconds in between batch uploads, below 500 will mean immediate upload + }, + + DefaultUrls: { + v1SecureServiceUrl: 'jssdks.mparticle.com/v1/JS/', + v2SecureServiceUrl: 'jssdks.mparticle.com/v2/JS/', + v3SecureServiceUrl: 'jssdks.mparticle.com/v3/JS/', + configUrl: 'jssdkcdns.mparticle.com/JS/v2/', + identityUrl: 'identity.mparticle.com/v1/', + aliasUrl: 'jssdks.mparticle.com/v1/identity/' + }, + Base64CookieKeys: { + csm: 1, + sa: 1, + ss: 1, + ua: 1, + ui: 1, + csd: 1, + ia: 1, + con: 1 + }, + SDKv2NonMPIDCookieKeys: { + gs: 1, + cu: 1, + l: 1, + globalSettings: 1, + currentUserMPID: 1 + }, + HTTPCodes: { + noHttpCoverage: -1, + activeIdentityRequest: -2, + activeSession: -3, + validationIssue: -4, + nativeIdentityRequest: -5, + loggingDisabledOrMissingAPIKey: -6, + tooManyRequests: 429 + }, + FeatureFlags: { + ReportBatching: 'reportBatching', + EventBatchingIntervalMillis: 'eventBatchingIntervalMillis', + OfflineStorage: 'offlineStorage' + }, + DefaultInstance: 'default_instance', + CCPAPurpose: 'data_sale_opt_out' }; - const sandbox = new Sandbox(); - - const api = extend(sandbox, apiMethods); - - module.exports = api; - - },{"./sinon/assert":3,"./sinon/behavior":4,"./sinon/create-sandbox":7,"./sinon/mock-expectation":11,"./sinon/promise":13,"./sinon/restore-object":18,"./sinon/sandbox":19,"./sinon/stub":22,"./sinon/util/core/default-config":24,"./sinon/util/core/extend":26,"./sinon/util/fake-timers":41,"@sinonjs/samsam":88,"nise":128}],3:[function(require,module,exports){ - - const arrayProto = require("@sinonjs/commons").prototypes.array; - const calledInOrder = require("@sinonjs/commons").calledInOrder; - const createMatcher = require("@sinonjs/samsam").createMatcher; - const orderByFirstCall = require("@sinonjs/commons").orderByFirstCall; - const timesInWords = require("./util/core/times-in-words"); - const inspect = require("util").inspect; - const stringSlice = require("@sinonjs/commons").prototypes.string.slice; - const globalObject = require("@sinonjs/commons").global; - - const arraySlice = arrayProto.slice; - const concat = arrayProto.concat; - const forEach = arrayProto.forEach; - const join = arrayProto.join; - const splice = arrayProto.splice; - - function createAssertObject() { - const assert = { - failException: "AssertError", - - fail: function fail(message) { - const error = new Error(message); - error.name = this.failException || assert.failException; - - throw error; - }, - - pass: function pass() { - return; - }, - - callOrder: function assertCallOrder() { - verifyIsStub.apply(null, arguments); - let expected = ""; - let actual = ""; - - if (!calledInOrder(arguments)) { - try { - expected = join(arguments, ", "); - const calls = arraySlice(arguments); - let i = calls.length; - while (i) { - if (!calls[--i].called) { - splice(calls, i, 1); - } - } - actual = join(orderByFirstCall(calls), ", "); - } catch (e) { - // If this fails, we'll just fall back to the blank string - } - - failAssertion( - this, - `expected ${expected} to be called in order but were called as ${actual}` - ); - } else { - assert.pass("callOrder"); - } - }, - - callCount: function assertCallCount(method, count) { - verifyIsStub(method); - - let msg; - if (typeof count !== "number") { - msg = - `expected ${inspect(count)} to be a number ` + - `but was of type ${typeof count}`; - failAssertion(this, msg); - } else if (method.callCount !== count) { - msg = - `expected %n to be called ${timesInWords(count)} ` + - `but was called %c%C`; - failAssertion(this, method.printf(msg)); - } else { - assert.pass("callCount"); - } - }, - - expose: function expose(target, options) { - if (!target) { - throw new TypeError("target is null or undefined"); - } - - const o = options || {}; - const prefix = - (typeof o.prefix === "undefined" && "assert") || o.prefix; - const includeFail = - typeof o.includeFail === "undefined" || Boolean(o.includeFail); - const instance = this; + var createCookieString = function createCookieString(value) { + return replaceCommasWithPipes(replaceQuotesWithApostrophes(value)); + }; + var revertCookieString = function revertCookieString(value) { + return replacePipesWithCommas(replaceApostrophesWithQuotes(value)); + }; + var inArray = function inArray(items, name) { + var i = 0; + if (Array.prototype.indexOf) { + return items.indexOf(name, 0) >= 0; + } else { + for (var n = items.length; i < n; i++) { + if (i in items && items[i] === name) { + return true; + } + } + } + return false; + }; + var findKeyInObject = function findKeyInObject(obj, key) { + if (key && obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop) && prop.toLowerCase() === key.toLowerCase()) { + return prop; + } + } + } + return null; + }; + function generateHash(name) { + var hash = 0; + var character; + if (name === undefined || name === null) { + return 0; + } + name = name.toString().toLowerCase(); + if (Array.prototype.reduce) { + return name.split('').reduce(function (a, b) { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + } + if (name.length === 0) { + return hash; + } + for (var i = 0; i < name.length; i++) { + character = name.charCodeAt(i); + hash = (hash << 5) - hash + character; + hash = hash & hash; + } + return hash; + } + var generateRandomValue = function generateRandomValue(value) { + var randomValue; + var a; + if (window.crypto && window.crypto.getRandomValues) { + // @ts-ignore + randomValue = window.crypto.getRandomValues(new Uint8Array(1)); // eslint-disable-line no-undef + } - forEach(Object.keys(instance), function (method) { - if ( - method !== "expose" && - (includeFail || !/^(fail)/.test(method)) - ) { - target[exposedName(prefix, method)] = instance[method]; - } - }); + if (randomValue) { + // @ts-ignore + return (a ^ randomValue[0] % 16 >> a / 4).toString(16); + } + return (a ^ Math.random() * 16 >> a / 4).toString(16); + }; + var generateUniqueId = function generateUniqueId(a) { + // https://gist.github.com/jed/982883 + // Added support for crypto for better random + if (a === void 0) { + a = ''; + } + return a // if the placeholder was passed, return + ? generateRandomValue() // if the placeholder was passed, return + : + // [1e7] -> // 10000000 + + // -1e3 -> // -1000 + + // -4e3 -> // -4000 + + // -8e3 -> // -80000000 + + // -1e11 -> //-100000000000, + "".concat(1e7, "-").concat(1e3, "-").concat(4e3, "-").concat(8e3, "-").concat(1e11).replace(/[018]/g, + // zeroes, ones, and eights with + generateUniqueId // random hex digits + ); + }; + /** + * Returns a value between 1-100 inclusive. + */ + var getRampNumber = function getRampNumber(value) { + if (!value) { + return 100; + } + var hash = generateHash(value); + return Math.abs(hash % 100) + 1; + }; + var isObject = function isObject(value) { + var objType = Object.prototype.toString.call(value); + return objType === '[object Object]' || objType === '[object Error]'; + }; + var parseNumber = function parseNumber(value) { + if (isNaN(value) || !isFinite(value)) { + return 0; + } + var floatValue = parseFloat(value); + return isNaN(floatValue) ? 0 : floatValue; + }; + var parseStringOrNumber = function parseStringOrNumber(value) { + if (isStringOrNumber(value)) { + return value; + } else { + return null; + } + }; + var replaceCommasWithPipes = function replaceCommasWithPipes(value) { + return value.replace(/,/g, '|'); + }; + var replacePipesWithCommas = function replacePipesWithCommas(value) { + return value.replace(/\|/g, ','); + }; + var replaceApostrophesWithQuotes = function replaceApostrophesWithQuotes(value) { + return value.replace(/\'/g, '"'); + }; + var replaceQuotesWithApostrophes = function replaceQuotesWithApostrophes(value) { + return value.replace(/\"/g, "'"); + }; + // FIXME: REFACTOR for V3 + // only used in store.js to sanitize server-side formatting of + // booleans when checking for `isDevelopmentMode` + // Should be removed in v3 + var returnConvertedBoolean = function returnConvertedBoolean(data) { + if (data === 'false' || data === '0') { + return false; + } else { + return Boolean(data); + } + }; + var decoded$1 = function decoded(s) { + return decodeURIComponent(s.replace(/\+/g, ' ')); + }; + var converted$1 = function converted(s) { + if (s.indexOf('"') === 0) { + s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); + } + return s; + }; + var isString = function isString(value) { + return typeof value === 'string'; + }; + var isNumber = function isNumber(value) { + return typeof value === 'number'; + }; + var isFunction = function isFunction(fn) { + return typeof fn === 'function'; + }; + // TODO: Refactor this to a regex + var isDataPlanSlug = function isDataPlanSlug(str) { + return isString(str) && str === slugify(str); + }; + var isStringOrNumber = function isStringOrNumber(value) { + return isString(value) || isNumber(value); + }; + var isEmpty = function isEmpty(value) { + return value == null || !(Object.keys(value) || value).length; + }; - return target; + var pluses = /\+/g, + getLocalStorageProducts$3 = function getLocalStorageProducts() { + return JSON.parse(atob(localStorage.getItem(mParticle.getInstance()._Helpers.createProductStorageName(workspaceToken)))); + }, + decoded = function decoded(s) { + return decodeURIComponent(s.replace(pluses, ' ')); + }, + converted = function converted(s) { + if (s.indexOf('"') === 0) { + s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); + } + return s; + }, + getCookieDomain = function getCookieDomain() { + var rootDomain = getDomain(document, location.hostname); + if (rootDomain === '') { + return ''; + } else { + return '.' + rootDomain; + } + }, + getDomain = function getDomain(doc, locationHostname) { + var i, + testParts, + mpTest = 'mptest=cookie', + hostname = locationHostname.split('.'); + for (i = hostname.length - 1; i >= 0; i--) { + testParts = hostname.slice(i).join('.'); + doc.cookie = mpTest + ';domain=.' + testParts + ';'; + if (doc.cookie.indexOf(mpTest) > -1) { + doc.cookie = mpTest.split('=')[0] + '=;domain=.' + testParts + ';expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + return testParts; + } + } + return ''; + }, + findCookie$2 = function findCookie(cookieName) { + var cookie; + if (cookieName === v4CookieKey || !cookieName) { + cookie = mParticle.getInstance()._Persistence.getCookie(); + } else if (cookieName === v3CookieKey) { + cookie = JSON.parse(replacePipesWithCommas(findEncodedCookie(cookieName))); + } else { + cookie = JSON.parse(findEncodedCookie(cookieName)); + } + if (cookie) { + return cookie; + } else { + return null; + } + }, + findEncodedCookie = function findEncodedCookie(cookieName) { + var cookies = document.cookie.split('; '); + for (var i = 0, l = cookies.length; i < l; i++) { + var parts = cookies[i].split('='); + var name = decoded(parts.shift()); + var cookie = decoded(parts.join('=')); + if (cookieName === name) { + return replacePipesWithCommas(converted(cookie)); + } + } + }, + setCookie$2 = function setCookie(cname, data, raw) { + var date = new Date(), + expires = new Date(date.getTime() + 365 * 24 * 60 * 60 * 1000).toGMTString(), + domain, + cookieDomain, + value; + if (cname === v4CookieKey || cname === workspaceCookieName) { + value = replaceCommasWithPipes(data); + } else if (cname === v3CookieKey) { + value = data; + } else { + value = JSON.stringify(data); + } + if (raw) { + value = data; + } + cookieDomain = getCookieDomain(); + if (cookieDomain === '') { + domain = ''; + } else { + domain = ';domain=' + cookieDomain; + } + window.document.cookie = encodeURIComponent(cname) + '=' + value + ';expires=' + expires + ';path=/' + domain; + }, + setLocalStorage$5 = function setLocalStorage(name, data, raw) { + var value; + //if we just set setLocalStorage(), we put a valid full length LS into localStorage + if (arguments.length === 0) { + data = { + cu: testMPID, + gs: { + csm: btoa(JSON.stringify([testMPID])), + cgid: '606d4dbd-123f-4a9c-9729-d6b6f42db743', + das: das, + dt: apiKey, + ie: 1, + les: new Date().getTime(), + sid: '826ECC8F-9FCC-49C2-A3D3-4FC4F21D052C', + ssd: new Date().getTime() }, - - match: function match(actual, expectation) { - const matcher = createMatcher(expectation); - if (matcher.test(actual)) { - assert.pass("match"); + l: false, + testMPID: { + ua: btoa(JSON.stringify({ + color: 'blue' + })), + ui: btoa(JSON.stringify({ + 1: 'testuser@mparticle.com' + })), + csd: btoa(JSON.stringify({ + 5: 500 + })) + } + }; + value = createCookieString(JSON.stringify(data)); + name = workspaceCookieName; + } else { + if (name === v4LSKey) { + value = createCookieString(JSON.stringify(data)); + } + if (raw) { + value = data; + } + } + localStorage.setItem(encodeURIComponent(name), value); + }, + getLocalStorage$5 = function getLocalStorage(name) { + if (name === v4LSKey || !name) { + return mParticle.getInstance()._Persistence.getLocalStorage(); + } + }, + findEventFromBatch = function findEventFromBatch(batch, eventName) { + if (batch.events.length) { + return batch.events.find(function (event) { + switch (event.event_type) { + case 'commerce_event': + if (event.data.product_action) { + return event.data.product_action.action === eventName; + } else if (event.data.promotion_action) { + // return the promotion action + return true; } else { - const formatted = [ - "expected value to match", - ` expected = ${inspect(expectation)}`, - ` actual = ${inspect(actual)}`, - ]; - - failAssertion(this, join(formatted, "\n")); - } - }, - }; - - function verifyIsStub() { - const args = arraySlice(arguments); - - forEach(args, function (method) { - if (!method) { - assert.fail("fake is not a spy"); - } - - if (method.proxy && method.proxy.isSinonProxy) { - verifyIsStub(method.proxy); - } else { - if (typeof method !== "function") { - assert.fail(`${method} is not a function`); - } - - if (typeof method.getCall !== "function") { - assert.fail(`${method} is not stubbed`); - } + // all commerce_events that do not have product_action + // or promotion_action are impression actions + return true; } + case 'custom_event': + return event.data.event_name === eventName; + case 'crash_report': + return true; + default: + // all other events are lifecycle events (session start, end, AST) + return event.event_type === eventName; + } + }); + } + return null; + }, + getForwarderEvent$1 = function getForwarderEvent(requests, eventName) { + var url = "https://jssdks.mparticle.com/v2/JS/".concat(apiKey, "/Forwarding"); + var returnedReqs = []; + if (requests.length) { + requests.filter(function (request) { + return request.url === url; + }).forEach(function (request) { + JSON.parse(request.requestBody).data.forEach(function (internalRequest) { + if (internalRequest.n === eventName) { + returnedReqs.push(internalRequest); + } }); + }); } - - function verifyIsValidAssertion(assertionMethod, assertionArgs) { - switch (assertionMethod) { - case "notCalled": - case "called": - case "calledOnce": - case "calledTwice": - case "calledThrice": - if (assertionArgs.length !== 0) { - assert.fail( - `${assertionMethod} takes 1 argument but was called with ${ - assertionArgs.length + 1 - } arguments` - ); - } - break; + if (returnedReqs.length) { + return returnedReqs[0]; + } else { + return null; + } + }, + findRequest$1 = function findRequest(requests, eventName) { + var matchingRequest; + requests.forEach(function (request) { + var batch = JSON.parse(request[1].body); + for (var i = 0; i < batch.events.length; i++) { + var foundEventFromBatch = findEventFromBatch(batch, eventName); + if (foundEventFromBatch) { + matchingRequest = request; + break; } + } + }); + return matchingRequest; + }, + findRequestURL$1 = function findRequestURL(requests, eventName) { + return findRequest$1(requests, eventName)[0]; + }, + findBatch$7 = function findBatch(requests, eventName) { + var request = findRequest$1(requests, eventName); + if (request) { + return JSON.parse(findRequest$1(requests, eventName)[1].body); + } else { + return null; } - - function failAssertion(object, msg) { - const obj = object || globalObject; - const failMethod = obj.fail || assert.fail; - failMethod.call(obj, msg); + }, + findEventFromRequest$8 = function findEventFromRequest(requests, eventName) { + var batch = findBatch$7(requests, eventName); + if (batch) { + return findEventFromBatch(batch, eventName); + } else { + return null; + } + }, + getIdentityRequests = function getIdentityRequests(requests, path) { + var returnedRequests = [], + fullPath = 'https://identity.mparticle.com/v1/' + path; + if (path !== 'modify') { + requests.forEach(function (item) { + if (item.url === fullPath) { + returnedRequests.push(item); + } + }); + } else { + requests.forEach(function (item) { + if (item.url.slice(-6) === 'modify') { + returnedRequests.push(item); + } + }); + } + return returnedRequests; + }, + getIdentityEvent$2 = function getIdentityEvent(mockRequests, endpoint) { + var returnedReqs = getIdentityRequests(mockRequests, endpoint); + if (returnedReqs[0] && returnedReqs[0].requestBody) { + return JSON.parse(returnedReqs[0].requestBody); + } + }, + forwarderDefaultConfiguration$5 = function forwarderDefaultConfiguration(forwarderName, forwarderId, suffix) { + var config = { + name: forwarderName || 'MockForwarder', + suffix: suffix || null, + moduleId: forwarderId || 1, + isDebug: false, + isVisible: true, + isDebugString: 'false', + hasDebugString: 'false', + settings: {}, + screenNameFilters: [], + screenAttributeFilters: [], + userIdentityFilters: [], + userAttributeFilters: [], + eventNameFilters: [], + eventTypeFilters: [], + attributeFilters: [], + githubPath: null, + filteringEventAttributeValue: null, + filteringUserAttributeValue: null, + filteringConsentRuleValues: null, + consentRegulationFilters: [], + consentRegulationPurposeFilters: [], + messageTypeFilters: [], + messageTypeStateFilters: [], + eventSubscriptionId: 1234567890 + }; + return config; + }, + MockForwarder$7 = function MockForwarder(forwarderName, forwarderId, suffix) { + var constructor = function constructor() { + var self = this; + this.id = forwarderId || 1; + this.initCalled = false; + this.processCalled = false; + this.setUserIdentityCalled = false; + this.onUserIdentifiedCalled = false; + this.setOptOutCalled = false; + this.setUserAttributeCalled = false; + this.reportingService = null; + this.name = forwarderName || 'MockForwarder'; + this.userAttributeFilters = []; + this.removeUserAttributeCalled = false; + this.receivedEvent = null; + this.isVisible = false; + this.logOutCalled = false; + this.trackerId = null; + this.userAttributes = {}; + this.userIdentities = null; + this.appVersion = null; + this.appName = null; + this.logOut = function () { + this.logOutCalled = true; + }; + this.init = function (settings, reportingService, testMode, id, userAttributes, userIdentities, appVersion, appName) { + self.reportingService = reportingService; + self.initCalled = true; + self.trackerId = id; + self.userAttributes = userAttributes; + mParticle.userAttributesFilterOnInitTest = userAttributes; + mParticle.userIdentitiesFilterOnInitTest = userIdentities; + self.userIdentities = userIdentities; + self.appVersion = appVersion; + self.appName = appName; + self.settings = settings; + self.testMode = testMode; + }; + this.process = function (event) { + self.processCalled = true; + this.receivedEvent = event; + self.reportingService(self, event); + self.logger.verbose(event.EventName + ' sent'); + }; + this.setUserIdentity = function (a, b) { + this.userIdentities = {}; + this.userIdentities[b] = a; + self.setUserIdentityCalled = true; + }; + this.settings = { + PriorityValue: 1 + }; + this.setOptOut = function () { + this.setOptOutCalled = true; + }; + this.onUserIdentified = function (user) { + this.onUserIdentifiedCalled = true; + this.onUserIdentifiedUser = user; + }; + this.onIdentifyComplete = function (user) { + this.onIdentifyCompleteCalled = true; + this.onIdentifyCompleteUser = user; + }; + this.onLoginComplete = function (user) { + this.onLoginCompleteCalled = true; + this.onLoginCompleteUser = user; + }; + this.onLogoutComplete = function (user) { + this.onLogoutCompleteCalled = true; + this.onLogoutCompleteUser = user; + }; + this.onModifyComplete = function (user) { + this.onModifyCompleteCalled = true; + this.onModifyCompleteUser = user; + }; + this.setUserAttribute = function (key, value) { + this.setUserAttributeCalled = true; + this.userAttributes[key] = value; + }; + this.removeUserAttribute = function (key) { + this.removeUserAttributeCalled = true; + delete this.userAttributes[key]; + }; + window[this.name + this.id] = { + instance: this + }; + }; + this.name = forwarderName || 'MockForwarder'; + this.suffix = suffix || null; + this.moduleId = forwarderId || 1; + this.constructor = constructor; + function register(config) { + if (!config.kits) { + config.kits = {}; + } + config.kits[this.name] = { + constructor: constructor + }; + } + function getId() { + return forwarderId || 1; + } + return { + register: register, + getId: getId, + constructor: constructor, + name: this.name, + suffix: this.suffix + }; + }, + MockSideloadedKit$2 = MockForwarder$7, + mParticleAndroid$1 = function mParticleAndroid() { + var self = this; + this.addedToCartItem = null; + this.logEventCalled = false; + this.setUserAttributeCalled = false; + this.removeUserAttributeCalled = false; + this.setSessionAttributeCalled = false; + this.addToCartCalled = false; + this.removeFromCartCalled = false; + this.clearCartCalled = false; + this.loginData = null; + this.logoutData = null; + this.modifyData = null; + this.event = null; + this.userAttrData = []; + this.sessionAttrData = []; + this.aliasUsers = null; + this.uploadCalled = false; + this.resetSessionAttrData = function () { + self.sessionAttrData = []; + }; + this.login = function (data) { + self.loginData = data; + }; + this.logout = function (data) { + self.logoutData = data; + }; + this.modify = function (data) { + self.modifyData = data; + }; + this.identify = function (data) { + self.modifyData = data; + }; + this.logEvent = function (event) { + self.logEventCalled = true; + self.event = event; + }; + this.setUserIdentity = function () { + self.setUserIdentityCalled = true; + }; + this.removeUserIdentity = function () { + self.removeUserIdentityCalled = true; + }; + this.setUserTag = function () { + self.setUserTagCalled = true; + }; + this.removeUserTag = function () { + self.removeUserTagCalled = true; + }; + this.resetUserAttributes = function () { + self.userAttrData = []; + }; + this.setUserAttribute = function (data) { + self.setUserAttributeCalled = true; + self.userAttrData.push(data); + }; + this.removeUserAttribute = function () { + self.removeUserAttributeCalled = true; + }; + this.setSessionAttribute = function (data) { + self.setSessionAttributeCalled = true; + self.sessionAttrData.push(data); + }; + this.addToCart = function (item) { + self.addToCartCalled = true; + self.addedToCartItem = item; + }; + this.removeFromCart = function (item) { + self.removeFromCartCalled = true; + self.removedFromCartItem = item; + }; + this.clearCart = function () { + self.addedToCartItem = null; + self.clearCartCalled = true; + }; + this.aliasUsers = function (item) { + self.aliasUsers = item; + }; + this.upload = function () { + self.uploadCalled = true; + }; + }, + mParticleIOS$1 = function mParticleIOS() { + var self = this; + this.data = []; + this.postMessage = function (data) { + self.data.push(data); + }; + this.reset = function () { + self.data = []; + }; + }, + deleteAllCookies = function deleteAllCookies() { + var cookies = document.cookie.split(";"); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + var eqPos = cookie.indexOf("="); + var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; + document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT"; } + }; + var TestsCore = { + getLocalStorageProducts: getLocalStorageProducts$3, + findCookie: findCookie$2, + setCookie: setCookie$2, + setLocalStorage: setLocalStorage$5, + getLocalStorage: getLocalStorage$5, + findRequestURL: findRequestURL$1, + findBatch: findBatch$7, + findEventFromRequest: findEventFromRequest$8, + findEventFromBatch: findEventFromBatch, + getForwarderEvent: getForwarderEvent$1, + findRequest: findRequest$1, + getIdentityEvent: getIdentityEvent$2, + MockForwarder: MockForwarder$7, + MockSideloadedKit: MockSideloadedKit$2, + mParticleAndroid: mParticleAndroid$1, + mParticleIOS: mParticleIOS$1, + v4CookieKey: v4CookieKey, + v4LSKey: v4LSKey, + workspaceToken: workspaceToken, + workspaceCookieName: workspaceCookieName, + forwarderDefaultConfiguration: forwarderDefaultConfiguration$5, + deleteAllCookies: deleteAllCookies + }; - function mirrorPropAsAssertion(name, method, message) { - let msg = message; - let meth = method; - if (arguments.length === 2) { - msg = method; - meth = name; + function createSDKConfig(config) { + // TODO: Refactor to create a default config object + var sdkConfig = {}; + for (var prop in Constants.DefaultConfig) { + if (Constants.DefaultConfig.hasOwnProperty(prop)) { + sdkConfig[prop] = Constants.DefaultConfig[prop]; + } + } + if (config) { + for (var prop in config) { + if (config.hasOwnProperty(prop)) { + sdkConfig[prop] = config[prop]; + } + } + } + for (var prop in Constants.DefaultUrls) { + sdkConfig[prop] = Constants.DefaultUrls[prop]; + } + return sdkConfig; + } + // TODO: Merge this with SDKStoreApi in sdkRuntimeModels + function Store(config, mpInstance) { + var defaultStore = { + isEnabled: true, + sessionAttributes: {}, + currentSessionMPIDs: [], + consentState: null, + sessionId: null, + isFirstRun: null, + clientId: null, + deviceId: null, + devToken: null, + serverSettings: {}, + dateLastEventSent: null, + sessionStartDate: null, + currentPosition: null, + isTracking: false, + watchPositionId: null, + cartProducts: [], + eventQueue: [], + currencyCode: null, + globalTimer: null, + context: null, + configurationLoaded: false, + identityCallInFlight: false, + SDKConfig: {}, + nonCurrentUserMPIDs: {}, + identifyCalled: false, + isLoggedIn: false, + cookieSyncDates: {}, + integrationAttributes: {}, + requireDelay: true, + isLocalStorageAvailable: null, + storageName: null, + prodStorageName: null, + activeForwarders: [], + kits: {}, + sideloadedKits: [], + configuredForwarders: [], + pixelConfigurations: [], + wrapperSDKInfo: { + name: 'none', + version: null, + isInfoSet: false + } + }; + for (var key in defaultStore) { + this[key] = defaultStore[key]; + } + this.integrationDelayTimeoutStart = Date.now(); + this.SDKConfig = createSDKConfig(config); + // Set configuration to default settings + if (config) { + if (config.deviceId) { + this.deviceId = config.deviceId; + } + if (config.hasOwnProperty('isDevelopmentMode')) { + this.SDKConfig.isDevelopmentMode = mpInstance._Helpers.returnConvertedBoolean(config.isDevelopmentMode); + } else { + this.SDKConfig.isDevelopmentMode = false; + } + if (config.hasOwnProperty('v1SecureServiceUrl')) { + this.SDKConfig.v1SecureServiceUrl = config.v1SecureServiceUrl; + } + if (config.hasOwnProperty('v2SecureServiceUrl')) { + this.SDKConfig.v2SecureServiceUrl = config.v2SecureServiceUrl; + } + if (config.hasOwnProperty('v3SecureServiceUrl')) { + this.SDKConfig.v3SecureServiceUrl = config.v3SecureServiceUrl; + } + if (config.hasOwnProperty('identityUrl')) { + this.SDKConfig.identityUrl = config.identityUrl; + } + if (config.hasOwnProperty('aliasUrl')) { + this.SDKConfig.aliasUrl = config.aliasUrl; + } + if (config.hasOwnProperty('configUrl')) { + this.SDKConfig.configUrl = config.configUrl; + } + if (config.hasOwnProperty('logLevel')) { + this.SDKConfig.logLevel = config.logLevel; + } + this.SDKConfig.useNativeSdk = !!config.useNativeSdk; + this.SDKConfig.kits = config.kits || {}; + this.SDKConfig.sideloadedKits = config.sideloadedKits || []; + if (config.hasOwnProperty('isIOS')) { + this.SDKConfig.isIOS = config.isIOS; + } else { + this.SDKConfig.isIOS = window.mParticle && window.mParticle.isIOS ? window.mParticle.isIOS : false; + } + if (config.hasOwnProperty('useCookieStorage')) { + this.SDKConfig.useCookieStorage = config.useCookieStorage; + } else { + this.SDKConfig.useCookieStorage = false; + } + if (config.hasOwnProperty('maxProducts')) { + this.SDKConfig.maxProducts = config.maxProducts; + } else { + this.SDKConfig.maxProducts = Constants.DefaultConfig.maxProducts; + } + if (config.hasOwnProperty('maxCookieSize')) { + this.SDKConfig.maxCookieSize = config.maxCookieSize; + } else { + this.SDKConfig.maxCookieSize = Constants.DefaultConfig.maxCookieSize; + } + if (config.hasOwnProperty('appName')) { + this.SDKConfig.appName = config.appName; + } + if (config.hasOwnProperty('package')) { + this.SDKConfig["package"] = config["package"]; + } + if (config.hasOwnProperty('integrationDelayTimeout')) { + this.SDKConfig.integrationDelayTimeout = config.integrationDelayTimeout; + } else { + this.SDKConfig.integrationDelayTimeout = Constants.DefaultConfig.integrationDelayTimeout; + } + if (config.hasOwnProperty('identifyRequest')) { + this.SDKConfig.identifyRequest = config.identifyRequest; + } + if (config.hasOwnProperty('identityCallback')) { + var callback = config.identityCallback; + if (mpInstance._Helpers.Validators.isFunction(callback)) { + this.SDKConfig.identityCallback = config.identityCallback; + } else { + mpInstance.Logger.warning('The optional callback must be a function. You tried entering a(n) ' + _typeof(callback) + ' . Callback not set. Please set your callback again.'); + } + } + if (config.hasOwnProperty('appVersion')) { + this.SDKConfig.appVersion = config.appVersion; + } + if (config.hasOwnProperty('appName')) { + this.SDKConfig.appName = config.appName; + } + if (config.hasOwnProperty('sessionTimeout')) { + this.SDKConfig.sessionTimeout = config.sessionTimeout; + } + if (config.hasOwnProperty('dataPlan')) { + this.SDKConfig.dataPlan = { + PlanVersion: null, + PlanId: null + }; + var dataPlan = config.dataPlan; + if (dataPlan.planId) { + if (isDataPlanSlug(dataPlan.planId)) { + this.SDKConfig.dataPlan.PlanId = dataPlan.planId; + } else { + mpInstance.Logger.error('Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)'); } + } + if (dataPlan.planVersion) { + if (isNumber(dataPlan.planVersion)) { + this.SDKConfig.dataPlan.PlanVersion = dataPlan.planVersion; + } else { + mpInstance.Logger.error('Your data plan version must be a number'); + } + } + } else { + this.SDKConfig.dataPlan = {}; + } + if (config.hasOwnProperty('forceHttps')) { + this.SDKConfig.forceHttps = config.forceHttps; + } else { + this.SDKConfig.forceHttps = true; + } + // Some forwarders require custom flags on initialization, so allow them to be set using config object + this.SDKConfig.customFlags = config.customFlags || {}; + if (config.hasOwnProperty('minWebviewBridgeVersion')) { + this.SDKConfig.minWebviewBridgeVersion = config.minWebviewBridgeVersion; + } else { + this.SDKConfig.minWebviewBridgeVersion = 1; + } + if (config.hasOwnProperty('aliasMaxWindow')) { + this.SDKConfig.aliasMaxWindow = config.aliasMaxWindow; + } else { + this.SDKConfig.aliasMaxWindow = Constants.DefaultConfig.aliasMaxWindow; + } + if (config.hasOwnProperty('dataPlanOptions')) { + var dataPlanOptions = config.dataPlanOptions; + if (!dataPlanOptions.hasOwnProperty('dataPlanVersion') || !dataPlanOptions.hasOwnProperty('blockUserAttributes') || !dataPlanOptions.hasOwnProperty('blockEventAttributes') || !dataPlanOptions.hasOwnProperty('blockEvents') || !dataPlanOptions.hasOwnProperty('blockUserIdentities')) { + mpInstance.Logger.error('Ensure your config.dataPlanOptions object has the following keys: a "dataPlanVersion" object, and "blockUserAttributes", "blockEventAttributes", "blockEvents", "blockUserIdentities" booleans'); + } + } + if (config.hasOwnProperty('onCreateBatch')) { + if (typeof config.onCreateBatch === 'function') { + this.SDKConfig.onCreateBatch = config.onCreateBatch; + } else { + mpInstance.Logger.error('config.onCreateBatch must be a function'); + // set to undefined because all items are set on createSDKConfig + this.SDKConfig.onCreateBatch = undefined; + } + } + if (!config.hasOwnProperty('flags')) { + this.SDKConfig.flags = {}; + } + if (!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.EventBatchingIntervalMillis)) { + this.SDKConfig.flags[Constants.FeatureFlags.EventBatchingIntervalMillis] = Constants.DefaultConfig.uploadInterval; + } + if (!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.ReportBatching)) { + this.SDKConfig.flags[Constants.FeatureFlags.ReportBatching] = false; + } + if (!this.SDKConfig.flags.hasOwnProperty(Constants.FeatureFlags.OfflineStorage)) { + this.SDKConfig.flags[Constants.FeatureFlags.OfflineStorage] = 0; + } + } + } - assert[name] = function (fake) { - verifyIsStub(fake); + function commonjsRequire(path) { + throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); + } - const args = arraySlice(arguments, 1); - let failed = false; + var sinon$3 = {exports: {}}; + + /* Sinon.JS 16.1.0, 2023-10-05, @license BSD-3 */ + sinon$3.exports; + + (function (module, exports) { + (function(f){{module.exports=f();}})(function(){return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof commonjsRequire&&commonjsRequire;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t);}return n[i].exports}for(var u="function"==typeof commonjsRequire&&commonjsRequire,i=0;i= 0) { + return args[callArgAt]; + } + + let argumentList; + + if (callArgAt === useLeftMostCallback) { + argumentList = args; + } + + if (callArgAt === useRightMostCallback) { + argumentList = reverse(slice(args)); + } + + const callArgProp = behavior.callArgProp; + + for (let i = 0, l = argumentList.length; i < l; ++i) { + if (!callArgProp && typeof argumentList[i] === "function") { + return argumentList[i]; + } + + if ( + callArgProp && + argumentList[i] && + typeof argumentList[i][callArgProp] === "function" + ) { + return argumentList[i][callArgProp]; + } + } + + return null; + } + + function getCallbackError(behavior, func, args) { + if (behavior.callArgAt < 0) { + let msg; + + if (behavior.callArgProp) { + msg = `${functionName( + behavior.stub + )} expected to yield to '${valueToString( + behavior.callArgProp + )}', but no object with such a property was passed.`; + } else { + msg = `${functionName( + behavior.stub + )} expected to yield, but no callback was passed.`; + } + + if (args.length > 0) { + msg += ` Received [${join(args, ", ")}]`; + } + + return msg; + } + + return `argument at index ${behavior.callArgAt} is not a function: ${func}`; + } + + function ensureArgs(name, behavior, args) { + // map function name to internal property + // callsArg => callArgAt + const property = name.replace(/sArg/, "ArgAt"); + const index = behavior[property]; + + if (index >= args.length) { + throw new TypeError( + `${name} failed: ${index + 1} arguments required but only ${ + args.length + } present` + ); + } + } + + function callCallback(behavior, args) { + if (typeof behavior.callArgAt === "number") { + ensureArgs("callsArg", behavior, args); + const func = getCallback(behavior, args); + + if (typeof func !== "function") { + throw new TypeError(getCallbackError(behavior, func, args)); + } + + if (behavior.callbackAsync) { + nextTick(function () { + func.apply( + behavior.callbackContext, + behavior.callbackArguments + ); + }); + } else { + return func.apply( + behavior.callbackContext, + behavior.callbackArguments + ); + } + } + + return undefined; + } + + const proto = { + create: function create(stub) { + const behavior = extend({}, proto); + delete behavior.create; + delete behavior.addBehavior; + delete behavior.createBehavior; + behavior.stub = stub; + + if (stub.defaultBehavior && stub.defaultBehavior.promiseLibrary) { + behavior.promiseLibrary = stub.defaultBehavior.promiseLibrary; + } + + return behavior; + }, + + isPresent: function isPresent() { + return ( + typeof this.callArgAt === "number" || + this.exception || + this.exceptionCreator || + typeof this.returnArgAt === "number" || + this.returnThis || + typeof this.resolveArgAt === "number" || + this.resolveThis || + typeof this.throwArgAt === "number" || + this.fakeFn || + this.returnValueDefined + ); + }, + + /*eslint complexity: ["error", 20]*/ + invoke: function invoke(context, args) { + /* + * callCallback (conditionally) calls ensureArgs + * + * Note: callCallback intentionally happens before + * everything else and cannot be moved lower + */ + const returnValue = callCallback(this, args); + + if (this.exception) { + throw this.exception; + } else if (this.exceptionCreator) { + this.exception = this.exceptionCreator(); + this.exceptionCreator = undefined; + throw this.exception; + } else if (typeof this.returnArgAt === "number") { + ensureArgs("returnsArg", this, args); + return args[this.returnArgAt]; + } else if (this.returnThis) { + return context; + } else if (typeof this.throwArgAt === "number") { + ensureArgs("throwsArg", this, args); + throw args[this.throwArgAt]; + } else if (this.fakeFn) { + return this.fakeFn.apply(context, args); + } else if (typeof this.resolveArgAt === "number") { + ensureArgs("resolvesArg", this, args); + return (this.promiseLibrary || Promise).resolve( + args[this.resolveArgAt] + ); + } else if (this.resolveThis) { + return (this.promiseLibrary || Promise).resolve(context); + } else if (this.resolve) { + return (this.promiseLibrary || Promise).resolve(this.returnValue); + } else if (this.reject) { + return (this.promiseLibrary || Promise).reject(this.returnValue); + } else if (this.callsThrough) { + const wrappedMethod = this.effectiveWrappedMethod(); + + return wrappedMethod.apply(context, args); + } else if (this.callsThroughWithNew) { + // Get the original method (assumed to be a constructor in this case) + const WrappedClass = this.effectiveWrappedMethod(); + // Turn the arguments object into a normal array + const argsArray = slice(args); + // Call the constructor + const F = WrappedClass.bind.apply( + WrappedClass, + concat([null], argsArray) + ); + return new F(); + } else if (typeof this.returnValue !== "undefined") { + return this.returnValue; + } else if (typeof this.callArgAt === "number") { + return returnValue; + } + + return this.returnValue; + }, + + effectiveWrappedMethod: function effectiveWrappedMethod() { + for (let stubb = this.stub; stubb; stubb = stubb.parent) { + if (stubb.wrappedMethod) { + return stubb.wrappedMethod; + } + } + throw new Error("Unable to find wrapped method"); + }, + + onCall: function onCall(index) { + return this.stub.onCall(index); + }, + + onFirstCall: function onFirstCall() { + return this.stub.onFirstCall(); + }, + + onSecondCall: function onSecondCall() { + return this.stub.onSecondCall(); + }, + + onThirdCall: function onThirdCall() { + return this.stub.onThirdCall(); + }, + + withArgs: function withArgs(/* arguments */) { + throw new Error( + 'Defining a stub by invoking "stub.onCall(...).withArgs(...)" ' + + 'is not supported. Use "stub.withArgs(...).onCall(...)" ' + + "to define sequential behavior for calls with certain arguments." + ); + }, + }; + + function createBehavior(behaviorMethod) { + return function () { + this.defaultBehavior = this.defaultBehavior || proto.create(this); + this.defaultBehavior[behaviorMethod].apply( + this.defaultBehavior, + arguments + ); + return this; + }; + } + + function addBehavior(stub, name, fn) { + proto[name] = function () { + fn.apply(this, concat([this], slice(arguments))); + return this.stub || this; + }; + + stub[name] = createBehavior(name); + } + + proto.addBehavior = addBehavior; + proto.createBehavior = createBehavior; + + const asyncBehaviors = exportAsyncBehaviors(proto); + + module.exports = extend.nonEnum({}, proto, asyncBehaviors); + + },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/next-tick":33,"@sinonjs/commons":47}],4:[function(require,module,exports){ + + const walk = require("./util/core/walk"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const push = require("@sinonjs/commons").prototypes.array.push; + + function collectMethod(methods, object, prop, propOwner) { + if ( + typeof getPropertyDescriptor(propOwner, prop).value === "function" && + hasOwnProperty(object, prop) + ) { + push(methods, object[prop]); + } + } + + // This function returns an array of all the own methods on the passed object + function collectOwnMethods(object) { + const methods = []; + + walk(object, collectMethod.bind(null, methods, object)); + + return methods; + } + + module.exports = collectOwnMethods; + + },{"./util/core/get-property-descriptor":28,"./util/core/walk":38,"@sinonjs/commons":47}],5:[function(require,module,exports){ + + const supportsColor = require("supports-color"); + + function colorize(str, color) { + if (supportsColor.stdout === false) { + return str; + } + + return `\x1b[${color}m${str}\x1b[0m`; + } + + exports.red = function (str) { + return colorize(str, 31); + }; + + exports.green = function (str) { + return colorize(str, 32); + }; + + exports.cyan = function (str) { + return colorize(str, 96); + }; + + exports.white = function (str) { + return colorize(str, 39); + }; + + exports.bold = function (str) { + return colorize(str, 1); + }; + + },{"supports-color":149}],6:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const Sandbox = require("./sandbox"); + + const forEach = arrayProto.forEach; + const push = arrayProto.push; + + function prepareSandboxFromConfig(config) { + const sandbox = new Sandbox(); + + if (config.useFakeServer) { + if (typeof config.useFakeServer === "object") { + sandbox.serverPrototype = config.useFakeServer; + } + + sandbox.useFakeServer(); + } + + if (config.useFakeTimers) { + if (typeof config.useFakeTimers === "object") { + sandbox.useFakeTimers(config.useFakeTimers); + } else { + sandbox.useFakeTimers(); + } + } + + return sandbox; + } + + function exposeValue(sandbox, config, key, value) { + if (!value) { + return; + } + + if (config.injectInto && !(key in config.injectInto)) { + config.injectInto[key] = value; + push(sandbox.injectedKeys, key); + } else { + push(sandbox.args, value); + } + } + + function createSandbox(config) { + if (!config) { + return new Sandbox(); + } + + const configuredSandbox = prepareSandboxFromConfig(config); + configuredSandbox.args = configuredSandbox.args || []; + configuredSandbox.injectedKeys = []; + configuredSandbox.injectInto = config.injectInto; + const exposed = configuredSandbox.inject({}); + + if (config.properties) { + forEach(config.properties, function (prop) { + const value = + exposed[prop] || (prop === "sandbox" && configuredSandbox); + exposeValue(configuredSandbox, config, prop, value); + }); + } else { + exposeValue(configuredSandbox, config, "sandbox"); + } + + return configuredSandbox; + } + + module.exports = createSandbox; + + },{"./sandbox":18,"@sinonjs/commons":47}],7:[function(require,module,exports){ + + const stub = require("./stub"); + const sinonType = require("./util/core/sinon-type"); + const forEach = require("@sinonjs/commons").prototypes.array.forEach; + + function isStub(value) { + return sinonType.get(value) === "stub"; + } + + module.exports = function createStubInstance(constructor, overrides) { + if (typeof constructor !== "function") { + throw new TypeError("The constructor should be a function."); + } + + const stubInstance = Object.create(constructor.prototype); + sinonType.set(stubInstance, "stub-instance"); + + const stubbedObject = stub(stubInstance); + + forEach(Object.keys(overrides || {}), function (propertyName) { + if (propertyName in stubbedObject) { + const value = overrides[propertyName]; + if (isStub(value)) { + stubbedObject[propertyName] = value; + } else { + stubbedObject[propertyName].returns(value); + } + } else { + throw new Error( + `Cannot stub ${propertyName}. Property does not exist!` + ); + } + }); + return stubbedObject; + }; + + },{"./stub":21,"./util/core/sinon-type":34,"@sinonjs/commons":47}],8:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const isPropertyConfigurable = require("./util/core/is-property-configurable"); + const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); + const extend = require("./util/core/extend"); + + const slice = arrayProto.slice; + + const useLeftMostCallback = -1; + const useRightMostCallback = -2; + + function throwsException(fake, error, message) { + if (typeof error === "function") { + fake.exceptionCreator = error; + } else if (typeof error === "string") { + fake.exceptionCreator = function () { + const newException = new Error( + message || `Sinon-provided ${error}` + ); + newException.name = error; + return newException; + }; + } else if (!error) { + fake.exceptionCreator = function () { + return new Error("Error"); + }; + } else { + fake.exception = error; + } + } + + const defaultBehaviors = { + callsFake: function callsFake(fake, fn) { + fake.fakeFn = fn; + fake.exception = undefined; + fake.exceptionCreator = undefined; + }, + + callsArg: function callsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.callArgAt = index; + fake.callbackArguments = []; + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, + + callsArgOn: function callsArgOn(fake, index, context) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.callArgAt = index; + fake.callbackArguments = []; + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, + + callsArgWith: function callsArgWith(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.callArgAt = index; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, + + callsArgOnWith: function callsArgWith(fake, index, context) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.callArgAt = index; + fake.callbackArguments = slice(arguments, 3); + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, + + usingPromise: function usingPromise(fake, promiseLibrary) { + fake.promiseLibrary = promiseLibrary; + }, + + yields: function (fake) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 1); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, + + yieldsRight: function (fake) { + fake.callArgAt = useRightMostCallback; + fake.callbackArguments = slice(arguments, 1); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, + + yieldsOn: function (fake, context) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, + + yieldsTo: function (fake, prop) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = undefined; + fake.callArgProp = prop; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, + + yieldsToOn: function (fake, prop, context) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 3); + fake.callbackContext = context; + fake.callArgProp = prop; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, + + throws: throwsException, + throwsException: throwsException, + + returns: function returns(fake, value) { + fake.returnValue = value; + fake.resolve = false; + fake.reject = false; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, + + returnsArg: function returnsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.returnArgAt = index; + }, + + throwsArg: function throwsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + + fake.throwArgAt = index; + }, + + returnsThis: function returnsThis(fake) { + fake.returnThis = true; + }, + + resolves: function resolves(fake, value) { + fake.returnValue = value; + fake.resolve = true; + fake.resolveThis = false; + fake.reject = false; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, + + resolvesArg: function resolvesArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + fake.resolveArgAt = index; + fake.returnValue = undefined; + fake.resolve = true; + fake.resolveThis = false; + fake.reject = false; + fake.returnValueDefined = false; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, + + rejects: function rejects(fake, error, message) { + let reason; + if (typeof error === "string") { + reason = new Error(message || ""); + reason.name = error; + } else if (!error) { + reason = new Error("Error"); + } else { + reason = error; + } + fake.returnValue = reason; + fake.resolve = false; + fake.resolveThis = false; + fake.reject = true; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + + return fake; + }, + + resolvesThis: function resolvesThis(fake) { + fake.returnValue = undefined; + fake.resolve = false; + fake.resolveThis = true; + fake.reject = false; + fake.returnValueDefined = false; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, + + callThrough: function callThrough(fake) { + fake.callsThrough = true; + }, + + callThroughWithNew: function callThroughWithNew(fake) { + fake.callsThroughWithNew = true; + }, + + get: function get(fake, getterFunction) { + const rootStub = fake.stub || fake; + + Object.defineProperty(rootStub.rootObj, rootStub.propName, { + get: getterFunction, + configurable: isPropertyConfigurable( + rootStub.rootObj, + rootStub.propName + ), + }); + + return fake; + }, + + set: function set(fake, setterFunction) { + const rootStub = fake.stub || fake; + + Object.defineProperty( + rootStub.rootObj, + rootStub.propName, + // eslint-disable-next-line accessor-pairs + { + set: setterFunction, + configurable: isPropertyConfigurable( + rootStub.rootObj, + rootStub.propName + ), + } + ); + + return fake; + }, + + value: function value(fake, newVal) { + const rootStub = fake.stub || fake; + + Object.defineProperty(rootStub.rootObj, rootStub.propName, { + value: newVal, + enumerable: true, + writable: true, + configurable: + rootStub.shadowsPropOnPrototype || + isPropertyConfigurable(rootStub.rootObj, rootStub.propName), + }); + + return fake; + }, + }; + + const asyncBehaviors = exportAsyncBehaviors(defaultBehaviors); + + module.exports = extend({}, defaultBehaviors, asyncBehaviors); + + },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/is-property-configurable":31,"@sinonjs/commons":47}],9:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const createProxy = require("./proxy"); + const nextTick = require("./util/core/next-tick"); + + const slice = arrayProto.slice; + let promiseLib = Promise; + + module.exports = fake; + + /** + * Returns a `fake` that records all calls, arguments and return values. + * + * When an `f` argument is supplied, this implementation will be used. + * + * @example + * // create an empty fake + * var f1 = sinon.fake(); + * + * f1(); + * + * f1.calledOnce() + * // true + * + * @example + * function greet(greeting) { + * console.log(`Hello ${greeting}`); + * } + * + * // create a fake with implementation + * var f2 = sinon.fake(greet); + * + * // Hello world + * f2("world"); + * + * f2.calledWith("world"); + * // true + * + * @param {Function|undefined} f + * @returns {Function} + * @namespace + */ + function fake(f) { + if (arguments.length > 0 && typeof f !== "function") { + throw new TypeError("Expected f argument to be a Function"); + } + + return wrapFunc(f); + } + + /** + * Creates a `fake` that returns the provided `value`, as well as recording all + * calls, arguments and return values. + * + * @example + * var f1 = sinon.fake.returns(42); + * + * f1(); + * // 42 + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.returns = function returns(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return value; + } + + return wrapFunc(f); + }; + + /** + * Creates a `fake` that throws an Error. + * If the `value` argument does not have Error in its prototype chain, it will + * be used for creating a new error. + * + * @example + * var f1 = sinon.fake.throws("hello"); + * + * f1(); + * // Uncaught Error: hello + * + * @example + * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); + * + * f2(); + * // Uncaught TypeError: Invalid argument + * + * @memberof fake + * @param {*|Error} value + * @returns {Function} + */ + fake.throws = function throws(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + throw getError(value); + } + + return wrapFunc(f); + }; + + /** + * Creates a `fake` that returns a promise that resolves to the passed `value` + * argument. + * + * @example + * var f1 = sinon.fake.resolves("apple pie"); + * + * await f1(); + * // "apple pie" + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.resolves = function resolves(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return promiseLib.resolve(value); + } + + return wrapFunc(f); + }; + + /** + * Creates a `fake` that returns a promise that rejects to the passed `value` + * argument. When `value` does not have Error in its prototype chain, it will be + * wrapped in an Error. + * + * @example + * var f1 = sinon.fake.rejects(":("); + * + * try { + * await ft(); + * } catch (error) { + * console.log(error); + * // ":(" + * } + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.rejects = function rejects(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return promiseLib.reject(getError(value)); + } + + return wrapFunc(f); + }; + + /** + * Causes `fake` to use a custom Promise implementation, instead of the native + * Promise implementation. + * + * @example + * const bluebird = require("bluebird"); + * sinon.fake.usingPromise(bluebird); + * + * @memberof fake + * @param {*} promiseLibrary + * @returns {Function} + */ + fake.usingPromise = function usingPromise(promiseLibrary) { + promiseLib = promiseLibrary; + return fake; + }; + + /** + * Returns a `fake` that calls the callback with the defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * // "apple*pie" + * + * @memberof fake + * @returns {Function} + */ + fake.yields = function yields() { + const values = slice(arguments); + + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + const callback = arguments[arguments.length - 1]; + if (typeof callback !== "function") { + throw new TypeError("Expected last argument to be a function"); + } + + callback.apply(null, values); + } + + return wrapFunc(f); + }; + + /** + * Returns a `fake` that calls the callback **asynchronously** with the + * defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * + * setTimeout(() => { + * // "apple*pie" + * }); + * + * @memberof fake + * @returns {Function} + */ + fake.yieldsAsync = function yieldsAsync() { + const values = slice(arguments); + + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + const callback = arguments[arguments.length - 1]; + if (typeof callback !== "function") { + throw new TypeError("Expected last argument to be a function"); + } + nextTick(function () { + callback.apply(null, values); + }); + } + + return wrapFunc(f); + }; + + let uuid = 0; + /** + * Creates a proxy (sinon concept) from the passed function. + * + * @private + * @param {Function} f + * @returns {Function} + */ + function wrapFunc(f) { + const fakeInstance = function () { + let firstArg, lastArg; + + if (arguments.length > 0) { + firstArg = arguments[0]; + lastArg = arguments[arguments.length - 1]; + } + + const callback = + lastArg && typeof lastArg === "function" ? lastArg : undefined; + + /* eslint-disable no-use-before-define */ + proxy.firstArg = firstArg; + proxy.lastArg = lastArg; + proxy.callback = callback; + + return f && f.apply(this, arguments); + }; + const proxy = createProxy(fakeInstance, f || fakeInstance); + + proxy.displayName = "fake"; + proxy.id = `fake#${uuid++}`; + + return proxy; + } + + /** + * Returns an Error instance from the passed value, if the value is not + * already an Error instance. + * + * @private + * @param {*} value [description] + * @returns {Error} [description] + */ + function getError(value) { + return value instanceof Error ? value : new Error(value); + } + + },{"./proxy":16,"./util/core/next-tick":33,"@sinonjs/commons":47}],10:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const proxyInvoke = require("./proxy-invoke"); + const proxyCallToString = require("./proxy-call").toString; + const timesInWords = require("./util/core/times-in-words"); + const extend = require("./util/core/extend"); + const match = require("@sinonjs/samsam").createMatcher; + const stub = require("./stub"); + const assert = require("./assert"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const inspect = require("util").inspect; + const valueToString = require("@sinonjs/commons").valueToString; + + const every = arrayProto.every; + const forEach = arrayProto.forEach; + const push = arrayProto.push; + const slice = arrayProto.slice; + + function callCountInWords(callCount) { + if (callCount === 0) { + return "never called"; + } + + return `called ${timesInWords(callCount)}`; + } + + function expectedCallCountInWords(expectation) { + const min = expectation.minCalls; + const max = expectation.maxCalls; + + if (typeof min === "number" && typeof max === "number") { + let str = timesInWords(min); + + if (min !== max) { + str = `at least ${str} and at most ${timesInWords(max)}`; + } + + return str; + } + + if (typeof min === "number") { + return `at least ${timesInWords(min)}`; + } + + return `at most ${timesInWords(max)}`; + } + + function receivedMinCalls(expectation) { + const hasMinLimit = typeof expectation.minCalls === "number"; + return !hasMinLimit || expectation.callCount >= expectation.minCalls; + } + + function receivedMaxCalls(expectation) { + if (typeof expectation.maxCalls !== "number") { + return false; + } + + return expectation.callCount === expectation.maxCalls; + } + + function verifyMatcher(possibleMatcher, arg) { + const isMatcher = match.isMatcher(possibleMatcher); + + return (isMatcher && possibleMatcher.test(arg)) || true; + } + + const mockExpectation = { + minCalls: 1, + maxCalls: 1, + + create: function create(methodName) { + const expectation = extend.nonEnum(stub(), mockExpectation); + delete expectation.create; + expectation.method = methodName; + + return expectation; + }, + + invoke: function invoke(func, thisValue, args) { + this.verifyCallAllowed(thisValue, args); + + return proxyInvoke.apply(this, arguments); + }, + + atLeast: function atLeast(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not number`); + } + + if (!this.limitsSet) { + this.maxCalls = null; + this.limitsSet = true; + } + + this.minCalls = num; + + return this; + }, + + atMost: function atMost(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not number`); + } + + if (!this.limitsSet) { + this.minCalls = null; + this.limitsSet = true; + } + + this.maxCalls = num; + + return this; + }, + + never: function never() { + return this.exactly(0); + }, + + once: function once() { + return this.exactly(1); + }, + + twice: function twice() { + return this.exactly(2); + }, + + thrice: function thrice() { + return this.exactly(3); + }, + + exactly: function exactly(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not a number`); + } + + this.atLeast(num); + return this.atMost(num); + }, + + met: function met() { + return !this.failed && receivedMinCalls(this); + }, + + verifyCallAllowed: function verifyCallAllowed(thisValue, args) { + const expectedArguments = this.expectedArguments; + + if (receivedMaxCalls(this)) { + this.failed = true; + mockExpectation.fail( + `${this.method} already called ${timesInWords(this.maxCalls)}` + ); + } + + if ("expectedThis" in this && this.expectedThis !== thisValue) { + mockExpectation.fail( + `${this.method} called with ${valueToString( + thisValue + )} as thisValue, expected ${valueToString(this.expectedThis)}` + ); + } + + if (!("expectedArguments" in this)) { + return; + } + + if (!args) { + mockExpectation.fail( + `${this.method} received no arguments, expected ${inspect( + expectedArguments + )}` + ); + } + + if (args.length < expectedArguments.length) { + mockExpectation.fail( + `${this.method} received too few arguments (${inspect( + args + )}), expected ${inspect(expectedArguments)}` + ); + } + + if ( + this.expectsExactArgCount && + args.length !== expectedArguments.length + ) { + mockExpectation.fail( + `${this.method} received too many arguments (${inspect( + args + )}), expected ${inspect(expectedArguments)}` + ); + } + + forEach( + expectedArguments, + function (expectedArgument, i) { + if (!verifyMatcher(expectedArgument, args[i])) { + mockExpectation.fail( + `${this.method} received wrong arguments ${inspect( + args + )}, didn't match ${String(expectedArguments)}` + ); + } + + if (!deepEqual(args[i], expectedArgument)) { + mockExpectation.fail( + `${this.method} received wrong arguments ${inspect( + args + )}, expected ${inspect(expectedArguments)}` + ); + } + }, + this + ); + }, + + allowsCall: function allowsCall(thisValue, args) { + const expectedArguments = this.expectedArguments; + + if (this.met() && receivedMaxCalls(this)) { + return false; + } + + if ("expectedThis" in this && this.expectedThis !== thisValue) { + return false; + } + + if (!("expectedArguments" in this)) { + return true; + } + + // eslint-disable-next-line no-underscore-dangle + const _args = args || []; + + if (_args.length < expectedArguments.length) { + return false; + } + + if ( + this.expectsExactArgCount && + _args.length !== expectedArguments.length + ) { + return false; + } + + return every(expectedArguments, function (expectedArgument, i) { + if (!verifyMatcher(expectedArgument, _args[i])) { + return false; + } + + if (!deepEqual(_args[i], expectedArgument)) { + return false; + } + + return true; + }); + }, + + withArgs: function withArgs() { + this.expectedArguments = slice(arguments); + return this; + }, + + withExactArgs: function withExactArgs() { + this.withArgs.apply(this, arguments); + this.expectsExactArgCount = true; + return this; + }, + + on: function on(thisValue) { + this.expectedThis = thisValue; + return this; + }, + + toString: function () { + const args = slice(this.expectedArguments || []); + + if (!this.expectsExactArgCount) { + push(args, "[...]"); + } + + const callStr = proxyCallToString.call({ + proxy: this.method || "anonymous mock expectation", + args: args, + }); + + const message = `${callStr.replace( + ", [...", + "[, ..." + )} ${expectedCallCountInWords(this)}`; + + if (this.met()) { + return `Expectation met: ${message}`; + } + + return `Expected ${message} (${callCountInWords(this.callCount)})`; + }, + + verify: function verify() { + if (!this.met()) { + mockExpectation.fail(String(this)); + } else { + mockExpectation.pass(String(this)); + } + + return true; + }, + + pass: function pass(message) { + assert.pass(message); + }, + + fail: function fail(message) { + const exception = new Error(message); + exception.name = "ExpectationError"; + + throw exception; + }, + }; + + module.exports = mockExpectation; + + },{"./assert":2,"./proxy-call":14,"./proxy-invoke":15,"./stub":21,"./util/core/extend":25,"./util/core/times-in-words":35,"@sinonjs/commons":47,"@sinonjs/samsam":87,"util":112}],11:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const mockExpectation = require("./mock-expectation"); + const proxyCallToString = require("./proxy-call").toString; + const extend = require("./util/core/extend"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const wrapMethod = require("./util/core/wrap-method"); + const usePromiseLibrary = require("./util/core/use-promise-library"); + + const concat = arrayProto.concat; + const filter = arrayProto.filter; + const forEach = arrayProto.forEach; + const every = arrayProto.every; + const join = arrayProto.join; + const push = arrayProto.push; + const slice = arrayProto.slice; + const unshift = arrayProto.unshift; + + function mock(object) { + if (!object || typeof object === "string") { + return mockExpectation.create(object ? object : "Anonymous mock"); + } + + return mock.create(object); + } + + function each(collection, callback) { + const col = collection || []; + + forEach(col, callback); + } + + function arrayEquals(arr1, arr2, compareLength) { + if (compareLength && arr1.length !== arr2.length) { + return false; + } + + return every(arr1, function (element, i) { + return deepEqual(arr2[i], element); + }); + } + + extend(mock, { + create: function create(object) { + if (!object) { + throw new TypeError("object is null"); + } + + const mockObject = extend.nonEnum({}, mock, { object: object }); + delete mockObject.create; + + return mockObject; + }, + + expects: function expects(method) { + if (!method) { + throw new TypeError("method is falsy"); + } + + if (!this.expectations) { + this.expectations = {}; + this.proxies = []; + this.failures = []; + } + + if (!this.expectations[method]) { + this.expectations[method] = []; + const mockObject = this; + + wrapMethod(this.object, method, function () { + return mockObject.invokeMethod(method, this, arguments); + }); + + push(this.proxies, method); + } + + const expectation = mockExpectation.create(method); + expectation.wrappedMethod = this.object[method].wrappedMethod; + push(this.expectations[method], expectation); + usePromiseLibrary(this.promiseLibrary, expectation); + + return expectation; + }, + + restore: function restore() { + const object = this.object; + + each(this.proxies, function (proxy) { + if (typeof object[proxy].restore === "function") { + object[proxy].restore(); + } + }); + }, + + verify: function verify() { + const expectations = this.expectations || {}; + const messages = this.failures ? slice(this.failures) : []; + const met = []; + + each(this.proxies, function (proxy) { + each(expectations[proxy], function (expectation) { + if (!expectation.met()) { + push(messages, String(expectation)); + } else { + push(met, String(expectation)); + } + }); + }); + + this.restore(); + + if (messages.length > 0) { + mockExpectation.fail(join(concat(messages, met), "\n")); + } else if (met.length > 0) { + mockExpectation.pass(join(concat(messages, met), "\n")); + } + + return true; + }, + + usingPromise: function usingPromise(promiseLibrary) { + this.promiseLibrary = promiseLibrary; + + return this; + }, + + invokeMethod: function invokeMethod(method, thisValue, args) { + /* if we cannot find any matching files we will explicitly call mockExpection#fail with error messages */ + /* eslint consistent-return: "off" */ + const expectations = + this.expectations && this.expectations[method] + ? this.expectations[method] + : []; + const currentArgs = args || []; + let available; + + const expectationsWithMatchingArgs = filter( + expectations, + function (expectation) { + const expectedArgs = expectation.expectedArguments || []; + + return arrayEquals( + expectedArgs, + currentArgs, + expectation.expectsExactArgCount + ); + } + ); + + const expectationsToApply = filter( + expectationsWithMatchingArgs, + function (expectation) { + return ( + !expectation.met() && + expectation.allowsCall(thisValue, args) + ); + } + ); + + if (expectationsToApply.length > 0) { + return expectationsToApply[0].apply(thisValue, args); + } + + const messages = []; + let exhausted = 0; + + forEach(expectationsWithMatchingArgs, function (expectation) { + if (expectation.allowsCall(thisValue, args)) { + available = available || expectation; + } else { + exhausted += 1; + } + }); + + if (available && exhausted === 0) { + return available.apply(thisValue, args); + } + + forEach(expectations, function (expectation) { + push(messages, ` ${String(expectation)}`); + }); + + unshift( + messages, + `Unexpected call: ${proxyCallToString.call({ + proxy: method, + args: args, + })}` + ); + + const err = new Error(); + if (!err.stack) { + // PhantomJS does not serialize the stack trace until the error has been thrown + try { + throw err; + } catch (e) { + /* empty */ + } + } + push( + this.failures, + `Unexpected call: ${proxyCallToString.call({ + proxy: method, + args: args, + stack: err.stack, + })}` + ); + + mockExpectation.fail(join(messages, "\n")); + }, + }); + + module.exports = mock; + + },{"./mock-expectation":10,"./proxy-call":14,"./util/core/extend":25,"./util/core/use-promise-library":36,"./util/core/wrap-method":39,"@sinonjs/commons":47,"@sinonjs/samsam":87}],12:[function(require,module,exports){ + + const fake = require("./fake"); + const isRestorable = require("./util/core/is-restorable"); + + const STATUS_PENDING = "pending"; + const STATUS_RESOLVED = "resolved"; + const STATUS_REJECTED = "rejected"; + + /** + * Returns a fake for a given function or undefined. If no function is given, a + * new fake is returned. If the given function is already a fake, it is + * returned as is. Otherwise the given function is wrapped in a new fake. + * + * @param {Function} [executor] The optional executor function. + * @returns {Function} + */ + function getFakeExecutor(executor) { + if (isRestorable(executor)) { + return executor; + } + if (executor) { + return fake(executor); + } + return fake(); + } + + /** + * Returns a new promise that exposes it's internal `status`, `resolvedValue` + * and `rejectedValue` and can be resolved or rejected from the outside by + * calling `resolve(value)` or `reject(reason)`. + * + * @param {Function} [executor] The optional executor function. + * @returns {Promise} + */ + function promise(executor) { + const fakeExecutor = getFakeExecutor(executor); + const sinonPromise = new Promise(fakeExecutor); + + sinonPromise.status = STATUS_PENDING; + sinonPromise + .then(function (value) { + sinonPromise.status = STATUS_RESOLVED; + sinonPromise.resolvedValue = value; + }) + .catch(function (reason) { + sinonPromise.status = STATUS_REJECTED; + sinonPromise.rejectedValue = reason; + }); + + /** + * Resolves or rejects the promise with the given status and value. + * + * @param {string} status + * @param {*} value + * @param {Function} callback + */ + function finalize(status, value, callback) { + if (sinonPromise.status !== STATUS_PENDING) { + throw new Error(`Promise already ${sinonPromise.status}`); + } + + sinonPromise.status = status; + callback(value); + } + + sinonPromise.resolve = function (value) { + finalize(STATUS_RESOLVED, value, fakeExecutor.firstCall.args[0]); + // Return the promise so that callers can await it: + return sinonPromise; + }; + sinonPromise.reject = function (reason) { + finalize(STATUS_REJECTED, reason, fakeExecutor.firstCall.args[1]); + // Return a new promise that resolves when the sinon promise was + // rejected, so that callers can await it: + return new Promise(function (resolve) { + sinonPromise.catch(() => resolve()); + }); + }; + + return sinonPromise; + } + + module.exports = promise; + + },{"./fake":9,"./util/core/is-restorable":32}],13:[function(require,module,exports){ + + const push = require("@sinonjs/commons").prototypes.array.push; + + exports.incrementCallCount = function incrementCallCount(proxy) { + proxy.called = true; + proxy.callCount += 1; + proxy.notCalled = false; + proxy.calledOnce = proxy.callCount === 1; + proxy.calledTwice = proxy.callCount === 2; + proxy.calledThrice = proxy.callCount === 3; + }; + + exports.createCallProperties = function createCallProperties(proxy) { + proxy.firstCall = proxy.getCall(0); + proxy.secondCall = proxy.getCall(1); + proxy.thirdCall = proxy.getCall(2); + proxy.lastCall = proxy.getCall(proxy.callCount - 1); + }; + + exports.delegateToCalls = function delegateToCalls( + proxy, + method, + matchAny, + actual, + returnsValues, + notCalled, + totalCallCount + ) { + proxy[method] = function () { + if (!this.called) { + if (notCalled) { + return notCalled.apply(this, arguments); + } + return false; + } + + if (totalCallCount !== undefined && this.callCount !== totalCallCount) { + return false; + } + + let currentCall; + let matches = 0; + const returnValues = []; + + for (let i = 0, l = this.callCount; i < l; i += 1) { + currentCall = this.getCall(i); + const returnValue = currentCall[actual || method].apply( + currentCall, + arguments + ); + push(returnValues, returnValue); + if (returnValue) { + matches += 1; + + if (matchAny) { + return true; + } + } + } + + if (returnsValues) { + return returnValues; + } + return matches === this.callCount; + }; + }; + + },{"@sinonjs/commons":47}],14:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const match = require("@sinonjs/samsam").createMatcher; + const deepEqual = require("@sinonjs/samsam").deepEqual; + const functionName = require("@sinonjs/commons").functionName; + const inspect = require("util").inspect; + const valueToString = require("@sinonjs/commons").valueToString; + + const concat = arrayProto.concat; + const filter = arrayProto.filter; + const join = arrayProto.join; + const map = arrayProto.map; + const reduce = arrayProto.reduce; + const slice = arrayProto.slice; + + /** + * @param proxy + * @param text + * @param args + */ + function throwYieldError(proxy, text, args) { + let msg = functionName(proxy) + text; + if (args.length) { + msg += ` Received [${join(slice(args), ", ")}]`; + } + throw new Error(msg); + } + + const callProto = { + calledOn: function calledOn(thisValue) { + if (match.isMatcher(thisValue)) { + return thisValue.test(this.thisValue); + } + return this.thisValue === thisValue; + }, + + calledWith: function calledWith() { + const self = this; + const calledWithArgs = slice(arguments); + + if (calledWithArgs.length > self.args.length) { + return false; + } + + return reduce( + calledWithArgs, + function (prev, arg, i) { + return prev && deepEqual(self.args[i], arg); + }, + true + ); + }, + + calledWithMatch: function calledWithMatch() { + const self = this; + const calledWithMatchArgs = slice(arguments); + + if (calledWithMatchArgs.length > self.args.length) { + return false; + } + + return reduce( + calledWithMatchArgs, + function (prev, expectation, i) { + const actual = self.args[i]; + + return prev && match(expectation).test(actual); + }, + true + ); + }, + + calledWithExactly: function calledWithExactly() { + return ( + arguments.length === this.args.length && + this.calledWith.apply(this, arguments) + ); + }, + + notCalledWith: function notCalledWith() { + return !this.calledWith.apply(this, arguments); + }, + + notCalledWithMatch: function notCalledWithMatch() { + return !this.calledWithMatch.apply(this, arguments); + }, + + returned: function returned(value) { + return deepEqual(this.returnValue, value); + }, + + threw: function threw(error) { + if (typeof error === "undefined" || !this.exception) { + return Boolean(this.exception); + } + + return this.exception === error || this.exception.name === error; + }, + + calledWithNew: function calledWithNew() { + return this.proxy.prototype && this.thisValue instanceof this.proxy; + }, + + calledBefore: function (other) { + return this.callId < other.callId; + }, + + calledAfter: function (other) { + return this.callId > other.callId; + }, + + calledImmediatelyBefore: function (other) { + return this.callId === other.callId - 1; + }, + + calledImmediatelyAfter: function (other) { + return this.callId === other.callId + 1; + }, + + callArg: function (pos) { + this.ensureArgIsAFunction(pos); + return this.args[pos](); + }, + + callArgOn: function (pos, thisValue) { + this.ensureArgIsAFunction(pos); + return this.args[pos].apply(thisValue); + }, + + callArgWith: function (pos) { + return this.callArgOnWith.apply( + this, + concat([pos, null], slice(arguments, 1)) + ); + }, + + callArgOnWith: function (pos, thisValue) { + this.ensureArgIsAFunction(pos); + const args = slice(arguments, 2); + return this.args[pos].apply(thisValue, args); + }, + + throwArg: function (pos) { + if (pos > this.args.length) { + throw new TypeError( + `Not enough arguments: ${pos} required but only ${this.args.length} present` + ); + } + + throw this.args[pos]; + }, + + yield: function () { + return this.yieldOn.apply(this, concat([null], slice(arguments, 0))); + }, + + yieldOn: function (thisValue) { + const args = slice(this.args); + const yieldFn = filter(args, function (arg) { + return typeof arg === "function"; + })[0]; + + if (!yieldFn) { + throwYieldError( + this.proxy, + " cannot yield since no callback was passed.", + args + ); + } + + return yieldFn.apply(thisValue, slice(arguments, 1)); + }, + + yieldTo: function (prop) { + return this.yieldToOn.apply( + this, + concat([prop, null], slice(arguments, 1)) + ); + }, + + yieldToOn: function (prop, thisValue) { + const args = slice(this.args); + const yieldArg = filter(args, function (arg) { + return arg && typeof arg[prop] === "function"; + })[0]; + const yieldFn = yieldArg && yieldArg[prop]; + + if (!yieldFn) { + throwYieldError( + this.proxy, + ` cannot yield to '${valueToString( + prop + )}' since no callback was passed.`, + args + ); + } + + return yieldFn.apply(thisValue, slice(arguments, 2)); + }, + + toString: function () { + if (!this.args) { + return ":("; + } + + let callStr = this.proxy ? `${String(this.proxy)}(` : ""; + const formattedArgs = map(this.args, function (arg) { + return inspect(arg); + }); + + callStr = `${callStr + join(formattedArgs, ", ")})`; + + if (typeof this.returnValue !== "undefined") { + callStr += ` => ${inspect(this.returnValue)}`; + } + + if (this.exception) { + callStr += ` !${this.exception.name}`; + + if (this.exception.message) { + callStr += `(${this.exception.message})`; + } + } + if (this.stack) { + // If we have a stack, add the first frame that's in end-user code + // Skip the first two frames because they will refer to Sinon code + callStr += (this.stack.split("\n")[3] || "unknown").replace( + /^\s*(?:at\s+|@)?/, + " at " + ); + } + + return callStr; + }, + + ensureArgIsAFunction: function (pos) { + if (typeof this.args[pos] !== "function") { + throw new TypeError( + `Expected argument at position ${pos} to be a Function, but was ${typeof this + .args[pos]}` + ); + } + }, + }; + Object.defineProperty(callProto, "stack", { + enumerable: true, + configurable: true, + get: function () { + return (this.errorWithCallStack && this.errorWithCallStack.stack) || ""; + }, + }); + + callProto.invokeCallback = callProto.yield; + + /** + * @param proxy + * @param thisValue + * @param args + * @param returnValue + * @param exception + * @param id + * @param errorWithCallStack + */ + function createProxyCall( + proxy, + thisValue, + args, + returnValue, + exception, + id, + errorWithCallStack + ) { + if (typeof id !== "number") { + throw new TypeError("Call id is not a number"); + } + + let firstArg, lastArg; + + if (args.length > 0) { + firstArg = args[0]; + lastArg = args[args.length - 1]; + } + + const proxyCall = Object.create(callProto); + const callback = + lastArg && typeof lastArg === "function" ? lastArg : undefined; + + proxyCall.proxy = proxy; + proxyCall.thisValue = thisValue; + proxyCall.args = args; + proxyCall.firstArg = firstArg; + proxyCall.lastArg = lastArg; + proxyCall.callback = callback; + proxyCall.returnValue = returnValue; + proxyCall.exception = exception; + proxyCall.callId = id; + proxyCall.errorWithCallStack = errorWithCallStack; + + return proxyCall; + } + createProxyCall.toString = callProto.toString; // used by mocks + + module.exports = createProxyCall; + + },{"@sinonjs/commons":47,"@sinonjs/samsam":87,"util":112}],15:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const proxyCallUtil = require("./proxy-call-util"); + + const push = arrayProto.push; + const forEach = arrayProto.forEach; + const concat = arrayProto.concat; + const ErrorConstructor = Error.prototype.constructor; + const bind = Function.prototype.bind; + + let callId = 0; + + module.exports = function invoke(func, thisValue, args) { + const matchings = this.matchingFakes(args); + const currentCallId = callId++; + let exception, returnValue; + + proxyCallUtil.incrementCallCount(this); + push(this.thisValues, thisValue); + push(this.args, args); + push(this.callIds, currentCallId); + forEach(matchings, function (matching) { + proxyCallUtil.incrementCallCount(matching); + push(matching.thisValues, thisValue); + push(matching.args, args); + push(matching.callIds, currentCallId); + }); + + // Make call properties available from within the spied function: + proxyCallUtil.createCallProperties(this); + forEach(matchings, proxyCallUtil.createCallProperties); + + try { + this.invoking = true; + + const thisCall = this.getCall(this.callCount - 1); + + if (thisCall.calledWithNew()) { + // Call through with `new` + returnValue = new (bind.apply( + this.func || func, + concat([thisValue], args) + ))(); + + if ( + typeof returnValue !== "object" && + typeof returnValue !== "function" + ) { + returnValue = thisValue; + } + } else { + returnValue = (this.func || func).apply(thisValue, args); + } + } catch (e) { + exception = e; + } finally { + delete this.invoking; + } + + push(this.exceptions, exception); + push(this.returnValues, returnValue); + forEach(matchings, function (matching) { + push(matching.exceptions, exception); + push(matching.returnValues, returnValue); + }); + + const err = new ErrorConstructor(); + // 1. Please do not get stack at this point. It may be so very slow, and not actually used + // 2. PhantomJS does not serialize the stack trace until the error has been thrown: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack + try { + throw err; + } catch (e) { + /* empty */ + } + push(this.errorsWithCallStack, err); + forEach(matchings, function (matching) { + push(matching.errorsWithCallStack, err); + }); + + // Make return value and exception available in the calls: + proxyCallUtil.createCallProperties(this); + forEach(matchings, proxyCallUtil.createCallProperties); + + if (exception !== undefined) { + throw exception; + } + + return returnValue; + }; + + },{"./proxy-call-util":13,"@sinonjs/commons":47}],16:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const extend = require("./util/core/extend"); + const functionToString = require("./util/core/function-to-string"); + const proxyCall = require("./proxy-call"); + const proxyCallUtil = require("./proxy-call-util"); + const proxyInvoke = require("./proxy-invoke"); + const inspect = require("util").inspect; + + const push = arrayProto.push; + const forEach = arrayProto.forEach; + const slice = arrayProto.slice; + + const emptyFakes = Object.freeze([]); + + // Public API + const proxyApi = { + toString: functionToString, + + named: function named(name) { + this.displayName = name; + const nameDescriptor = Object.getOwnPropertyDescriptor(this, "name"); + if (nameDescriptor && nameDescriptor.configurable) { + // IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + nameDescriptor.value = name; + Object.defineProperty(this, "name", nameDescriptor); + } + return this; + }, + + invoke: proxyInvoke, + + /* + * Hook for derived implementation to return fake instances matching the + * given arguments. + */ + matchingFakes: function (/*args, strict*/) { + return emptyFakes; + }, + + getCall: function getCall(index) { + let i = index; + if (i < 0) { + // Negative indices means counting backwards from the last call + i += this.callCount; + } + if (i < 0 || i >= this.callCount) { + return null; + } + + return proxyCall( + this, + this.thisValues[i], + this.args[i], + this.returnValues[i], + this.exceptions[i], + this.callIds[i], + this.errorsWithCallStack[i] + ); + }, + + getCalls: function () { + const calls = []; + let i; + + for (i = 0; i < this.callCount; i++) { + push(calls, this.getCall(i)); + } + + return calls; + }, + + calledBefore: function calledBefore(proxy) { + if (!this.called) { + return false; + } + + if (!proxy.called) { + return true; + } + + return this.callIds[0] < proxy.callIds[proxy.callIds.length - 1]; + }, + + calledAfter: function calledAfter(proxy) { + if (!this.called || !proxy.called) { + return false; + } + + return this.callIds[this.callCount - 1] > proxy.callIds[0]; + }, + + calledImmediatelyBefore: function calledImmediatelyBefore(proxy) { + if (!this.called || !proxy.called) { + return false; + } + + return ( + this.callIds[this.callCount - 1] === + proxy.callIds[proxy.callCount - 1] - 1 + ); + }, + + calledImmediatelyAfter: function calledImmediatelyAfter(proxy) { + if (!this.called || !proxy.called) { + return false; + } + + return ( + this.callIds[this.callCount - 1] === + proxy.callIds[proxy.callCount - 1] + 1 + ); + }, + + formatters: require("./spy-formatters"), + printf: function (format) { + const spyInstance = this; + const args = slice(arguments, 1); + let formatter; + + return (format || "").replace(/%(.)/g, function (match, specifier) { + formatter = proxyApi.formatters[specifier]; + + if (typeof formatter === "function") { + return String(formatter(spyInstance, args)); + } else if (!isNaN(parseInt(specifier, 10))) { + return inspect(args[specifier - 1]); + } + + return `%${specifier}`; + }); + }, + + resetHistory: function () { + if (this.invoking) { + const err = new Error( + "Cannot reset Sinon function while invoking it. " + + "Move the call to .resetHistory outside of the callback." + ); + err.name = "InvalidResetException"; + throw err; + } + + this.called = false; + this.notCalled = true; + this.calledOnce = false; + this.calledTwice = false; + this.calledThrice = false; + this.callCount = 0; + this.firstCall = null; + this.secondCall = null; + this.thirdCall = null; + this.lastCall = null; + this.args = []; + this.firstArg = null; + this.lastArg = null; + this.returnValues = []; + this.thisValues = []; + this.exceptions = []; + this.callIds = []; + this.errorsWithCallStack = []; + + if (this.fakes) { + forEach(this.fakes, function (fake) { + fake.resetHistory(); + }); + } + + return this; + }, + }; + + const delegateToCalls = proxyCallUtil.delegateToCalls; + delegateToCalls(proxyApi, "calledOn", true); + delegateToCalls(proxyApi, "alwaysCalledOn", false, "calledOn"); + delegateToCalls(proxyApi, "calledWith", true); + delegateToCalls( + proxyApi, + "calledOnceWith", + true, + "calledWith", + false, + undefined, + 1 + ); + delegateToCalls(proxyApi, "calledWithMatch", true); + delegateToCalls(proxyApi, "alwaysCalledWith", false, "calledWith"); + delegateToCalls(proxyApi, "alwaysCalledWithMatch", false, "calledWithMatch"); + delegateToCalls(proxyApi, "calledWithExactly", true); + delegateToCalls( + proxyApi, + "calledOnceWithExactly", + true, + "calledWithExactly", + false, + undefined, + 1 + ); + delegateToCalls( + proxyApi, + "calledOnceWithMatch", + true, + "calledWithMatch", + false, + undefined, + 1 + ); + delegateToCalls( + proxyApi, + "alwaysCalledWithExactly", + false, + "calledWithExactly" + ); + delegateToCalls( + proxyApi, + "neverCalledWith", + false, + "notCalledWith", + false, + function () { + return true; + } + ); + delegateToCalls( + proxyApi, + "neverCalledWithMatch", + false, + "notCalledWithMatch", + false, + function () { + return true; + } + ); + delegateToCalls(proxyApi, "threw", true); + delegateToCalls(proxyApi, "alwaysThrew", false, "threw"); + delegateToCalls(proxyApi, "returned", true); + delegateToCalls(proxyApi, "alwaysReturned", false, "returned"); + delegateToCalls(proxyApi, "calledWithNew", true); + delegateToCalls(proxyApi, "alwaysCalledWithNew", false, "calledWithNew"); + + function createProxy(func, originalFunc) { + const proxy = wrapFunction(func, originalFunc); + + // Inherit function properties: + extend(proxy, func); + + proxy.prototype = func.prototype; + + extend.nonEnum(proxy, proxyApi); + + return proxy; + } + + function wrapFunction(func, originalFunc) { + const arity = originalFunc.length; + let p; + // Do not change this to use an eval. Projects that depend on sinon block the use of eval. + // ref: https://github.com/sinonjs/sinon/issues/710 + switch (arity) { + /*eslint-disable no-unused-vars, max-len*/ + case 0: + p = function proxy() { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 1: + p = function proxy(a) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 2: + p = function proxy(a, b) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 3: + p = function proxy(a, b, c) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 4: + p = function proxy(a, b, c, d) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 5: + p = function proxy(a, b, c, d, e) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 6: + p = function proxy(a, b, c, d, e, f) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 7: + p = function proxy(a, b, c, d, e, f, g) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 8: + p = function proxy(a, b, c, d, e, f, g, h) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 9: + p = function proxy(a, b, c, d, e, f, g, h, i) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 10: + p = function proxy(a, b, c, d, e, f, g, h, i, j) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 11: + p = function proxy(a, b, c, d, e, f, g, h, i, j, k) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 12: + p = function proxy(a, b, c, d, e, f, g, h, i, j, k, l) { + return p.invoke(func, this, slice(arguments)); + }; + break; + default: + p = function proxy() { + return p.invoke(func, this, slice(arguments)); + }; + break; + /*eslint-enable*/ + } + const nameDescriptor = Object.getOwnPropertyDescriptor( + originalFunc, + "name" + ); + if (nameDescriptor && nameDescriptor.configurable) { + // IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + Object.defineProperty(p, "name", nameDescriptor); + } + extend.nonEnum(p, { + isSinonProxy: true, + + called: false, + notCalled: true, + calledOnce: false, + calledTwice: false, + calledThrice: false, + callCount: 0, + firstCall: null, + firstArg: null, + secondCall: null, + thirdCall: null, + lastCall: null, + lastArg: null, + args: [], + returnValues: [], + thisValues: [], + exceptions: [], + callIds: [], + errorsWithCallStack: [], + }); + return p; + } + + module.exports = createProxy; + + },{"./proxy-call":14,"./proxy-call-util":13,"./proxy-invoke":15,"./spy-formatters":19,"./util/core/extend":25,"./util/core/function-to-string":26,"@sinonjs/commons":47,"util":112}],17:[function(require,module,exports){ + + const walkObject = require("./util/core/walk-object"); + + function filter(object, property) { + return object[property].restore && object[property].restore.sinon; + } + + function restore(object, property) { + object[property].restore(); + } + + function restoreObject(object) { + return walkObject(restore, object, filter); + } + + module.exports = restoreObject; + + },{"./util/core/walk-object":37}],18:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const logger = require("@sinonjs/commons").deprecated; + const collectOwnMethods = require("./collect-own-methods"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const isPropertyConfigurable = require("./util/core/is-property-configurable"); + const match = require("@sinonjs/samsam").createMatcher; + const sinonAssert = require("./assert"); + const sinonClock = require("./util/fake-timers"); + const sinonMock = require("./mock"); + const sinonSpy = require("./spy"); + const sinonStub = require("./stub"); + const sinonCreateStubInstance = require("./create-stub-instance"); + const sinonFake = require("./fake"); + const valueToString = require("@sinonjs/commons").valueToString; + const fakeServer = require("nise").fakeServer; + const fakeXhr = require("nise").fakeXhr; + const usePromiseLibrary = require("./util/core/use-promise-library"); + + const DEFAULT_LEAK_THRESHOLD = 10000; + + const filter = arrayProto.filter; + const forEach = arrayProto.forEach; + const push = arrayProto.push; + const reverse = arrayProto.reverse; + + function applyOnEach(fakes, method) { + const matchingFakes = filter(fakes, function (fake) { + return typeof fake[method] === "function"; + }); + + forEach(matchingFakes, function (fake) { + fake[method](); + }); + } + + function throwOnAccessors(descriptor) { + if (typeof descriptor.get === "function") { + throw new Error("Use sandbox.replaceGetter for replacing getters"); + } + + if (typeof descriptor.set === "function") { + throw new Error("Use sandbox.replaceSetter for replacing setters"); + } + } + + function verifySameType(object, property, replacement) { + if (typeof object[property] !== typeof replacement) { + throw new TypeError( + `Cannot replace ${typeof object[ + property + ]} with ${typeof replacement}` + ); + } + } + + function checkForValidArguments(descriptor, property, replacement) { + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}. Perhaps you meant sandbox.define()?` + ); + } + + if (typeof replacement === "undefined") { + throw new TypeError("Expected replacement argument to be defined"); + } + } + + function Sandbox() { + const sandbox = this; + let fakeRestorers = []; + let promiseLib; + + let collection = []; + let loggedLeakWarning = false; + sandbox.leakThreshold = DEFAULT_LEAK_THRESHOLD; + + function addToCollection(object) { + if ( + push(collection, object) > sandbox.leakThreshold && + !loggedLeakWarning + ) { + // eslint-disable-next-line no-console + logger.printWarning( + "Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox." + ); + loggedLeakWarning = true; + } + } + + sandbox.assert = sinonAssert.createAssertObject(); + + sandbox.serverPrototype = fakeServer; + + // this is for testing only + sandbox.getFakes = function getFakes() { + return collection; + }; + + sandbox.createStubInstance = function createStubInstance() { + const stubbed = sinonCreateStubInstance.apply(null, arguments); + + const ownMethods = collectOwnMethods(stubbed); + + forEach(ownMethods, function (method) { + addToCollection(method); + }); + + usePromiseLibrary(promiseLib, ownMethods); + + return stubbed; + }; + + sandbox.inject = function inject(obj) { + obj.spy = function () { + return sandbox.spy.apply(null, arguments); + }; + + obj.stub = function () { + return sandbox.stub.apply(null, arguments); + }; + + obj.mock = function () { + return sandbox.mock.apply(null, arguments); + }; + + obj.createStubInstance = function () { + return sandbox.createStubInstance.apply(sandbox, arguments); + }; + + obj.fake = function () { + return sandbox.fake.apply(null, arguments); + }; + + obj.define = function () { + return sandbox.define.apply(null, arguments); + }; + + obj.replace = function () { + return sandbox.replace.apply(null, arguments); + }; + + obj.replaceSetter = function () { + return sandbox.replaceSetter.apply(null, arguments); + }; + + obj.replaceGetter = function () { + return sandbox.replaceGetter.apply(null, arguments); + }; + + if (sandbox.clock) { + obj.clock = sandbox.clock; + } + + if (sandbox.server) { + obj.server = sandbox.server; + obj.requests = sandbox.server.requests; + } + + obj.match = match; + + return obj; + }; + + sandbox.mock = function mock() { + const m = sinonMock.apply(null, arguments); + + addToCollection(m); + usePromiseLibrary(promiseLib, m); + + return m; + }; + + sandbox.reset = function reset() { + applyOnEach(collection, "reset"); + applyOnEach(collection, "resetHistory"); + }; + + sandbox.resetBehavior = function resetBehavior() { + applyOnEach(collection, "resetBehavior"); + }; + + sandbox.resetHistory = function resetHistory() { + function privateResetHistory(f) { + const method = f.resetHistory || f.reset; + if (method) { + method.call(f); + } + } + + forEach(collection, privateResetHistory); + }; + + sandbox.restore = function restore() { + if (arguments.length) { + throw new Error( + "sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()" + ); + } + + reverse(collection); + applyOnEach(collection, "restore"); + collection = []; + + forEach(fakeRestorers, function (restorer) { + restorer(); + }); + fakeRestorers = []; + + sandbox.restoreContext(); + }; + + sandbox.restoreContext = function restoreContext() { + if (!sandbox.injectedKeys) { + return; + } + + forEach(sandbox.injectedKeys, function (injectedKey) { + delete sandbox.injectInto[injectedKey]; + }); + + sandbox.injectedKeys.length = 0; + }; + + /** + * Creates a restorer function for the property + * + * @param {object|Function} object + * @param {string} property + * @param {boolean} forceAssignment + * @returns {Function} restorer function + */ + function getFakeRestorer(object, property, forceAssignment = false) { + const descriptor = getPropertyDescriptor(object, property); + const value = object[property]; + + function restorer() { + if (forceAssignment) { + object[property] = value; + } else if (descriptor?.isOwn) { + Object.defineProperty(object, property, descriptor); + } else { + delete object[property]; + } + } + + restorer.object = object; + restorer.property = property; + return restorer; + } + + function verifyNotReplaced(object, property) { + forEach(fakeRestorers, function (fakeRestorer) { + if ( + fakeRestorer.object === object && + fakeRestorer.property === property + ) { + throw new TypeError( + `Attempted to replace ${property} which is already replaced` + ); + } + }); + } + + /** + * Replace an existing property + * + * @param {object|Function} object + * @param {string} property + * @param {*} replacement a fake, stub, spy or any other value + * @returns {*} + */ + sandbox.replace = function replace(object, property, replacement) { + const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + throwOnAccessors(descriptor); + verifySameType(object, property, replacement); + + verifyNotReplaced(object, property); + + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); + + object[property] = replacement; + + return replacement; + }; + + sandbox.replace.usingAccessor = function replaceUsingAccessor( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + verifySameType(object, property, replacement); + + verifyNotReplaced(object, property); + + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property, true)); + + object[property] = replacement; + + return replacement; + }; + + sandbox.define = function define(object, property, value) { + const descriptor = getPropertyDescriptor(object, property); + + if (descriptor) { + throw new TypeError( + `Cannot define the already existing property ${valueToString( + property + )}. Perhaps you meant sandbox.replace()?` + ); + } + + if (typeof value === "undefined") { + throw new TypeError("Expected value argument to be defined"); + } + + verifyNotReplaced(object, property); + + // store a function for restoring the defined property + push(fakeRestorers, getFakeRestorer(object, property)); + + object[property] = value; + + return value; + }; + + sandbox.replaceGetter = function replaceGetter( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); + + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}` + ); + } + + if (typeof replacement !== "function") { + throw new TypeError( + "Expected replacement argument to be a function" + ); + } + + if (typeof descriptor.get !== "function") { + throw new Error("`object.property` is not a getter"); + } + + verifyNotReplaced(object, property); + + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); + + Object.defineProperty(object, property, { + get: replacement, + configurable: isPropertyConfigurable(object, property), + }); + + return replacement; + }; + + sandbox.replaceSetter = function replaceSetter( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); - verifyIsValidAssertion(name, args); + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}` + ); + } + + if (typeof replacement !== "function") { + throw new TypeError( + "Expected replacement argument to be a function" + ); + } + + if (typeof descriptor.set !== "function") { + throw new Error("`object.property` is not a setter"); + } + + verifyNotReplaced(object, property); - if (typeof meth === "function") { - failed = !meth(fake); - } else { - failed = - typeof fake[meth] === "function" - ? !fake[meth].apply(fake, args) - : !fake[meth]; - } + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); + + // eslint-disable-next-line accessor-pairs + Object.defineProperty(object, property, { + set: replacement, + configurable: isPropertyConfigurable(object, property), + }); + + return replacement; + }; + + function commonPostInitSetup(args, spy) { + const [object, property, types] = args; + + const isSpyingOnEntireObject = + typeof property === "undefined" && typeof object === "object"; + + if (isSpyingOnEntireObject) { + const ownMethods = collectOwnMethods(spy); + + forEach(ownMethods, function (method) { + addToCollection(method); + }); + + usePromiseLibrary(promiseLib, ownMethods); + } else if (Array.isArray(types)) { + for (const accessorType of types) { + addToCollection(spy[accessorType]); + usePromiseLibrary(promiseLib, spy[accessorType]); + } + } else { + addToCollection(spy); + usePromiseLibrary(promiseLib, spy); + } + + return spy; + } + + sandbox.spy = function spy() { + const createdSpy = sinonSpy.apply(sinonSpy, arguments); + return commonPostInitSetup(arguments, createdSpy); + }; + + sandbox.stub = function stub() { + const createdStub = sinonStub.apply(sinonStub, arguments); + return commonPostInitSetup(arguments, createdStub); + }; + + // eslint-disable-next-line no-unused-vars + sandbox.fake = function fake(f) { + const s = sinonFake.apply(sinonFake, arguments); + + addToCollection(s); + + return s; + }; + + forEach(Object.keys(sinonFake), function (key) { + const fakeBehavior = sinonFake[key]; + if (typeof fakeBehavior === "function") { + sandbox.fake[key] = function () { + const s = fakeBehavior.apply(fakeBehavior, arguments); + + addToCollection(s); + + return s; + }; + } + }); + + sandbox.useFakeTimers = function useFakeTimers(args) { + const clock = sinonClock.useFakeTimers.call(null, args); + + sandbox.clock = clock; + addToCollection(clock); + + return clock; + }; + + sandbox.verify = function verify() { + applyOnEach(collection, "verify"); + }; + + sandbox.verifyAndRestore = function verifyAndRestore() { + let exception; + + try { + sandbox.verify(); + } catch (e) { + exception = e; + } + + sandbox.restore(); + + if (exception) { + throw exception; + } + }; + + sandbox.useFakeServer = function useFakeServer() { + const proto = sandbox.serverPrototype || fakeServer; + + if (!proto || !proto.create) { + return null; + } + + sandbox.server = proto.create(); + addToCollection(sandbox.server); + + return sandbox.server; + }; + + sandbox.useFakeXMLHttpRequest = function useFakeXMLHttpRequest() { + const xhr = fakeXhr.useFakeXMLHttpRequest(); + addToCollection(xhr); + return xhr; + }; + + sandbox.usingPromise = function usingPromise(promiseLibrary) { + promiseLib = promiseLibrary; + collection.promiseLibrary = promiseLibrary; + + return sandbox; + }; + } + + Sandbox.prototype.match = match; + + module.exports = Sandbox; + + },{"./assert":2,"./collect-own-methods":4,"./create-stub-instance":7,"./fake":9,"./mock":11,"./spy":20,"./stub":21,"./util/core/get-property-descriptor":28,"./util/core/is-property-configurable":31,"./util/core/use-promise-library":36,"./util/fake-timers":40,"@sinonjs/commons":47,"@sinonjs/samsam":87,"nise":127}],19:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const color = require("./color"); + const match = require("@sinonjs/samsam").createMatcher; + const timesInWords = require("./util/core/times-in-words"); + const inspect = require("util").inspect; + const jsDiff = require("diff"); + + const join = arrayProto.join; + const map = arrayProto.map; + const push = arrayProto.push; + const slice = arrayProto.slice; + + function colorSinonMatchText(matcher, calledArg, calledArgMessage) { + let calledArgumentMessage = calledArgMessage; + let matcherMessage = matcher.message; + if (!matcher.test(calledArg)) { + matcherMessage = color.red(matcher.message); + if (calledArgumentMessage) { + calledArgumentMessage = color.green(calledArgumentMessage); + } + } + return `${calledArgumentMessage} ${matcherMessage}`; + } + + function colorDiffText(diff) { + const objects = map(diff, function (part) { + let text = part.value; + if (part.added) { + text = color.green(text); + } else if (part.removed) { + text = color.red(text); + } + if (diff.length === 2) { + text += " "; // format simple diffs + } + return text; + }); + return join(objects, ""); + } + + function quoteStringValue(value) { + if (typeof value === "string") { + return JSON.stringify(value); + } + return value; + } + + module.exports = { + c: function (spyInstance) { + return timesInWords(spyInstance.callCount); + }, + + n: function (spyInstance) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return spyInstance.toString(); + }, + + D: function (spyInstance, args) { + let message = ""; + + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + // describe multiple calls + if (l > 1) { + message += `\nCall ${i + 1}:`; + } + const calledArgs = spyInstance.getCall(i).args; + const expectedArgs = slice(args); + + for ( + let j = 0; + j < calledArgs.length || j < expectedArgs.length; + ++j + ) { + let calledArg = calledArgs[j]; + let expectedArg = expectedArgs[j]; + if (calledArg) { + calledArg = quoteStringValue(calledArg); + } + + if (expectedArg) { + expectedArg = quoteStringValue(expectedArg); + } + + message += "\n"; + + const calledArgMessage = + j < calledArgs.length ? inspect(calledArg) : ""; + if (match.isMatcher(expectedArg)) { + message += colorSinonMatchText( + expectedArg, + calledArg, + calledArgMessage + ); + } else { + const expectedArgMessage = + j < expectedArgs.length ? inspect(expectedArg) : ""; + const diff = jsDiff.diffJson( + calledArgMessage, + expectedArgMessage + ); + message += colorDiffText(diff); + } + } + } + + return message; + }, + + C: function (spyInstance) { + const calls = []; + + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + let stringifiedCall = ` ${spyInstance.getCall(i).toString()}`; + if (/\n/.test(calls[i - 1])) { + stringifiedCall = `\n${stringifiedCall}`; + } + push(calls, stringifiedCall); + } + + return calls.length > 0 ? `\n${join(calls, "\n")}` : ""; + }, + + t: function (spyInstance) { + const objects = []; + + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + push(objects, inspect(spyInstance.thisValues[i])); + } + + return join(objects, ", "); + }, + + "*": function (spyInstance, args) { + return join( + map(args, function (arg) { + return inspect(arg); + }), + ", " + ); + }, + }; + + },{"./color":5,"./util/core/times-in-words":35,"@sinonjs/commons":47,"@sinonjs/samsam":87,"diff":113,"util":112}],20:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const createProxy = require("./proxy"); + const extend = require("./util/core/extend"); + const functionName = require("@sinonjs/commons").functionName; + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const isEsModule = require("./util/core/is-es-module"); + const proxyCallUtil = require("./proxy-call-util"); + const walkObject = require("./util/core/walk-object"); + const wrapMethod = require("./util/core/wrap-method"); + const valueToString = require("@sinonjs/commons").valueToString; + + /* cache references to library methods so that they also can be stubbed without problems */ + const forEach = arrayProto.forEach; + const pop = arrayProto.pop; + const push = arrayProto.push; + const slice = arrayProto.slice; + const filter = Array.prototype.filter; + + let uuid = 0; + + function matches(fake, args, strict) { + const margs = fake.matchingArguments; + if ( + margs.length <= args.length && + deepEqual(slice(args, 0, margs.length), margs) + ) { + return !strict || margs.length === args.length; + } + return false; + } + + // Public API + const spyApi = { + withArgs: function () { + const args = slice(arguments); + const matching = pop(this.matchingFakes(args, true)); + if (matching) { + return matching; + } + + const original = this; + const fake = this.instantiateFake(); + fake.matchingArguments = args; + fake.parent = this; + push(this.fakes, fake); + + fake.withArgs = function () { + return original.withArgs.apply(original, arguments); + }; + + forEach(original.args, function (arg, i) { + if (!matches(fake, arg)) { + return; + } + + proxyCallUtil.incrementCallCount(fake); + push(fake.thisValues, original.thisValues[i]); + push(fake.args, arg); + push(fake.returnValues, original.returnValues[i]); + push(fake.exceptions, original.exceptions[i]); + push(fake.callIds, original.callIds[i]); + }); + + proxyCallUtil.createCallProperties(fake); + + return fake; + }, + + // Override proxy default implementation + matchingFakes: function (args, strict) { + return filter.call(this.fakes, function (fake) { + return matches(fake, args, strict); + }); + }, + }; + + /* eslint-disable @sinonjs/no-prototype-methods/no-prototype-methods */ + const delegateToCalls = proxyCallUtil.delegateToCalls; + delegateToCalls(spyApi, "callArg", false, "callArgWith", true, function () { + throw new Error( + `${this.toString()} cannot call arg since it was not yet invoked.` + ); + }); + spyApi.callArgWith = spyApi.callArg; + delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", true, function () { + throw new Error( + `${this.toString()} cannot call arg since it was not yet invoked.` + ); + }); + spyApi.callArgOnWith = spyApi.callArgOn; + delegateToCalls(spyApi, "throwArg", false, "throwArg", false, function () { + throw new Error( + `${this.toString()} cannot throw arg since it was not yet invoked.` + ); + }); + delegateToCalls(spyApi, "yield", false, "yield", true, function () { + throw new Error( + `${this.toString()} cannot yield since it was not yet invoked.` + ); + }); + // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. + spyApi.invokeCallback = spyApi.yield; + delegateToCalls(spyApi, "yieldOn", false, "yieldOn", true, function () { + throw new Error( + `${this.toString()} cannot yield since it was not yet invoked.` + ); + }); + delegateToCalls(spyApi, "yieldTo", false, "yieldTo", true, function (property) { + throw new Error( + `${this.toString()} cannot yield to '${valueToString( + property + )}' since it was not yet invoked.` + ); + }); + delegateToCalls( + spyApi, + "yieldToOn", + false, + "yieldToOn", + true, + function (property) { + throw new Error( + `${this.toString()} cannot yield to '${valueToString( + property + )}' since it was not yet invoked.` + ); + } + ); + + function createSpy(func) { + let name; + let funk = func; + + if (typeof funk !== "function") { + funk = function () { + return; + }; + } else { + name = functionName(funk); + } + + const proxy = createProxy(funk, funk); + + // Inherit spy API: + extend.nonEnum(proxy, spyApi); + extend.nonEnum(proxy, { + displayName: name || "spy", + fakes: [], + instantiateFake: createSpy, + id: `spy#${uuid++}`, + }); + return proxy; + } + + function spy(object, property, types) { + if (isEsModule(object)) { + throw new TypeError("ES Modules cannot be spied"); + } + + if (!property && typeof object === "function") { + return createSpy(object); + } + + if (!property && typeof object === "object") { + return walkObject(spy, object); + } + + if (!object && !property) { + return createSpy(function () { + return; + }); + } + + if (!types) { + return wrapMethod(object, property, createSpy(object[property])); + } + + const descriptor = {}; + const methodDesc = getPropertyDescriptor(object, property); + + forEach(types, function (type) { + descriptor[type] = createSpy(methodDesc[type]); + }); + + return wrapMethod(object, property, descriptor); + } + + extend(spy, spyApi); + module.exports = spy; + + },{"./proxy":16,"./proxy-call-util":13,"./util/core/extend":25,"./util/core/get-property-descriptor":28,"./util/core/is-es-module":29,"./util/core/walk-object":37,"./util/core/wrap-method":39,"@sinonjs/commons":47,"@sinonjs/samsam":87}],21:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const behavior = require("./behavior"); + const behaviors = require("./default-behaviors"); + const createProxy = require("./proxy"); + const functionName = require("@sinonjs/commons").functionName; + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const isNonExistentProperty = require("./util/core/is-non-existent-property"); + const spy = require("./spy"); + const extend = require("./util/core/extend"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const isEsModule = require("./util/core/is-es-module"); + const sinonType = require("./util/core/sinon-type"); + const wrapMethod = require("./util/core/wrap-method"); + const throwOnFalsyObject = require("./throw-on-falsy-object"); + const valueToString = require("@sinonjs/commons").valueToString; + const walkObject = require("./util/core/walk-object"); + + const forEach = arrayProto.forEach; + const pop = arrayProto.pop; + const slice = arrayProto.slice; + const sort = arrayProto.sort; + + let uuid = 0; + + function createStub(originalFunc) { + // eslint-disable-next-line prefer-const + let proxy; + + function functionStub() { + const args = slice(arguments); + const matchings = proxy.matchingFakes(args); + + const fnStub = + pop( + sort(matchings, function (a, b) { + return ( + a.matchingArguments.length - b.matchingArguments.length + ); + }) + ) || proxy; + return getCurrentBehavior(fnStub).invoke(this, arguments); + } + + proxy = createProxy(functionStub, originalFunc || functionStub); + // Inherit spy API: + extend.nonEnum(proxy, spy); + // Inherit stub API: + extend.nonEnum(proxy, stub); + + const name = originalFunc ? functionName(originalFunc) : null; + extend.nonEnum(proxy, { + fakes: [], + instantiateFake: createStub, + displayName: name || "stub", + defaultBehavior: null, + behaviors: [], + id: `stub#${uuid++}`, + }); + + sinonType.set(proxy, "stub"); + + return proxy; + } + + function stub(object, property) { + if (arguments.length > 2) { + throw new TypeError( + "stub(obj, 'meth', fn) has been removed, see documentation" + ); + } + + if (isEsModule(object)) { + throw new TypeError("ES Modules cannot be stubbed"); + } + + throwOnFalsyObject.apply(null, arguments); + + if (isNonExistentProperty(object, property)) { + throw new TypeError( + `Cannot stub non-existent property ${valueToString(property)}` + ); + } + + const actualDescriptor = getPropertyDescriptor(object, property); + + assertValidPropertyDescriptor(actualDescriptor, property); + + const isObjectOrFunction = + typeof object === "object" || typeof object === "function"; + const isStubbingEntireObject = + typeof property === "undefined" && isObjectOrFunction; + const isCreatingNewStub = !object && typeof property === "undefined"; + const isStubbingNonFuncProperty = + isObjectOrFunction && + typeof property !== "undefined" && + (typeof actualDescriptor === "undefined" || + typeof actualDescriptor.value !== "function"); + + if (isStubbingEntireObject) { + return walkObject(stub, object); + } + + if (isCreatingNewStub) { + return createStub(); + } + + const func = + typeof actualDescriptor.value === "function" + ? actualDescriptor.value + : null; + const s = createStub(func); + + extend.nonEnum(s, { + rootObj: object, + propName: property, + shadowsPropOnPrototype: !actualDescriptor.isOwn, + restore: function restore() { + if (actualDescriptor !== undefined && actualDescriptor.isOwn) { + Object.defineProperty(object, property, actualDescriptor); + return; + } + + delete object[property]; + }, + }); + + return isStubbingNonFuncProperty ? s : wrapMethod(object, property, s); + } + + function assertValidPropertyDescriptor(descriptor, property) { + if (!descriptor || !property) { + return; + } + if (descriptor.isOwn && !descriptor.configurable && !descriptor.writable) { + throw new TypeError( + `Descriptor for property ${property} is non-configurable and non-writable` + ); + } + if ((descriptor.get || descriptor.set) && !descriptor.configurable) { + throw new TypeError( + `Descriptor for accessor property ${property} is non-configurable` + ); + } + if (isDataDescriptor(descriptor) && !descriptor.writable) { + throw new TypeError( + `Descriptor for data property ${property} is non-writable` + ); + } + } + + function isDataDescriptor(descriptor) { + return ( + !descriptor.value && + !descriptor.writable && + !descriptor.set && + !descriptor.get + ); + } + + /*eslint-disable no-use-before-define*/ + function getParentBehaviour(stubInstance) { + return stubInstance.parent && getCurrentBehavior(stubInstance.parent); + } + + function getDefaultBehavior(stubInstance) { + return ( + stubInstance.defaultBehavior || + getParentBehaviour(stubInstance) || + behavior.create(stubInstance) + ); + } + + function getCurrentBehavior(stubInstance) { + const currentBehavior = stubInstance.behaviors[stubInstance.callCount - 1]; + return currentBehavior && currentBehavior.isPresent() + ? currentBehavior + : getDefaultBehavior(stubInstance); + } + /*eslint-enable no-use-before-define*/ + + const proto = { + resetBehavior: function () { + this.defaultBehavior = null; + this.behaviors = []; + + delete this.returnValue; + delete this.returnArgAt; + delete this.throwArgAt; + delete this.resolveArgAt; + delete this.fakeFn; + this.returnThis = false; + this.resolveThis = false; + + forEach(this.fakes, function (fake) { + fake.resetBehavior(); + }); + }, + + reset: function () { + this.resetHistory(); + this.resetBehavior(); + }, + + onCall: function onCall(index) { + if (!this.behaviors[index]) { + this.behaviors[index] = behavior.create(this); + } + + return this.behaviors[index]; + }, + + onFirstCall: function onFirstCall() { + return this.onCall(0); + }, + + onSecondCall: function onSecondCall() { + return this.onCall(1); + }, + + onThirdCall: function onThirdCall() { + return this.onCall(2); + }, + + withArgs: function withArgs() { + const fake = spy.withArgs.apply(this, arguments); + if (this.defaultBehavior && this.defaultBehavior.promiseLibrary) { + fake.defaultBehavior = + fake.defaultBehavior || behavior.create(fake); + fake.defaultBehavior.promiseLibrary = + this.defaultBehavior.promiseLibrary; + } + return fake; + }, + }; + + forEach(Object.keys(behavior), function (method) { + if ( + hasOwnProperty(behavior, method) && + !hasOwnProperty(proto, method) && + method !== "create" && + method !== "invoke" + ) { + proto[method] = behavior.createBehavior(method); + } + }); + + forEach(Object.keys(behaviors), function (method) { + if (hasOwnProperty(behaviors, method) && !hasOwnProperty(proto, method)) { + behavior.addBehavior(stub, method, behaviors[method]); + } + }); + + extend(stub, proto); + module.exports = stub; + + },{"./behavior":3,"./default-behaviors":8,"./proxy":16,"./spy":20,"./throw-on-falsy-object":22,"./util/core/extend":25,"./util/core/get-property-descriptor":28,"./util/core/is-es-module":29,"./util/core/is-non-existent-property":30,"./util/core/sinon-type":34,"./util/core/walk-object":37,"./util/core/wrap-method":39,"@sinonjs/commons":47}],22:[function(require,module,exports){ + const valueToString = require("@sinonjs/commons").valueToString; + + function throwOnFalsyObject(object, property) { + if (property && !object) { + const type = object === null ? "null" : "undefined"; + throw new Error( + `Trying to stub property '${valueToString(property)}' of ${type}` + ); + } + } + + module.exports = throwOnFalsyObject; + + },{"@sinonjs/commons":47}],23:[function(require,module,exports){ + + module.exports = { + injectInto: null, + properties: [ + "spy", + "stub", + "mock", + "clock", + "server", + "requests", + "fake", + "define", + "replace", + "replaceSetter", + "replaceGetter", + "createStubInstance", + ], + useFakeTimers: true, + useFakeServer: true, + }; + + },{}],24:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const reduce = arrayProto.reduce; + + module.exports = function exportAsyncBehaviors(behaviorMethods) { + return reduce( + Object.keys(behaviorMethods), + function (acc, method) { + // need to avoid creating another async versions of the newly added async methods + if (method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { + acc[`${method}Async`] = function () { + const result = behaviorMethods[method].apply( + this, + arguments + ); + this.callbackAsync = true; + return result; + }; + } + return acc; + }, + {} + ); + }; + + },{"@sinonjs/commons":47}],25:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + + const join = arrayProto.join; + const push = arrayProto.push; + + // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug + const hasDontEnumBug = (function () { + const obj = { + constructor: function () { + return "0"; + }, + toString: function () { + return "1"; + }, + valueOf: function () { + return "2"; + }, + toLocaleString: function () { + return "3"; + }, + prototype: function () { + return "4"; + }, + isPrototypeOf: function () { + return "5"; + }, + propertyIsEnumerable: function () { + return "6"; + }, + hasOwnProperty: function () { + return "7"; + }, + length: function () { + return "8"; + }, + unique: function () { + return "9"; + }, + }; + + const result = []; + for (const prop in obj) { + if (hasOwnProperty(obj, prop)) { + push(result, obj[prop]()); + } + } + return join(result, "") !== "0123456789"; + })(); + + /** + * + * @param target + * @param sources + * @param doCopy + * @returns {*} target + */ + function extendCommon(target, sources, doCopy) { + let source, i, prop; + + for (i = 0; i < sources.length; i++) { + source = sources[i]; + + for (prop in source) { + if (hasOwnProperty(source, prop)) { + doCopy(target, source, prop); + } + } + + // Make sure we copy (own) toString method even when in JScript with DontEnum bug + // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug + if ( + hasDontEnumBug && + hasOwnProperty(source, "toString") && + source.toString !== target.toString + ) { + target.toString = source.toString; + } + } + + return target; + } + + /** + * Public: Extend target in place with all (own) properties, except 'name' when [[writable]] is false, + * from sources in-order. Thus, last source will override properties in previous sources. + * + * @param {object} target - The Object to extend + * @param {object[]} sources - Objects to copy properties from. + * @returns {object} the extended target + */ + module.exports = function extend(target, ...sources) { + return extendCommon( + target, + sources, + function copyValue(dest, source, prop) { + const destOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( + dest, + prop + ); + const sourceOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( + source, + prop + ); + + if (prop === "name" && !destOwnPropertyDescriptor.writable) { + return; + } + const descriptors = { + configurable: sourceOwnPropertyDescriptor.configurable, + enumerable: sourceOwnPropertyDescriptor.enumerable, + }; + /* + if the sorce has an Accessor property copy over the accessor functions (get and set) + data properties has writable attribute where as accessor property don't + REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties + */ + + if (hasOwnProperty(sourceOwnPropertyDescriptor, "writable")) { + descriptors.writable = sourceOwnPropertyDescriptor.writable; + descriptors.value = sourceOwnPropertyDescriptor.value; + } else { + if (sourceOwnPropertyDescriptor.get) { + descriptors.get = + sourceOwnPropertyDescriptor.get.bind(dest); + } + if (sourceOwnPropertyDescriptor.set) { + descriptors.set = + sourceOwnPropertyDescriptor.set.bind(dest); + } + } + Object.defineProperty(dest, prop, descriptors); + } + ); + }; + + /** + * Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will + * override properties in previous sources. Define the properties as non enumerable. + * + * @param {object} target - The Object to extend + * @param {object[]} sources - Objects to copy properties from. + * @returns {object} the extended target + */ + module.exports.nonEnum = function extendNonEnum(target, ...sources) { + return extendCommon( + target, + sources, + function copyProperty(dest, source, prop) { + Object.defineProperty(dest, prop, { + value: source[prop], + enumerable: false, + configurable: true, + writable: true, + }); + } + ); + }; + + },{"@sinonjs/commons":47}],26:[function(require,module,exports){ + + module.exports = function toString() { + let i, prop, thisValue; + if (this.getCall && this.callCount) { + i = this.callCount; + + while (i--) { + thisValue = this.getCall(i).thisValue; + + // eslint-disable-next-line guard-for-in + for (prop in thisValue) { + try { + if (thisValue[prop] === this) { + return prop; + } + } catch (e) { + // no-op - accessing props can throw an error, nothing to do here + } + } + } + } + + return this.displayName || "sinon fake"; + }; + + },{}],27:[function(require,module,exports){ + + /* istanbul ignore next : not testing that setTimeout works */ + function nextTick(callback) { + setTimeout(callback, 0); + } + + module.exports = function getNextTick(process, setImmediate) { + if (typeof process === "object" && typeof process.nextTick === "function") { + return process.nextTick; + } + + if (typeof setImmediate === "function") { + return setImmediate; + } + + return nextTick; + }; + + },{}],28:[function(require,module,exports){ + + /* eslint-disable jsdoc/valid-types */ + /* + * The following type def is strictly an illegal JSDoc, but the expression forms a + * legal Typescript union type and is understood by Visual Studio and the IntelliJ + * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these + * days for that reason (and the fact that JSDoc is essentially unmaintained) + */ + + /** + * @typedef {{isOwn: boolean} & PropertyDescriptor} SinonPropertyDescriptor + * a slightly enriched property descriptor + * @property {boolean} isOwn true if the descriptor is owned by this object, false if it comes from the prototype + */ + /* eslint-enable jsdoc/valid-types */ + + /** + * Returns a slightly modified property descriptor that one can tell is from the object or the prototype + * + * @param {*} object + * @param {string} property + * @returns {SinonPropertyDescriptor} + */ + function getPropertyDescriptor(object, property) { + let proto = object; + let descriptor; + const isOwn = Boolean( + object && Object.getOwnPropertyDescriptor(object, property) + ); + + while ( + proto && + !(descriptor = Object.getOwnPropertyDescriptor(proto, property)) + ) { + proto = Object.getPrototypeOf(proto); + } + + if (descriptor) { + descriptor.isOwn = isOwn; + } + + return descriptor; + } + + module.exports = getPropertyDescriptor; + + },{}],29:[function(require,module,exports){ + + /** + * Verify if an object is a ECMAScript Module + * + * As the exports from a module is immutable we cannot alter the exports + * using spies or stubs. Let the consumer know this to avoid bug reports + * on weird error messages. + * + * @param {object} object The object to examine + * @returns {boolean} true when the object is a module + */ + module.exports = function (object) { + return ( + object && + typeof Symbol !== "undefined" && + object[Symbol.toStringTag] === "Module" && + Object.isSealed(object) + ); + }; + + },{}],30:[function(require,module,exports){ + + /** + * @param {*} object + * @param {string} property + * @returns {boolean} whether a prop exists in the prototype chain + */ + function isNonExistentProperty(object, property) { + return Boolean( + object && typeof property !== "undefined" && !(property in object) + ); + } + + module.exports = isNonExistentProperty; + + },{}],31:[function(require,module,exports){ + + const getPropertyDescriptor = require("./get-property-descriptor"); + + function isPropertyConfigurable(obj, propName) { + const propertyDescriptor = getPropertyDescriptor(obj, propName); + + return propertyDescriptor ? propertyDescriptor.configurable : true; + } + + module.exports = isPropertyConfigurable; + + },{"./get-property-descriptor":28}],32:[function(require,module,exports){ + + function isRestorable(obj) { + return ( + typeof obj === "function" && + typeof obj.restore === "function" && + obj.restore.sinon + ); + } + + module.exports = isRestorable; + + },{}],33:[function(require,module,exports){ + + const globalObject = require("@sinonjs/commons").global; + const getNextTick = require("./get-next-tick"); + + module.exports = getNextTick(globalObject.process, globalObject.setImmediate); + + },{"./get-next-tick":27,"@sinonjs/commons":47}],34:[function(require,module,exports){ + + const sinonTypeSymbolProperty = Symbol("SinonType"); + + module.exports = { + /** + * Set the type of a Sinon object to make it possible to identify it later at runtime + * + * @param {object|Function} object object/function to set the type on + * @param {string} type the named type of the object/function + */ + set(object, type) { + Object.defineProperty(object, sinonTypeSymbolProperty, { + value: type, + configurable: false, + enumerable: false, + }); + }, + get(object) { + return object && object[sinonTypeSymbolProperty]; + }, + }; + + },{}],35:[function(require,module,exports){ + + const array = [null, "once", "twice", "thrice"]; + + module.exports = function timesInWords(count) { + return array[count] || `${count || 0} times`; + }; + + },{}],36:[function(require,module,exports){ + + const forEach = Array.prototype.forEach; + + function usePromiseLibrary(library, fakes) { + if (typeof library === "undefined") { + return; + } + + if (Array.isArray(fakes)) { + forEach.call(fakes, usePromiseLibrary.bind(null, library)); + + return; + } + + if (typeof fakes.usingPromise === "function") { + fakes.usingPromise(library); + } + } + + module.exports = usePromiseLibrary; + + },{}],37:[function(require,module,exports){ + + const functionName = require("@sinonjs/commons").functionName; + + const getPropertyDescriptor = require("./get-property-descriptor"); + const walk = require("./walk"); + + /** + * A utility that allows traversing an object, applying mutating functions on the properties + * + * @param {Function} mutator called on each property + * @param {object} object the object we are walking over + * @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property + * @returns {void} nothing + */ + function walkObject(mutator, object, filter) { + let called = false; + const name = functionName(mutator); + + if (!object) { + throw new Error( + `Trying to ${name} object but received ${String(object)}` + ); + } + + walk(object, function (prop, propOwner) { + // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object + // is not Object.prototype + if ( + propOwner !== Object.prototype && + prop !== "constructor" && + typeof getPropertyDescriptor(propOwner, prop).value === "function" + ) { + if (filter) { + if (filter(object, prop)) { + called = true; + mutator(object, prop); + } + } else { + called = true; + mutator(object, prop); + } + } + }); + + if (!called) { + throw new Error( + `Found no methods on object to which we could apply mutations` + ); + } + + return object; + } + + module.exports = walkObject; + + },{"./get-property-descriptor":28,"./walk":38,"@sinonjs/commons":47}],38:[function(require,module,exports){ + + const forEach = require("@sinonjs/commons").prototypes.array.forEach; + + function walkInternal(obj, iterator, context, originalObj, seen) { + let prop; + const proto = Object.getPrototypeOf(obj); + + if (typeof Object.getOwnPropertyNames !== "function") { + // We explicitly want to enumerate through all of the prototype's properties + // in this case, therefore we deliberately leave out an own property check. + /* eslint-disable-next-line guard-for-in */ + for (prop in obj) { + iterator.call(context, obj[prop], prop, obj); + } + + return; + } + + forEach(Object.getOwnPropertyNames(obj), function (k) { + if (seen[k] !== true) { + seen[k] = true; + const target = + typeof Object.getOwnPropertyDescriptor(obj, k).get === + "function" + ? originalObj + : obj; + iterator.call(context, k, target); + } + }); + + if (proto) { + walkInternal(proto, iterator, context, originalObj, seen); + } + } + + /* Walks the prototype chain of an object and iterates over every own property + * name encountered. The iterator is called in the same fashion that Array.prototype.forEach + * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional + * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will + * default to using a simple for..in loop. + * + * obj - The object to walk the prototype chain for. + * iterator - The function to be called on each pass of the walk. + * context - (Optional) When given, the iterator will be called with this object as the receiver. + */ + module.exports = function walk(obj, iterator, context) { + return walkInternal(obj, iterator, context, obj, {}); + }; + + },{"@sinonjs/commons":47}],39:[function(require,module,exports){ + + // eslint-disable-next-line no-empty-function + const noop = () => {}; + const getPropertyDescriptor = require("./get-property-descriptor"); + const extend = require("./extend"); + const sinonType = require("./sinon-type"); + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const valueToString = require("@sinonjs/commons").valueToString; + const push = require("@sinonjs/commons").prototypes.array.push; + + function isFunction(obj) { + return ( + typeof obj === "function" || + Boolean(obj && obj.constructor && obj.call && obj.apply) + ); + } + + function mirrorProperties(target, source) { + for (const prop in source) { + if (!hasOwnProperty(target, prop)) { + target[prop] = source[prop]; + } + } + } + + function getAccessor(object, property, method) { + const accessors = ["get", "set"]; + const descriptor = getPropertyDescriptor(object, property); + + for (let i = 0; i < accessors.length; i++) { + if ( + descriptor[accessors[i]] && + descriptor[accessors[i]].name === method.name + ) { + return accessors[i]; + } + } + return null; + } + + // Cheap way to detect if we have ES5 support. + const hasES5Support = "keys" in Object; + + module.exports = function wrapMethod(object, property, method) { + if (!object) { + throw new TypeError("Should wrap property of object"); + } + + if (typeof method !== "function" && typeof method !== "object") { + throw new TypeError( + "Method wrapper should be a function or a property descriptor" + ); + } + + function checkWrappedMethod(wrappedMethod) { + let error; + + if (!isFunction(wrappedMethod)) { + error = new TypeError( + `Attempted to wrap ${typeof wrappedMethod} property ${valueToString( + property + )} as function` + ); + } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) { + error = new TypeError( + `Attempted to wrap ${valueToString( + property + )} which is already wrapped` + ); + } else if (wrappedMethod.calledBefore) { + const verb = wrappedMethod.returns ? "stubbed" : "spied on"; + error = new TypeError( + `Attempted to wrap ${valueToString( + property + )} which is already ${verb}` + ); + } + + if (error) { + if (wrappedMethod && wrappedMethod.stackTraceError) { + error.stack += `\n--------------\n${wrappedMethod.stackTraceError.stack}`; + } + throw error; + } + } + + let error, wrappedMethod, i, wrappedMethodDesc, target, accessor; + + const wrappedMethods = []; + + function simplePropertyAssignment() { + wrappedMethod = object[property]; + checkWrappedMethod(wrappedMethod); + object[property] = method; + method.displayName = property; + } + + // Firefox has a problem when using hasOwn.call on objects from other frames. + const owned = object.hasOwnProperty + ? object.hasOwnProperty(property) // eslint-disable-line @sinonjs/no-prototype-methods/no-prototype-methods + : hasOwnProperty(object, property); + + if (hasES5Support) { + const methodDesc = + typeof method === "function" ? { value: method } : method; + wrappedMethodDesc = getPropertyDescriptor(object, property); + + if (!wrappedMethodDesc) { + error = new TypeError( + `Attempted to wrap ${typeof wrappedMethod} property ${property} as function` + ); + } else if ( + wrappedMethodDesc.restore && + wrappedMethodDesc.restore.sinon + ) { + error = new TypeError( + `Attempted to wrap ${property} which is already wrapped` + ); + } + if (error) { + if (wrappedMethodDesc && wrappedMethodDesc.stackTraceError) { + error.stack += `\n--------------\n${wrappedMethodDesc.stackTraceError.stack}`; + } + throw error; + } + + const types = Object.keys(methodDesc); + for (i = 0; i < types.length; i++) { + wrappedMethod = wrappedMethodDesc[types[i]]; + checkWrappedMethod(wrappedMethod); + push(wrappedMethods, wrappedMethod); + } + + mirrorProperties(methodDesc, wrappedMethodDesc); + for (i = 0; i < types.length; i++) { + mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]); + } + + // you are not allowed to flip the configurable prop on an + // existing descriptor to anything but false (#2514) + if (!owned) { + methodDesc.configurable = true; + } + + Object.defineProperty(object, property, methodDesc); + + // catch failing assignment + // this is the converse of the check in `.restore` below + if (typeof method === "function" && object[property] !== method) { + // correct any wrongdoings caused by the defineProperty call above, + // such as adding new items (if object was a Storage object) + delete object[property]; + simplePropertyAssignment(); + } + } else { + simplePropertyAssignment(); + } + + extendObjectWithWrappedMethods(); + + function extendObjectWithWrappedMethods() { + for (i = 0; i < wrappedMethods.length; i++) { + accessor = getAccessor(object, property, wrappedMethods[i]); + target = accessor ? method[accessor] : method; + extend.nonEnum(target, { + displayName: property, + wrappedMethod: wrappedMethods[i], + + // Set up an Error object for a stack trace which can be used later to find what line of + // code the original method was created on. + stackTraceError: new Error("Stack Trace for original"), + + restore: restore, + }); + + target.restore.sinon = true; + if (!hasES5Support) { + mirrorProperties(target, wrappedMethod); + } + } + } + + function restore() { + accessor = getAccessor(object, property, this.wrappedMethod); + let descriptor; + // For prototype properties try to reset by delete first. + // If this fails (ex: localStorage on mobile safari) then force a reset + // via direct assignment. + if (accessor) { + if (!owned) { + try { + // In some cases `delete` may throw an error + delete object[property][accessor]; + } catch (e) {} // eslint-disable-line no-empty + // For native code functions `delete` fails without throwing an error + // on Chrome < 43, PhantomJS, etc. + } else if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + descriptor[accessor] = wrappedMethodDesc[accessor]; + Object.defineProperty(object, property, descriptor); + } + + if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + if (descriptor && descriptor.value === target) { + object[property][accessor] = this.wrappedMethod; + } + } else { + // Use strict equality comparison to check failures then force a reset + // via direct assignment. + if (object[property][accessor] === target) { + object[property][accessor] = this.wrappedMethod; + } + } + } else { + if (!owned) { + try { + delete object[property]; + } catch (e) {} // eslint-disable-line no-empty + } else if (hasES5Support) { + Object.defineProperty(object, property, wrappedMethodDesc); + } + + if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + if (descriptor && descriptor.value === target) { + object[property] = this.wrappedMethod; + } + } else { + if (object[property] === target) { + object[property] = this.wrappedMethod; + } + } + } + if (sinonType.get(object) === "stub-instance") { + // this is simply to avoid errors after restoring if something should + // traverse the object in a cleanup phase, ref #2477 + object[property] = noop; + } + } + + return method; + }; + + },{"./extend":25,"./get-property-descriptor":28,"./sinon-type":34,"@sinonjs/commons":47}],40:[function(require,module,exports){ + + const extend = require("./core/extend"); + const FakeTimers = require("@sinonjs/fake-timers"); + const globalObject = require("@sinonjs/commons").global; + + /** + * + * @param config + * @param globalCtx + */ + function createClock(config, globalCtx) { + let FakeTimersCtx = FakeTimers; + if (globalCtx !== null && typeof globalCtx === "object") { + FakeTimersCtx = FakeTimers.withGlobal(globalCtx); + } + const clock = FakeTimersCtx.install(config); + clock.restore = clock.uninstall; + return clock; + } + + /** + * + * @param obj + * @param globalPropName + */ + function addIfDefined(obj, globalPropName) { + const globalProp = globalObject[globalPropName]; + if (typeof globalProp !== "undefined") { + obj[globalPropName] = globalProp; + } + } + + /** + * @param {number|Date|object} dateOrConfig The unix epoch value to install with (default 0) + * @returns {object} Returns a lolex clock instance + */ + exports.useFakeTimers = function (dateOrConfig) { + const hasArguments = typeof dateOrConfig !== "undefined"; + const argumentIsDateLike = + (typeof dateOrConfig === "number" || dateOrConfig instanceof Date) && + arguments.length === 1; + const argumentIsObject = + dateOrConfig !== null && + typeof dateOrConfig === "object" && + arguments.length === 1; + + if (!hasArguments) { + return createClock({ + now: 0, + }); + } + + if (argumentIsDateLike) { + return createClock({ + now: dateOrConfig, + }); + } + + if (argumentIsObject) { + const config = extend.nonEnum({}, dateOrConfig); + const globalCtx = config.global; + delete config.global; + return createClock(config, globalCtx); + } + + throw new TypeError( + "useFakeTimers expected epoch or config object. See https://github.com/sinonjs/sinon" + ); + }; + + exports.clock = { + create: function (now) { + return FakeTimers.createClock(now); + }, + }; + + const timers = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval, + Date: Date, + }; + addIfDefined(timers, "setImmediate"); + addIfDefined(timers, "clearImmediate"); + + exports.timers = timers; + + },{"./core/extend":25,"@sinonjs/commons":47,"@sinonjs/fake-timers":60}],41:[function(require,module,exports){ + + var every = require("./prototypes/array").every; + + /** + * @private + */ + function hasCallsLeft(callMap, spy) { + if (callMap[spy.id] === undefined) { + callMap[spy.id] = 0; + } + + return callMap[spy.id] < spy.callCount; + } + + /** + * @private + */ + function checkAdjacentCalls(callMap, spy, index, spies) { + var calledBeforeNext = true; + + if (index !== spies.length - 1) { + calledBeforeNext = spy.calledBefore(spies[index + 1]); + } + + if (hasCallsLeft(callMap, spy) && calledBeforeNext) { + callMap[spy.id] += 1; + return true; + } + + return false; + } + + /** + * A Sinon proxy object (fake, spy, stub) + * + * @typedef {object} SinonProxy + * @property {Function} calledBefore - A method that determines if this proxy was called before another one + * @property {string} id - Some id + * @property {number} callCount - Number of times this proxy has been called + */ + + /** + * Returns true when the spies have been called in the order they were supplied in + * + * @param {SinonProxy[] | SinonProxy} spies An array of proxies, or several proxies as arguments + * @returns {boolean} true when spies are called in order, false otherwise + */ + function calledInOrder(spies) { + var callMap = {}; + // eslint-disable-next-line no-underscore-dangle + var _spies = arguments.length > 1 ? arguments : spies; + + return every(_spies, checkAdjacentCalls.bind(null, callMap)); + } + + module.exports = calledInOrder; + + },{"./prototypes/array":49}],42:[function(require,module,exports){ + + var functionName = require("./function-name"); + + /** + * Returns a display name for a value from a constructor + * + * @param {object} value A value to examine + * @returns {(string|null)} A string or null + */ + function className(value) { + return ( + (value.constructor && value.constructor.name) || + // The next branch is for IE11 support only: + // Because the name property is not set on the prototype + // of the Function object, we finally try to grab the + // name from its definition. This will never be reached + // in node, so we are not able to test this properly. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + (typeof value.constructor === "function" && + /* istanbul ignore next */ + functionName(value.constructor)) || + null + ); + } + + module.exports = className; + + },{"./function-name":45}],43:[function(require,module,exports){ + + /** + * Returns a function that will invoke the supplied function and print a + * deprecation warning to the console each time it is called. + * + * @param {Function} func + * @param {string} msg + * @returns {Function} + */ + exports.wrap = function (func, msg) { + var wrapped = function () { + exports.printWarning(msg); + return func.apply(this, arguments); + }; + if (func.prototype) { + wrapped.prototype = func.prototype; + } + return wrapped; + }; + + /** + * Returns a string which can be supplied to `wrap()` to notify the user that a + * particular part of the sinon API has been deprecated. + * + * @param {string} packageName + * @param {string} funcName + * @returns {string} + */ + exports.defaultMsg = function (packageName, funcName) { + return `${packageName}.${funcName} is deprecated and will be removed from the public API in a future version of ${packageName}.`; + }; + + /** + * Prints a warning on the console, when it exists + * + * @param {string} msg + * @returns {undefined} + */ + exports.printWarning = function (msg) { + /* istanbul ignore next */ + if (typeof process === "object" && process.emitWarning) { + // Emit Warnings in Node + process.emitWarning(msg); + } else if (console.info) { + console.info(msg); + } else { + console.log(msg); + } + }; + + },{}],44:[function(require,module,exports){ + + /** + * Returns true when fn returns true for all members of obj. + * This is an every implementation that works for all iterables + * + * @param {object} obj + * @param {Function} fn + * @returns {boolean} + */ + module.exports = function every(obj, fn) { + var pass = true; + + try { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + obj.forEach(function () { + if (!fn.apply(this, arguments)) { + // Throwing an error is the only way to break `forEach` + throw new Error(); + } + }); + } catch (e) { + pass = false; + } + + return pass; + }; + + },{}],45:[function(require,module,exports){ + + /** + * Returns a display name for a function + * + * @param {Function} func + * @returns {string} + */ + module.exports = function functionName(func) { + if (!func) { + return ""; + } + + try { + return ( + func.displayName || + func.name || + // Use function decomposition as a last resort to get function + // name. Does not rely on function decomposition to work - if it + // doesn't debugging will be slightly less informative + // (i.e. toString will say 'spy' rather than 'myFunc'). + (String(func).match(/function ([^\s(]+)/) || [])[1] + ); + } catch (e) { + // Stringify may fail and we might get an exception, as a last-last + // resort fall back to empty string. + return ""; + } + }; + + },{}],46:[function(require,module,exports){ + + /** + * A reference to the global object + * + * @type {object} globalObject + */ + var globalObject; + + /* istanbul ignore else */ + if (typeof commonjsGlobal$1 !== "undefined") { + // Node + globalObject = commonjsGlobal$1; + } else if (typeof window !== "undefined") { + // Browser + globalObject = window; + } else { + // WebWorker + globalObject = self; + } + + module.exports = globalObject; + + },{}],47:[function(require,module,exports){ + + module.exports = { + global: require("./global"), + calledInOrder: require("./called-in-order"), + className: require("./class-name"), + deprecated: require("./deprecated"), + every: require("./every"), + functionName: require("./function-name"), + orderByFirstCall: require("./order-by-first-call"), + prototypes: require("./prototypes"), + typeOf: require("./type-of"), + valueToString: require("./value-to-string"), + }; + + },{"./called-in-order":41,"./class-name":42,"./deprecated":43,"./every":44,"./function-name":45,"./global":46,"./order-by-first-call":48,"./prototypes":52,"./type-of":58,"./value-to-string":59}],48:[function(require,module,exports){ + + var sort = require("./prototypes/array").sort; + var slice = require("./prototypes/array").slice; + + /** + * @private + */ + function comparator(a, b) { + // uuid, won't ever be equal + var aCall = a.getCall(0); + var bCall = b.getCall(0); + var aId = (aCall && aCall.callId) || -1; + var bId = (bCall && bCall.callId) || -1; + + return aId < bId ? -1 : 1; + } + + /** + * A Sinon proxy object (fake, spy, stub) + * + * @typedef {object} SinonProxy + * @property {Function} getCall - A method that can return the first call + */ + + /** + * Sorts an array of SinonProxy instances (fake, spy, stub) by their first call + * + * @param {SinonProxy[] | SinonProxy} spies + * @returns {SinonProxy[]} + */ + function orderByFirstCall(spies) { + return sort(slice(spies), comparator); + } + + module.exports = orderByFirstCall; + + },{"./prototypes/array":49}],49:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Array.prototype); + + },{"./copy-prototype-methods":50}],50:[function(require,module,exports){ + + var call = Function.call; + var throwsOnProto = require("./throws-on-proto"); + + var disallowedProperties = [ + // ignore size because it throws from Map + "size", + "caller", + "callee", + "arguments", + ]; + + // This branch is covered when tests are run with `--disable-proto=throw`, + // however we can test both branches at the same time, so this is ignored + /* istanbul ignore next */ + if (throwsOnProto) { + disallowedProperties.push("__proto__"); + } + + module.exports = function copyPrototypeMethods(prototype) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return Object.getOwnPropertyNames(prototype).reduce(function ( + result, + name + ) { + if (disallowedProperties.includes(name)) { + return result; + } + + if (typeof prototype[name] !== "function") { + return result; + } + + result[name] = call.bind(prototype[name]); + + return result; + }, + Object.create(null)); + }; + + },{"./throws-on-proto":57}],51:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Function.prototype); + + },{"./copy-prototype-methods":50}],52:[function(require,module,exports){ + + module.exports = { + array: require("./array"), + function: require("./function"), + map: require("./map"), + object: require("./object"), + set: require("./set"), + string: require("./string"), + }; + + },{"./array":49,"./function":51,"./map":53,"./object":54,"./set":55,"./string":56}],53:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Map.prototype); + + },{"./copy-prototype-methods":50}],54:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Object.prototype); + + },{"./copy-prototype-methods":50}],55:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Set.prototype); + + },{"./copy-prototype-methods":50}],56:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(String.prototype); + + },{"./copy-prototype-methods":50}],57:[function(require,module,exports){ + + /** + * Is true when the environment causes an error to be thrown for accessing the + * __proto__ property. + * + * This is necessary in order to support `node --disable-proto=throw`. + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto + * + * @type {boolean} + */ + let throwsOnProto; + try { + const object = {}; + // eslint-disable-next-line no-proto, no-unused-expressions + object.__proto__; + throwsOnProto = false; + } catch (_) { + // This branch is covered when tests are run with `--disable-proto=throw`, + // however we can test both branches at the same time, so this is ignored + /* istanbul ignore next */ + throwsOnProto = true; + } + + module.exports = throwsOnProto; + + },{}],58:[function(require,module,exports){ + + var type = require("type-detect"); + + /** + * Returns the lower-case result of running type from type-detect on the value + * + * @param {*} value + * @returns {string} + */ + module.exports = function typeOf(value) { + return type(value).toLowerCase(); + }; + + },{"type-detect":150}],59:[function(require,module,exports){ + + /** + * Returns a string representation of the value + * + * @param {*} value + * @returns {string} + */ + function valueToString(value) { + if (value && value.toString) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return value.toString(); + } + return String(value); + } + + module.exports = valueToString; + + },{}],60:[function(require,module,exports){ + + const globalObject = require("@sinonjs/commons").global; + + /** + * @typedef {object} IdleDeadline + * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout + * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period + */ + + /** + * Queues a function to be called during a browser's idle periods + * + * @callback RequestIdleCallback + * @param {function(IdleDeadline)} callback + * @param {{timeout: number}} options - an options object + * @returns {number} the id + */ + + /** + * @callback NextTick + * @param {VoidVarArgsFunc} callback - the callback to run + * @param {...*} arguments - optional arguments to call the callback with + * @returns {void} + */ + + /** + * @callback SetImmediate + * @param {VoidVarArgsFunc} callback - the callback to run + * @param {...*} arguments - optional arguments to call the callback with + * @returns {NodeImmediate} + */ + + /** + * @callback VoidVarArgsFunc + * @param {...*} callback - the callback to run + * @returns {void} + */ + + /** + * @typedef RequestAnimationFrame + * @property {function(number):void} requestAnimationFrame + * @returns {number} - the id + */ + + /** + * @typedef Performance + * @property {function(): number} now + */ + + /* eslint-disable jsdoc/require-property-description */ + /** + * @typedef {object} Clock + * @property {number} now - the current time + * @property {Date} Date - the Date constructor + * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop + * @property {RequestIdleCallback} requestIdleCallback + * @property {function(number):void} cancelIdleCallback + * @property {setTimeout} setTimeout + * @property {clearTimeout} clearTimeout + * @property {NextTick} nextTick + * @property {queueMicrotask} queueMicrotask + * @property {setInterval} setInterval + * @property {clearInterval} clearInterval + * @property {SetImmediate} setImmediate + * @property {function(NodeImmediate):void} clearImmediate + * @property {function():number} countTimers + * @property {RequestAnimationFrame} requestAnimationFrame + * @property {function(number):void} cancelAnimationFrame + * @property {function():void} runMicrotasks + * @property {function(string | number): number} tick + * @property {function(string | number): Promise} tickAsync + * @property {function(): number} next + * @property {function(): Promise} nextAsync + * @property {function(): number} runAll + * @property {function(): number} runToFrame + * @property {function(): Promise} runAllAsync + * @property {function(): number} runToLast + * @property {function(): Promise} runToLastAsync + * @property {function(): void} reset + * @property {function(number | Date): void} setSystemTime + * @property {function(number): void} jump + * @property {Performance} performance + * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) + * @property {function(): void} uninstall Uninstall the clock. + * @property {Function[]} methods - the methods that are faked + * @property {boolean} [shouldClearNativeTimers] inherited from config + */ + /* eslint-enable jsdoc/require-property-description */ + + /** + * Configuration object for the `install` method. + * + * @typedef {object} Config + * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) + * @property {string[]} [toFake] names of the methods that should be faked. + * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() + * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) + * @property {number} [advanceTimeDelta] increment mocked time every <> ms (default: 20ms) + * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) + */ + + /* eslint-disable jsdoc/require-property-description */ + /** + * The internal structure to describe a scheduled fake timer + * + * @typedef {object} Timer + * @property {Function} func + * @property {*[]} args + * @property {number} delay + * @property {number} callAt + * @property {number} createdAt + * @property {boolean} immediate + * @property {number} id + * @property {Error} [error] + */ + + /** + * A Node timer + * + * @typedef {object} NodeImmediate + * @property {function(): boolean} hasRef + * @property {function(): NodeImmediate} ref + * @property {function(): NodeImmediate} unref + */ + /* eslint-enable jsdoc/require-property-description */ + + /* eslint-disable complexity */ + + /** + * Mocks available features in the specified global namespace. + * + * @param {*} _global Namespace to mock (e.g. `window`) + * @returns {FakeTimers} + */ + function withGlobal(_global) { + const userAgent = _global.navigator && _global.navigator.userAgent; + const isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1; + const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint + const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs + const NOOP = function () { + return undefined; + }; + const NOOP_ARRAY = function () { + return []; + }; + const timeoutResult = _global.setTimeout(NOOP, 0); + const addTimerReturnsObject = typeof timeoutResult === "object"; + const hrtimePresent = + _global.process && typeof _global.process.hrtime === "function"; + const hrtimeBigintPresent = + hrtimePresent && typeof _global.process.hrtime.bigint === "function"; + const nextTickPresent = + _global.process && typeof _global.process.nextTick === "function"; + const utilPromisify = _global.process && require("util").promisify; + const performancePresent = + _global.performance && typeof _global.performance.now === "function"; + const hasPerformancePrototype = + _global.Performance && + (typeof _global.Performance).match(/^(function|object)$/); + const hasPerformanceConstructorPrototype = + _global.performance && + _global.performance.constructor && + _global.performance.constructor.prototype; + const queueMicrotaskPresent = _global.hasOwnProperty("queueMicrotask"); + const requestAnimationFramePresent = + _global.requestAnimationFrame && + typeof _global.requestAnimationFrame === "function"; + const cancelAnimationFramePresent = + _global.cancelAnimationFrame && + typeof _global.cancelAnimationFrame === "function"; + const requestIdleCallbackPresent = + _global.requestIdleCallback && + typeof _global.requestIdleCallback === "function"; + const cancelIdleCallbackPresent = + _global.cancelIdleCallback && + typeof _global.cancelIdleCallback === "function"; + const setImmediatePresent = + _global.setImmediate && typeof _global.setImmediate === "function"; + + // Make properties writable in IE, as per + // https://www.adequatelygood.com/Replacing-setTimeout-Globally.html + /* eslint-disable no-self-assign */ + if (isRunningInIE) { + _global.setTimeout = _global.setTimeout; + _global.clearTimeout = _global.clearTimeout; + _global.setInterval = _global.setInterval; + _global.clearInterval = _global.clearInterval; + _global.Date = _global.Date; + } + + // setImmediate is not a standard function + // avoid adding the prop to the window object if not present + if (setImmediatePresent) { + _global.setImmediate = _global.setImmediate; + _global.clearImmediate = _global.clearImmediate; + } + /* eslint-enable no-self-assign */ + + _global.clearTimeout(timeoutResult); + + const NativeDate = _global.Date; + let uniqueTimerId = idCounterStart; + + /** + * @param {number} num + * @returns {boolean} + */ + function isNumberFinite(num) { + if (Number.isFinite) { + return Number.isFinite(num); + } + + return isFinite(num); + } + + let isNearInfiniteLimit = false; + + /** + * @param {Clock} clock + * @param {number} i + */ + function checkIsNearInfiniteLimit(clock, i) { + if (clock.loopLimit && i === clock.loopLimit - 1) { + isNearInfiniteLimit = true; + } + } + + /** + * + */ + function resetIsNearInfiniteLimit() { + isNearInfiniteLimit = false; + } + + /** + * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into + * number of milliseconds. This is used to support human-readable strings passed + * to clock.tick() + * + * @param {string} str + * @returns {number} + */ + function parseTime(str) { + if (!str) { + return 0; + } + + const strings = str.split(":"); + const l = strings.length; + let i = l; + let ms = 0; + let parsed; + + if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { + throw new Error( + "tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits" + ); + } + + while (i--) { + parsed = parseInt(strings[i], 10); + + if (parsed >= 60) { + throw new Error(`Invalid time ${str}`); + } + + ms += parsed * Math.pow(60, l - i - 1); + } + + return ms * 1000; + } + + /** + * Get the decimal part of the millisecond value as nanoseconds + * + * @param {number} msFloat the number of milliseconds + * @returns {number} an integer number of nanoseconds in the range [0,1e6) + * + * Example: nanoRemainer(123.456789) -> 456789 + */ + function nanoRemainder(msFloat) { + const modulo = 1e6; + const remainder = (msFloat * 1e6) % modulo; + const positiveRemainder = + remainder < 0 ? remainder + modulo : remainder; + + return Math.floor(positiveRemainder); + } + + /** + * Used to grok the `now` parameter to createClock. + * + * @param {Date|number} epoch the system time + * @returns {number} + */ + function getEpoch(epoch) { + if (!epoch) { + return 0; + } + if (typeof epoch.getTime === "function") { + return epoch.getTime(); + } + if (typeof epoch === "number") { + return epoch; + } + throw new TypeError("now should be milliseconds since UNIX epoch"); + } + + /** + * @param {number} from + * @param {number} to + * @param {Timer} timer + * @returns {boolean} + */ + function inRange(from, to, timer) { + return timer && timer.callAt >= from && timer.callAt <= to; + } + + /** + * @param {Clock} clock + * @param {Timer} job + */ + function getInfiniteLoopError(clock, job) { + const infiniteLoopError = new Error( + `Aborting after running ${clock.loopLimit} timers, assuming an infinite loop!` + ); + + if (!job.error) { + return infiniteLoopError; + } + + // pattern never matched in Node + const computedTargetPattern = /target\.*[<|(|[].*?[>|\]|)]\s*/; + let clockMethodPattern = new RegExp( + String(Object.keys(clock).join("|")) + ); + + if (addTimerReturnsObject) { + // node.js environment + clockMethodPattern = new RegExp( + `\\s+at (Object\\.)?(?:${Object.keys(clock).join("|")})\\s+` + ); + } + + let matchedLineIndex = -1; + job.error.stack.split("\n").some(function (line, i) { + // If we've matched a computed target line (e.g. setTimeout) then we + // don't need to look any further. Return true to stop iterating. + const matchedComputedTarget = line.match(computedTargetPattern); + /* istanbul ignore if */ + if (matchedComputedTarget) { + matchedLineIndex = i; + return true; + } + + // If we've matched a clock method line, then there may still be + // others further down the trace. Return false to keep iterating. + const matchedClockMethod = line.match(clockMethodPattern); + if (matchedClockMethod) { + matchedLineIndex = i; + return false; + } + + // If we haven't matched anything on this line, but we matched + // previously and set the matched line index, then we can stop. + // If we haven't matched previously, then we should keep iterating. + return matchedLineIndex >= 0; + }); + + const stack = `${infiniteLoopError}\n${job.type || "Microtask"} - ${ + job.func.name || "anonymous" + }\n${job.error.stack + .split("\n") + .slice(matchedLineIndex + 1) + .join("\n")}`; + + try { + Object.defineProperty(infiniteLoopError, "stack", { + value: stack, + }); + } catch (e) { + // noop + } + + return infiniteLoopError; + } + + /** + * @param {Date} target + * @param {Date} source + * @returns {Date} the target after modifications + */ + function mirrorDateProperties(target, source) { + let prop; + for (prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + + // set special now implementation + if (source.now) { + target.now = function now() { + return target.clock.now; + }; + } else { + delete target.now; + } + + // set special toSource implementation + if (source.toSource) { + target.toSource = function toSource() { + return source.toSource(); + }; + } else { + delete target.toSource; + } + + // set special toString implementation + target.toString = function toString() { + return source.toString(); + }; + + target.prototype = source.prototype; + target.parse = source.parse; + target.UTC = source.UTC; + target.prototype.toUTCString = source.prototype.toUTCString; + target.isFake = true; + + return target; + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function createDate() { + /** + * @param {number} year + * @param {number} month + * @param {number} date + * @param {number} hour + * @param {number} minute + * @param {number} second + * @param {number} ms + * @returns {Date} + */ + function ClockDate(year, month, date, hour, minute, second, ms) { + // the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2. + // This remains so in the 10th edition of 2019 as well. + if (!(this instanceof ClockDate)) { + return new NativeDate(ClockDate.clock.now).toString(); + } + + // if Date is called as a constructor with 'new' keyword + // Defensive and verbose to avoid potential harm in passing + // explicit undefined when user does not pass argument + switch (arguments.length) { + case 0: + return new NativeDate(ClockDate.clock.now); + case 1: + return new NativeDate(year); + case 2: + return new NativeDate(year, month); + case 3: + return new NativeDate(year, month, date); + case 4: + return new NativeDate(year, month, date, hour); + case 5: + return new NativeDate(year, month, date, hour, minute); + case 6: + return new NativeDate( + year, + month, + date, + hour, + minute, + second + ); + default: + return new NativeDate( + year, + month, + date, + hour, + minute, + second, + ms + ); + } + } + + return mirrorDateProperties(ClockDate, NativeDate); + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function enqueueJob(clock, job) { + // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob + if (!clock.jobs) { + clock.jobs = []; + } + clock.jobs.push(job); + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function runJobs(clock) { + // runs all microtick-deferred tasks - ecma262/#sec-runjobs + if (!clock.jobs) { + return; + } + for (let i = 0; i < clock.jobs.length; i++) { + const job = clock.jobs[i]; + job.func.apply(null, job.args); + + checkIsNearInfiniteLimit(clock, i); + if (clock.loopLimit && i > clock.loopLimit) { + throw getInfiniteLoopError(clock, job); + } + } + resetIsNearInfiniteLimit(); + clock.jobs = []; + } + + /** + * @param {Clock} clock + * @param {Timer} timer + * @returns {number} id of the created timer + */ + function addTimer(clock, timer) { + if (timer.func === undefined) { + throw new Error("Callback must be provided to timer calls"); + } + + if (addTimerReturnsObject) { + // Node.js environment + if (typeof timer.func !== "function") { + throw new TypeError( + `[ERR_INVALID_CALLBACK]: Callback must be a function. Received ${ + timer.func + } of type ${typeof timer.func}` + ); + } + } + + if (isNearInfiniteLimit) { + timer.error = new Error(); + } + + timer.type = timer.immediate ? "Immediate" : "Timeout"; + + if (timer.hasOwnProperty("delay")) { + if (typeof timer.delay !== "number") { + timer.delay = parseInt(timer.delay, 10); + } + + if (!isNumberFinite(timer.delay)) { + timer.delay = 0; + } + timer.delay = timer.delay > maxTimeout ? 1 : timer.delay; + timer.delay = Math.max(0, timer.delay); + } + + if (timer.hasOwnProperty("interval")) { + timer.type = "Interval"; + timer.interval = timer.interval > maxTimeout ? 1 : timer.interval; + } + + if (timer.hasOwnProperty("animation")) { + timer.type = "AnimationFrame"; + timer.animation = true; + } + + if (timer.hasOwnProperty("idleCallback")) { + timer.type = "IdleCallback"; + timer.idleCallback = true; + } + + if (!clock.timers) { + clock.timers = {}; + } + + timer.id = uniqueTimerId++; + timer.createdAt = clock.now; + timer.callAt = + clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); + + clock.timers[timer.id] = timer; + + if (addTimerReturnsObject) { + const res = { + refed: true, + ref: function () { + this.refed = true; + return res; + }, + unref: function () { + this.refed = false; + return res; + }, + hasRef: function () { + return this.refed; + }, + refresh: function () { + timer.callAt = + clock.now + + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); + + // it _might_ have been removed, but if not the assignment is perfectly fine + clock.timers[timer.id] = timer; + + return res; + }, + [Symbol.toPrimitive]: function () { + return timer.id; + }, + }; + return res; + } + + return timer.id; + } + + /* eslint consistent-return: "off" */ + /** + * Timer comparitor + * + * @param {Timer} a + * @param {Timer} b + * @returns {number} + */ + function compareTimers(a, b) { + // Sort first by absolute timing + if (a.callAt < b.callAt) { + return -1; + } + if (a.callAt > b.callAt) { + return 1; + } + + // Sort next by immediate, immediate timers take precedence + if (a.immediate && !b.immediate) { + return -1; + } + if (!a.immediate && b.immediate) { + return 1; + } + + // Sort next by creation time, earlier-created timers take precedence + if (a.createdAt < b.createdAt) { + return -1; + } + if (a.createdAt > b.createdAt) { + return 1; + } + + // Sort next by id, lower-id timers take precedence + if (a.id < b.id) { + return -1; + } + if (a.id > b.id) { + return 1; + } + + // As timer ids are unique, no fallback `0` is necessary + } + + /** + * @param {Clock} clock + * @param {number} from + * @param {number} to + * @returns {Timer} + */ + function firstTimerInRange(clock, from, to) { + const timers = clock.timers; + let timer = null; + let id, isInRange; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + isInRange = inRange(from, to, timers[id]); + + if ( + isInRange && + (!timer || compareTimers(timer, timers[id]) === 1) + ) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @returns {Timer} + */ + function firstTimer(clock) { + const timers = clock.timers; + let timer = null; + let id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === 1) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @returns {Timer} + */ + function lastTimer(clock) { + const timers = clock.timers; + let timer = null; + let id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === -1) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @param {Timer} timer + */ + function callTimer(clock, timer) { + if (typeof timer.interval === "number") { + clock.timers[timer.id].callAt += timer.interval; + } else { + delete clock.timers[timer.id]; + } + + if (typeof timer.func === "function") { + timer.func.apply(null, timer.args); + } else { + /* eslint no-eval: "off" */ + const eval2 = eval; + (function () { + eval2(timer.func); + })(); + } + } + + /** + * Gets clear handler name for a given timer type + * + * @param {string} ttype + */ + function getClearHandler(ttype) { + if (ttype === "IdleCallback" || ttype === "AnimationFrame") { + return `cancel${ttype}`; + } + return `clear${ttype}`; + } + + /** + * Gets schedule handler name for a given timer type + * + * @param {string} ttype + */ + function getScheduleHandler(ttype) { + if (ttype === "IdleCallback" || ttype === "AnimationFrame") { + return `request${ttype}`; + } + return `set${ttype}`; + } + + /** + * Creates an anonymous function to warn only once + */ + function createWarnOnce() { + let calls = 0; + return function (msg) { + // eslint-disable-next-line + !calls++ && console.warn(msg); + }; + } + const warnOnce = createWarnOnce(); + + /** + * @param {Clock} clock + * @param {number} timerId + * @param {string} ttype + */ + function clearTimer(clock, timerId, ttype) { + if (!timerId) { + // null appears to be allowed in most browsers, and appears to be + // relied upon by some libraries, like Bootstrap carousel + return; + } + + if (!clock.timers) { + clock.timers = {}; + } + + // in Node, the ID is stored as the primitive value for `Timeout` objects + // for `Immediate` objects, no ID exists, so it gets coerced to NaN + const id = Number(timerId); + + if (Number.isNaN(id) || id < idCounterStart) { + const handlerName = getClearHandler(ttype); + + if (clock.shouldClearNativeTimers === true) { + const nativeHandler = clock[`_${handlerName}`]; + return typeof nativeHandler === "function" + ? nativeHandler(timerId) + : undefined; + } + warnOnce( + `FakeTimers: ${handlerName} was invoked to clear a native timer instead of one created by this library.` + + "\nTo automatically clean-up native timers, use `shouldClearNativeTimers`." + ); + } + + if (clock.timers.hasOwnProperty(id)) { + // check that the ID matches a timer of the correct type + const timer = clock.timers[id]; + if ( + timer.type === ttype || + (timer.type === "Timeout" && ttype === "Interval") || + (timer.type === "Interval" && ttype === "Timeout") + ) { + delete clock.timers[id]; + } else { + const clear = getClearHandler(ttype); + const schedule = getScheduleHandler(timer.type); + throw new Error( + `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()` + ); + } + } + } + + /** + * @param {Clock} clock + * @param {Config} config + * @returns {Timer[]} + */ + function uninstall(clock, config) { + let method, i, l; + const installedHrTime = "_hrtime"; + const installedNextTick = "_nextTick"; + + for (i = 0, l = clock.methods.length; i < l; i++) { + method = clock.methods[i]; + if (method === "hrtime" && _global.process) { + _global.process.hrtime = clock[installedHrTime]; + } else if (method === "nextTick" && _global.process) { + _global.process.nextTick = clock[installedNextTick]; + } else if (method === "performance") { + const originalPerfDescriptor = Object.getOwnPropertyDescriptor( + clock, + `_${method}` + ); + if ( + originalPerfDescriptor && + originalPerfDescriptor.get && + !originalPerfDescriptor.set + ) { + Object.defineProperty( + _global, + method, + originalPerfDescriptor + ); + } else if (originalPerfDescriptor.configurable) { + _global[method] = clock[`_${method}`]; + } + } else { + if (_global[method] && _global[method].hadOwnProperty) { + _global[method] = clock[`_${method}`]; + } else { + try { + delete _global[method]; + } catch (ignore) { + /* eslint no-empty: "off" */ + } + } + } + } + + if (config.shouldAdvanceTime === true) { + _global.clearInterval(clock.attachedInterval); + } + + // Prevent multiple executions which will completely remove these props + clock.methods = []; + + // return pending timers, to enable checking what timers remained on uninstall + if (!clock.timers) { + return []; + } + return Object.keys(clock.timers).map(function mapper(key) { + return clock.timers[key]; + }); + } + + /** + * @param {object} target the target containing the method to replace + * @param {string} method the keyname of the method on the target + * @param {Clock} clock + */ + function hijackMethod(target, method, clock) { + clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call( + target, + method + ); + clock[`_${method}`] = target[method]; + + if (method === "Date") { + const date = mirrorDateProperties(clock[method], target[method]); + target[method] = date; + } else if (method === "performance") { + const originalPerfDescriptor = Object.getOwnPropertyDescriptor( + target, + method + ); + // JSDOM has a read only performance field so we have to save/copy it differently + if ( + originalPerfDescriptor && + originalPerfDescriptor.get && + !originalPerfDescriptor.set + ) { + Object.defineProperty( + clock, + `_${method}`, + originalPerfDescriptor + ); + + const perfDescriptor = Object.getOwnPropertyDescriptor( + clock, + method + ); + Object.defineProperty(target, method, perfDescriptor); + } else { + target[method] = clock[method]; + } + } else { + target[method] = function () { + return clock[method].apply(clock, arguments); + }; + + Object.defineProperties( + target[method], + Object.getOwnPropertyDescriptors(clock[method]) + ); + } + + target[method].clock = clock; + } + + /** + * @param {Clock} clock + * @param {number} advanceTimeDelta + */ + function doIntervalTick(clock, advanceTimeDelta) { + clock.tick(advanceTimeDelta); + } + + /** + * @typedef {object} Timers + * @property {setTimeout} setTimeout + * @property {clearTimeout} clearTimeout + * @property {setInterval} setInterval + * @property {clearInterval} clearInterval + * @property {Date} Date + * @property {SetImmediate=} setImmediate + * @property {function(NodeImmediate): void=} clearImmediate + * @property {function(number[]):number[]=} hrtime + * @property {NextTick=} nextTick + * @property {Performance=} performance + * @property {RequestAnimationFrame=} requestAnimationFrame + * @property {boolean=} queueMicrotask + * @property {function(number): void=} cancelAnimationFrame + * @property {RequestIdleCallback=} requestIdleCallback + * @property {function(number): void=} cancelIdleCallback + */ + + /** @type {Timers} */ + const timers = { + setTimeout: _global.setTimeout, + clearTimeout: _global.clearTimeout, + setInterval: _global.setInterval, + clearInterval: _global.clearInterval, + Date: _global.Date, + }; + + if (setImmediatePresent) { + timers.setImmediate = _global.setImmediate; + timers.clearImmediate = _global.clearImmediate; + } + + if (hrtimePresent) { + timers.hrtime = _global.process.hrtime; + } + + if (nextTickPresent) { + timers.nextTick = _global.process.nextTick; + } + + if (performancePresent) { + timers.performance = _global.performance; + } + + if (requestAnimationFramePresent) { + timers.requestAnimationFrame = _global.requestAnimationFrame; + } + + if (queueMicrotaskPresent) { + timers.queueMicrotask = true; + } + + if (cancelAnimationFramePresent) { + timers.cancelAnimationFrame = _global.cancelAnimationFrame; + } + + if (requestIdleCallbackPresent) { + timers.requestIdleCallback = _global.requestIdleCallback; + } + + if (cancelIdleCallbackPresent) { + timers.cancelIdleCallback = _global.cancelIdleCallback; + } + + const originalSetTimeout = _global.setImmediate || _global.setTimeout; + + /** + * @param {Date|number} [start] the system time - non-integer values are floored + * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll() + * @returns {Clock} + */ + function createClock(start, loopLimit) { + // eslint-disable-next-line no-param-reassign + start = Math.floor(getEpoch(start)); + // eslint-disable-next-line no-param-reassign + loopLimit = loopLimit || 1000; + let nanos = 0; + const adjustedSystemTime = [0, 0]; // [millis, nanoremainder] + + if (NativeDate === undefined) { + throw new Error( + "The global scope doesn't have a `Date` object" + + " (see https://github.com/sinonjs/sinon/issues/1852#issuecomment-419622780)" + ); + } + + const clock = { + now: start, + Date: createDate(), + loopLimit: loopLimit, + }; + + clock.Date.clock = clock; + + //eslint-disable-next-line jsdoc/require-jsdoc + function getTimeToNextFrame() { + return 16 - ((clock.now - start) % 16); + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function hrtime(prev) { + const millisSinceStart = clock.now - adjustedSystemTime[0] - start; + const secsSinceStart = Math.floor(millisSinceStart / 1000); + const remainderInNanos = + (millisSinceStart - secsSinceStart * 1e3) * 1e6 + + nanos - + adjustedSystemTime[1]; + + if (Array.isArray(prev)) { + if (prev[1] > 1e9) { + throw new TypeError( + "Number of nanoseconds can't exceed a billion" + ); + } + + const oldSecs = prev[0]; + let nanoDiff = remainderInNanos - prev[1]; + let secDiff = secsSinceStart - oldSecs; + + if (nanoDiff < 0) { + nanoDiff += 1e9; + secDiff -= 1; + } + + return [secDiff, nanoDiff]; + } + return [secsSinceStart, remainderInNanos]; + } + + function fakePerformanceNow() { + const hrt = hrtime(); + const millis = hrt[0] * 1000 + hrt[1] / 1e6; + return millis; + } + + if (hrtimeBigintPresent) { + hrtime.bigint = function () { + const parts = hrtime(); + return BigInt(parts[0]) * BigInt(1e9) + BigInt(parts[1]); // eslint-disable-line + }; + } + + clock.requestIdleCallback = function requestIdleCallback( + func, + timeout + ) { + let timeToNextIdlePeriod = 0; + + if (clock.countTimers() > 0) { + timeToNextIdlePeriod = 50; // const for now + } + + const result = addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: + typeof timeout === "undefined" + ? timeToNextIdlePeriod + : Math.min(timeout, timeToNextIdlePeriod), + idleCallback: true, + }); + + return Number(result); + }; + + clock.cancelIdleCallback = function cancelIdleCallback(timerId) { + return clearTimer(clock, timerId, "IdleCallback"); + }; + + clock.setTimeout = function setTimeout(func, timeout) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout, + }); + }; + if (typeof _global.Promise !== "undefined" && utilPromisify) { + clock.setTimeout[utilPromisify.custom] = + function promisifiedSetTimeout(timeout, arg) { + return new _global.Promise(function setTimeoutExecutor( + resolve + ) { + addTimer(clock, { + func: resolve, + args: [arg], + delay: timeout, + }); + }); + }; + } + + clock.clearTimeout = function clearTimeout(timerId) { + return clearTimer(clock, timerId, "Timeout"); + }; + + clock.nextTick = function nextTick(func) { + return enqueueJob(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 1), + error: isNearInfiniteLimit ? new Error() : null, + }); + }; + + clock.queueMicrotask = function queueMicrotask(func) { + return clock.nextTick(func); // explicitly drop additional arguments + }; + + clock.setInterval = function setInterval(func, timeout) { + // eslint-disable-next-line no-param-reassign + timeout = parseInt(timeout, 10); + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout, + interval: timeout, + }); + }; + + clock.clearInterval = function clearInterval(timerId) { + return clearTimer(clock, timerId, "Interval"); + }; + + if (setImmediatePresent) { + clock.setImmediate = function setImmediate(func) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 1), + immediate: true, + }); + }; + + if (typeof _global.Promise !== "undefined" && utilPromisify) { + clock.setImmediate[utilPromisify.custom] = + function promisifiedSetImmediate(arg) { + return new _global.Promise( + function setImmediateExecutor(resolve) { + addTimer(clock, { + func: resolve, + args: [arg], + immediate: true, + }); + } + ); + }; + } + + clock.clearImmediate = function clearImmediate(timerId) { + return clearTimer(clock, timerId, "Immediate"); + }; + } + + clock.countTimers = function countTimers() { + return ( + Object.keys(clock.timers || {}).length + + (clock.jobs || []).length + ); + }; + + clock.requestAnimationFrame = function requestAnimationFrame(func) { + const result = addTimer(clock, { + func: func, + delay: getTimeToNextFrame(), + get args() { + return [fakePerformanceNow()]; + }, + animation: true, + }); + + return Number(result); + }; + + clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) { + return clearTimer(clock, timerId, "AnimationFrame"); + }; + + clock.runMicrotasks = function runMicrotasks() { + runJobs(clock); + }; + + /** + * @param {number|string} tickValue milliseconds or a string parseable by parseTime + * @param {boolean} isAsync + * @param {Function} resolve + * @param {Function} reject + * @returns {number|undefined} will return the new `now` value or nothing for async + */ + function doTick(tickValue, isAsync, resolve, reject) { + const msFloat = + typeof tickValue === "number" + ? tickValue + : parseTime(tickValue); + const ms = Math.floor(msFloat); + const remainder = nanoRemainder(msFloat); + let nanosTotal = nanos + remainder; + let tickTo = clock.now + ms; + + if (msFloat < 0) { + throw new TypeError("Negative ticks are not supported"); + } + + // adjust for positive overflow + if (nanosTotal >= 1e6) { + tickTo += 1; + nanosTotal -= 1e6; + } + + nanos = nanosTotal; + let tickFrom = clock.now; + let previous = clock.now; + // ESLint fails to detect this correctly + /* eslint-disable prefer-const */ + let timer, + firstException, + oldNow, + nextPromiseTick, + compensationCheck, + postTimerCall; + /* eslint-enable prefer-const */ + + clock.duringTick = true; + + // perform microtasks + oldNow = clock.now; + runJobs(clock); + if (oldNow !== clock.now) { + // compensate for any setSystemTime() call during microtask callback + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function doTickInner() { + // perform each timer in the requested range + timer = firstTimerInRange(clock, tickFrom, tickTo); + // eslint-disable-next-line no-unmodified-loop-condition + while (timer && tickFrom <= tickTo) { + if (clock.timers[timer.id]) { + tickFrom = timer.callAt; + clock.now = timer.callAt; + oldNow = clock.now; + try { + runJobs(clock); + callTimer(clock, timer); + } catch (e) { + firstException = firstException || e; + } + + if (isAsync) { + // finish up after native setImmediate callback to allow + // all native es6 promises to process their callbacks after + // each timer fires. + originalSetTimeout(nextPromiseTick); + return; + } + + compensationCheck(); + } + + postTimerCall(); + } + + // perform process.nextTick()s again + oldNow = clock.now; + runJobs(clock); + if (oldNow !== clock.now) { + // compensate for any setSystemTime() call during process.nextTick() callback + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + } + clock.duringTick = false; + + // corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo] + timer = firstTimerInRange(clock, tickFrom, tickTo); + if (timer) { + try { + clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range + } catch (e) { + firstException = firstException || e; + } + } else { + // no timers remaining in the requested range: move the clock all the way to the end + clock.now = tickTo; + + // update nanos + nanos = nanosTotal; + } + if (firstException) { + throw firstException; + } + + if (isAsync) { + resolve(clock.now); + } else { + return clock.now; + } + } + + nextPromiseTick = + isAsync && + function () { + try { + compensationCheck(); + postTimerCall(); + doTickInner(); + } catch (e) { + reject(e); + } + }; + + compensationCheck = function () { + // compensate for any setSystemTime() call during timer callback + if (oldNow !== clock.now) { + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + previous += clock.now - oldNow; + } + }; + + postTimerCall = function () { + timer = firstTimerInRange(clock, previous, tickTo); + previous = tickFrom; + }; + + return doTickInner(); + } + + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {number} will return the new `now` value + */ + clock.tick = function tick(tickValue) { + return doTick(tickValue, false); + }; + + if (typeof _global.Promise !== "undefined") { + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {Promise} + */ + clock.tickAsync = function tickAsync(tickValue) { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + doTick(tickValue, true, resolve, reject); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.next = function next() { + runJobs(clock); + const timer = firstTimer(clock); + if (!timer) { + return clock.now; + } + + clock.duringTick = true; + try { + clock.now = timer.callAt; + callTimer(clock, timer); + runJobs(clock); + return clock.now; + } finally { + clock.duringTick = false; + } + }; + + if (typeof _global.Promise !== "undefined") { + clock.nextAsync = function nextAsync() { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + const timer = firstTimer(clock); + if (!timer) { + resolve(clock.now); + return; + } + + let err; + clock.duringTick = true; + clock.now = timer.callAt; + try { + callTimer(clock, timer); + } catch (e) { + err = e; + } + clock.duringTick = false; + + originalSetTimeout(function () { + if (err) { + reject(err); + } else { + resolve(clock.now); + } + }); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.runAll = function runAll() { + let numTimers, i; + runJobs(clock); + for (i = 0; i < clock.loopLimit; i++) { + if (!clock.timers) { + resetIsNearInfiniteLimit(); + return clock.now; + } + + numTimers = Object.keys(clock.timers).length; + if (numTimers === 0) { + resetIsNearInfiniteLimit(); + return clock.now; + } + + clock.next(); + checkIsNearInfiniteLimit(clock, i); + } + + const excessJob = firstTimer(clock); + throw getInfiniteLoopError(clock, excessJob); + }; + + clock.runToFrame = function runToFrame() { + return clock.tick(getTimeToNextFrame()); + }; + + if (typeof _global.Promise !== "undefined") { + clock.runAllAsync = function runAllAsync() { + return new _global.Promise(function (resolve, reject) { + let i = 0; + /** + * + */ + function doRun() { + originalSetTimeout(function () { + try { + let numTimers; + if (i < clock.loopLimit) { + if (!clock.timers) { + resetIsNearInfiniteLimit(); + resolve(clock.now); + return; + } + + numTimers = Object.keys( + clock.timers + ).length; + if (numTimers === 0) { + resetIsNearInfiniteLimit(); + resolve(clock.now); + return; + } + + clock.next(); + + i++; + + doRun(); + checkIsNearInfiniteLimit(clock, i); + return; + } + + const excessJob = firstTimer(clock); + reject(getInfiniteLoopError(clock, excessJob)); + } catch (e) { + reject(e); + } + }); + } + doRun(); + }); + }; + } + + clock.runToLast = function runToLast() { + const timer = lastTimer(clock); + if (!timer) { + runJobs(clock); + return clock.now; + } + + return clock.tick(timer.callAt - clock.now); + }; + + if (typeof _global.Promise !== "undefined") { + clock.runToLastAsync = function runToLastAsync() { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + const timer = lastTimer(clock); + if (!timer) { + resolve(clock.now); + } + + resolve(clock.tickAsync(timer.callAt - clock.now)); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.reset = function reset() { + nanos = 0; + clock.timers = {}; + clock.jobs = []; + clock.now = start; + }; + + clock.setSystemTime = function setSystemTime(systemTime) { + // determine time difference + const newNow = getEpoch(systemTime); + const difference = newNow - clock.now; + let id, timer; + + adjustedSystemTime[0] = adjustedSystemTime[0] + difference; + adjustedSystemTime[1] = adjustedSystemTime[1] + nanos; + // update 'system clock' + clock.now = newNow; + nanos = 0; + + // update timers and intervals to keep them stable + for (id in clock.timers) { + if (clock.timers.hasOwnProperty(id)) { + timer = clock.timers[id]; + timer.createdAt += difference; + timer.callAt += difference; + } + } + }; + + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {number} will return the new `now` value + */ + clock.jump = function jump(tickValue) { + const msFloat = + typeof tickValue === "number" + ? tickValue + : parseTime(tickValue); + const ms = Math.floor(msFloat); + + for (const timer of Object.values(clock.timers)) { + if (clock.now + ms > timer.callAt) { + timer.callAt = clock.now + ms; + } + } + clock.tick(ms); + }; + + if (performancePresent) { + clock.performance = Object.create(null); + clock.performance.now = fakePerformanceNow; + } + + if (hrtimePresent) { + clock.hrtime = hrtime; + } + + return clock; + } + + /* eslint-disable complexity */ + + /** + * @param {Config=} [config] Optional config + * @returns {Clock} + */ + function install(config) { + if ( + arguments.length > 1 || + config instanceof Date || + Array.isArray(config) || + typeof config === "number" + ) { + throw new TypeError( + `FakeTimers.install called with ${String( + config + )} install requires an object parameter` + ); + } + + if (_global.Date.isFake === true) { + // Timers are already faked; this is a problem. + // Make the user reset timers before continuing. + throw new TypeError( + "Can't install fake timers twice on the same global object." + ); + } + + // eslint-disable-next-line no-param-reassign + config = typeof config !== "undefined" ? config : {}; + config.shouldAdvanceTime = config.shouldAdvanceTime || false; + config.advanceTimeDelta = config.advanceTimeDelta || 20; + config.shouldClearNativeTimers = + config.shouldClearNativeTimers || false; + + if (config.target) { + throw new TypeError( + "config.target is no longer supported. Use `withGlobal(target)` instead." + ); + } + + let i, l; + const clock = createClock(config.now, config.loopLimit); + clock.shouldClearNativeTimers = config.shouldClearNativeTimers; + + clock.uninstall = function () { + return uninstall(clock, config); + }; + + clock.methods = config.toFake || []; + + if (clock.methods.length === 0) { + // do not fake nextTick by default - GitHub#126 + clock.methods = Object.keys(timers).filter(function (key) { + return key !== "nextTick" && key !== "queueMicrotask"; + }); + } + + if (config.shouldAdvanceTime === true) { + const intervalTick = doIntervalTick.bind( + null, + clock, + config.advanceTimeDelta + ); + const intervalId = _global.setInterval( + intervalTick, + config.advanceTimeDelta + ); + clock.attachedInterval = intervalId; + } + + if (clock.methods.includes("performance")) { + const proto = (() => { + if (hasPerformancePrototype) { + return _global.Performance.prototype; + } + if (hasPerformanceConstructorPrototype) { + return _global.performance.constructor.prototype; + } + })(); + if (proto) { + Object.getOwnPropertyNames(proto).forEach(function (name) { + if (name !== "now") { + clock.performance[name] = + name.indexOf("getEntries") === 0 + ? NOOP_ARRAY + : NOOP; + } + }); + } else if ((config.toFake || []).includes("performance")) { + // user explicitly tried to fake performance when not present + throw new ReferenceError( + "non-existent performance object cannot be faked" + ); + } + } + + for (i = 0, l = clock.methods.length; i < l; i++) { + const nameOfMethodToReplace = clock.methods[i]; + if (nameOfMethodToReplace === "hrtime") { + if ( + _global.process && + typeof _global.process.hrtime === "function" + ) { + hijackMethod(_global.process, nameOfMethodToReplace, clock); + } + } else if (nameOfMethodToReplace === "nextTick") { + if ( + _global.process && + typeof _global.process.nextTick === "function" + ) { + hijackMethod(_global.process, nameOfMethodToReplace, clock); + } + } else { + hijackMethod(_global, nameOfMethodToReplace, clock); + } + } + + return clock; + } + + /* eslint-enable complexity */ + + return { + timers: timers, + createClock: createClock, + install: install, + withGlobal: withGlobal, + }; + } + + /** + * @typedef {object} FakeTimers + * @property {Timers} timers + * @property {createClock} createClock + * @property {Function} install + * @property {withGlobal} withGlobal + */ + + /* eslint-enable complexity */ + + /** @type {FakeTimers} */ + const defaultImplementation = withGlobal(globalObject); + + exports.timers = defaultImplementation.timers; + exports.createClock = defaultImplementation.createClock; + exports.install = defaultImplementation.install; + exports.withGlobal = withGlobal; + + },{"@sinonjs/commons":47,"util":112}],61:[function(require,module,exports){ + + var ARRAY_TYPES = [ + Array, + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + module.exports = ARRAY_TYPES; + + },{}],62:[function(require,module,exports){ + + var arrayProto = require("@sinonjs/commons").prototypes.array; + var deepEqual = require("./deep-equal").use(createMatcher); // eslint-disable-line no-use-before-define + var every = require("@sinonjs/commons").every; + var functionName = require("@sinonjs/commons").functionName; + var get = require("lodash.get"); + var iterableToString = require("./iterable-to-string"); + var objectProto = require("@sinonjs/commons").prototypes.object; + var typeOf = require("@sinonjs/commons").typeOf; + var valueToString = require("@sinonjs/commons").valueToString; + + var assertMatcher = require("./create-matcher/assert-matcher"); + var assertMethodExists = require("./create-matcher/assert-method-exists"); + var assertType = require("./create-matcher/assert-type"); + var isIterable = require("./create-matcher/is-iterable"); + var isMatcher = require("./create-matcher/is-matcher"); + + var matcherPrototype = require("./create-matcher/matcher-prototype"); + + var arrayIndexOf = arrayProto.indexOf; + var some = arrayProto.some; + + var hasOwnProperty = objectProto.hasOwnProperty; + var objectToString = objectProto.toString; + + var TYPE_MAP = require("./create-matcher/type-map")(createMatcher); // eslint-disable-line no-use-before-define + + /** + * Creates a matcher object for the passed expectation + * + * @alias module:samsam.createMatcher + * @param {*} expectation An expecttation + * @param {string} message A message for the expectation + * @returns {object} A matcher object + */ + function createMatcher(expectation, message) { + var m = Object.create(matcherPrototype); + var type = typeOf(expectation); + + if (message !== undefined && typeof message !== "string") { + throw new TypeError("Message should be a string"); + } + + if (arguments.length > 2) { + throw new TypeError( + `Expected 1 or 2 arguments, received ${arguments.length}` + ); + } + + if (type in TYPE_MAP) { + TYPE_MAP[type](m, expectation, message); + } else { + m.test = function (actual) { + return deepEqual(actual, expectation); + }; + } + + if (!m.message) { + m.message = `match(${valueToString(expectation)})`; + } + + // ensure that nothing mutates the exported message value, ref https://github.com/sinonjs/sinon/issues/2502 + Object.defineProperty(m, "message", { + configurable: false, + writable: false, + value: m.message, + }); + + return m; + } + + createMatcher.isMatcher = isMatcher; + + createMatcher.any = createMatcher(function () { + return true; + }, "any"); + + createMatcher.defined = createMatcher(function (actual) { + return actual !== null && actual !== undefined; + }, "defined"); + + createMatcher.truthy = createMatcher(function (actual) { + return Boolean(actual); + }, "truthy"); + + createMatcher.falsy = createMatcher(function (actual) { + return !actual; + }, "falsy"); + + createMatcher.same = function (expectation) { + return createMatcher(function (actual) { + return expectation === actual; + }, `same(${valueToString(expectation)})`); + }; + + createMatcher.in = function (arrayOfExpectations) { + if (typeOf(arrayOfExpectations) !== "array") { + throw new TypeError("array expected"); + } + + return createMatcher(function (actual) { + return some(arrayOfExpectations, function (expectation) { + return expectation === actual; + }); + }, `in(${valueToString(arrayOfExpectations)})`); + }; + + createMatcher.typeOf = function (type) { + assertType(type, "string", "type"); + return createMatcher(function (actual) { + return typeOf(actual) === type; + }, `typeOf("${type}")`); + }; + + createMatcher.instanceOf = function (type) { + /* istanbul ignore if */ + if ( + typeof Symbol === "undefined" || + typeof Symbol.hasInstance === "undefined" + ) { + assertType(type, "function", "type"); + } else { + assertMethodExists( + type, + Symbol.hasInstance, + "type", + "[Symbol.hasInstance]" + ); + } + return createMatcher(function (actual) { + return actual instanceof type; + }, `instanceOf(${functionName(type) || objectToString(type)})`); + }; + + /** + * Creates a property matcher + * + * @private + * @param {Function} propertyTest A function to test the property against a value + * @param {string} messagePrefix A prefix to use for messages generated by the matcher + * @returns {object} A matcher + */ + function createPropertyMatcher(propertyTest, messagePrefix) { + return function (property, value) { + assertType(property, "string", "property"); + var onlyProperty = arguments.length === 1; + var message = `${messagePrefix}("${property}"`; + if (!onlyProperty) { + message += `, ${valueToString(value)}`; + } + message += ")"; + return createMatcher(function (actual) { + if ( + actual === undefined || + actual === null || + !propertyTest(actual, property) + ) { + return false; + } + return onlyProperty || deepEqual(actual[property], value); + }, message); + }; + } + + createMatcher.has = createPropertyMatcher(function (actual, property) { + if (typeof actual === "object") { + return property in actual; + } + return actual[property] !== undefined; + }, "has"); + + createMatcher.hasOwn = createPropertyMatcher(function (actual, property) { + return hasOwnProperty(actual, property); + }, "hasOwn"); + + createMatcher.hasNested = function (property, value) { + assertType(property, "string", "property"); + var onlyProperty = arguments.length === 1; + var message = `hasNested("${property}"`; + if (!onlyProperty) { + message += `, ${valueToString(value)}`; + } + message += ")"; + return createMatcher(function (actual) { + if ( + actual === undefined || + actual === null || + get(actual, property) === undefined + ) { + return false; + } + return onlyProperty || deepEqual(get(actual, property), value); + }, message); + }; + + var jsonParseResultTypes = { + null: true, + boolean: true, + number: true, + string: true, + object: true, + array: true, + }; + createMatcher.json = function (value) { + if (!jsonParseResultTypes[typeOf(value)]) { + throw new TypeError("Value cannot be the result of JSON.parse"); + } + var message = `json(${JSON.stringify(value, null, " ")})`; + return createMatcher(function (actual) { + var parsed; + try { + parsed = JSON.parse(actual); + } catch (e) { + return false; + } + return deepEqual(parsed, value); + }, message); + }; + + createMatcher.every = function (predicate) { + assertMatcher(predicate); + + return createMatcher(function (actual) { + if (typeOf(actual) === "object") { + return every(Object.keys(actual), function (key) { + return predicate.test(actual[key]); + }); + } + + return ( + isIterable(actual) && + every(actual, function (element) { + return predicate.test(element); + }) + ); + }, `every(${predicate.message})`); + }; + + createMatcher.some = function (predicate) { + assertMatcher(predicate); + + return createMatcher(function (actual) { + if (typeOf(actual) === "object") { + return !every(Object.keys(actual), function (key) { + return !predicate.test(actual[key]); + }); + } + + return ( + isIterable(actual) && + !every(actual, function (element) { + return !predicate.test(element); + }) + ); + }, `some(${predicate.message})`); + }; + + createMatcher.array = createMatcher.typeOf("array"); + + createMatcher.array.deepEquals = function (expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.length === expectation.length; + return ( + typeOf(actual) === "array" && + sameLength && + every(actual, function (element, index) { + var expected = expectation[index]; + return typeOf(expected) === "array" && + typeOf(element) === "array" + ? createMatcher.array.deepEquals(expected).test(element) + : deepEqual(expected, element); + }) + ); + }, `deepEquals([${iterableToString(expectation)}])`); + }; + + createMatcher.array.startsWith = function (expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement, index) { + return actual[index] === expectedElement; + }) + ); + }, `startsWith([${iterableToString(expectation)}])`); + }; + + createMatcher.array.endsWith = function (expectation) { + return createMatcher(function (actual) { + // This indicates the index in which we should start matching + var offset = actual.length - expectation.length; + + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement, index) { + return actual[offset + index] === expectedElement; + }) + ); + }, `endsWith([${iterableToString(expectation)}])`); + }; + + createMatcher.array.contains = function (expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement) { + return arrayIndexOf(actual, expectedElement) !== -1; + }) + ); + }, `contains([${iterableToString(expectation)}])`); + }; + + createMatcher.map = createMatcher.typeOf("map"); + + createMatcher.map.deepEquals = function mapDeepEquals(expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.size === expectation.size; + return ( + typeOf(actual) === "map" && + sameLength && + every(actual, function (element, key) { + return expectation.has(key) && expectation.get(key) === element; + }) + ); + }, `deepEquals(Map[${iterableToString(expectation)}])`); + }; + + createMatcher.map.contains = function mapContains(expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "map" && + every(expectation, function (element, key) { + return actual.has(key) && actual.get(key) === element; + }) + ); + }, `contains(Map[${iterableToString(expectation)}])`); + }; + + createMatcher.set = createMatcher.typeOf("set"); + + createMatcher.set.deepEquals = function setDeepEquals(expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.size === expectation.size; + return ( + typeOf(actual) === "set" && + sameLength && + every(actual, function (element) { + return expectation.has(element); + }) + ); + }, `deepEquals(Set[${iterableToString(expectation)}])`); + }; + + createMatcher.set.contains = function setContains(expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "set" && + every(expectation, function (element) { + return actual.has(element); + }) + ); + }, `contains(Set[${iterableToString(expectation)}])`); + }; + + createMatcher.bool = createMatcher.typeOf("boolean"); + createMatcher.number = createMatcher.typeOf("number"); + createMatcher.string = createMatcher.typeOf("string"); + createMatcher.object = createMatcher.typeOf("object"); + createMatcher.func = createMatcher.typeOf("function"); + createMatcher.regexp = createMatcher.typeOf("regexp"); + createMatcher.date = createMatcher.typeOf("date"); + createMatcher.symbol = createMatcher.typeOf("symbol"); + + module.exports = createMatcher; + + },{"./create-matcher/assert-matcher":63,"./create-matcher/assert-method-exists":64,"./create-matcher/assert-type":65,"./create-matcher/is-iterable":66,"./create-matcher/is-matcher":67,"./create-matcher/matcher-prototype":69,"./create-matcher/type-map":70,"./deep-equal":71,"./iterable-to-string":85,"@sinonjs/commons":94,"lodash.get":115}],63:[function(require,module,exports){ + + var isMatcher = require("./is-matcher"); + + /** + * Throws a TypeError when `value` is not a matcher + * + * @private + * @param {*} value The value to examine + */ + function assertMatcher(value) { + if (!isMatcher(value)) { + throw new TypeError("Matcher expected"); + } + } + + module.exports = assertMatcher; + + },{"./is-matcher":67}],64:[function(require,module,exports){ + + /** + * Throws a TypeError when expected method doesn't exist + * + * @private + * @param {*} value A value to examine + * @param {string} method The name of the method to look for + * @param {name} name A name to use for the error message + * @param {string} methodPath The name of the method to use for error messages + * @throws {TypeError} When the method doesn't exist + */ + function assertMethodExists(value, method, name, methodPath) { + if (value[method] === null || value[method] === undefined) { + throw new TypeError(`Expected ${name} to have method ${methodPath}`); + } + } + + module.exports = assertMethodExists; + + },{}],65:[function(require,module,exports){ + + var typeOf = require("@sinonjs/commons").typeOf; + + /** + * Ensures that value is of type + * + * @private + * @param {*} value A value to examine + * @param {string} type A basic JavaScript type to compare to, e.g. "object", "string" + * @param {string} name A string to use for the error message + * @throws {TypeError} If value is not of the expected type + * @returns {undefined} + */ + function assertType(value, type, name) { + var actual = typeOf(value); + if (actual !== type) { + throw new TypeError( + `Expected type of ${name} to be ${type}, but was ${actual}` + ); + } + } + + module.exports = assertType; + + },{"@sinonjs/commons":94}],66:[function(require,module,exports){ + + var typeOf = require("@sinonjs/commons").typeOf; + + /** + * Returns `true` for iterables + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` looks like an iterable + */ + function isIterable(value) { + return Boolean(value) && typeOf(value.forEach) === "function"; + } + + module.exports = isIterable; + + },{"@sinonjs/commons":94}],67:[function(require,module,exports){ + + var isPrototypeOf = require("@sinonjs/commons").prototypes.object.isPrototypeOf; + + var matcherPrototype = require("./matcher-prototype"); + + /** + * Returns `true` when `object` is a matcher + * + * @private + * @param {*} object A value to examine + * @returns {boolean} Returns `true` when `object` is a matcher + */ + function isMatcher(object) { + return isPrototypeOf(matcherPrototype, object); + } + + module.exports = isMatcher; + + },{"./matcher-prototype":69,"@sinonjs/commons":94}],68:[function(require,module,exports){ + + var every = require("@sinonjs/commons").prototypes.array.every; + var concat = require("@sinonjs/commons").prototypes.array.concat; + var typeOf = require("@sinonjs/commons").typeOf; + + var deepEqualFactory = require("../deep-equal").use; + + var isMatcher = require("./is-matcher"); + + var keys = Object.keys; + var getOwnPropertySymbols = Object.getOwnPropertySymbols; + + /** + * Matches `actual` with `expectation` + * + * @private + * @param {*} actual A value to examine + * @param {object} expectation An object with properties to match on + * @param {object} matcher A matcher to use for comparison + * @returns {boolean} Returns true when `actual` matches all properties in `expectation` + */ + function matchObject(actual, expectation, matcher) { + var deepEqual = deepEqualFactory(matcher); + if (actual === null || actual === undefined) { + return false; + } + + var expectedKeys = keys(expectation); + /* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */ + if (typeOf(getOwnPropertySymbols) === "function") { + expectedKeys = concat(expectedKeys, getOwnPropertySymbols(expectation)); + } + + return every(expectedKeys, function (key) { + var exp = expectation[key]; + var act = actual[key]; + + if (isMatcher(exp)) { + if (!exp.test(act)) { + return false; + } + } else if (typeOf(exp) === "object") { + if (!matchObject(act, exp, matcher)) { + return false; + } + } else if (!deepEqual(act, exp)) { + return false; + } + + return true; + }); + } + + module.exports = matchObject; + + },{"../deep-equal":71,"./is-matcher":67,"@sinonjs/commons":94}],69:[function(require,module,exports){ + + var matcherPrototype = { + toString: function () { + return this.message; + }, + }; + + matcherPrototype.or = function (valueOrMatcher) { + var createMatcher = require("../create-matcher"); + var isMatcher = createMatcher.isMatcher; + + if (!arguments.length) { + throw new TypeError("Matcher expected"); + } + + var m2 = isMatcher(valueOrMatcher) + ? valueOrMatcher + : createMatcher(valueOrMatcher); + var m1 = this; + var or = Object.create(matcherPrototype); + or.test = function (actual) { + return m1.test(actual) || m2.test(actual); + }; + or.message = `${m1.message}.or(${m2.message})`; + return or; + }; + + matcherPrototype.and = function (valueOrMatcher) { + var createMatcher = require("../create-matcher"); + var isMatcher = createMatcher.isMatcher; + + if (!arguments.length) { + throw new TypeError("Matcher expected"); + } + + var m2 = isMatcher(valueOrMatcher) + ? valueOrMatcher + : createMatcher(valueOrMatcher); + var m1 = this; + var and = Object.create(matcherPrototype); + and.test = function (actual) { + return m1.test(actual) && m2.test(actual); + }; + and.message = `${m1.message}.and(${m2.message})`; + return and; + }; + + module.exports = matcherPrototype; + + },{"../create-matcher":62}],70:[function(require,module,exports){ + + var functionName = require("@sinonjs/commons").functionName; + var join = require("@sinonjs/commons").prototypes.array.join; + var map = require("@sinonjs/commons").prototypes.array.map; + var stringIndexOf = require("@sinonjs/commons").prototypes.string.indexOf; + var valueToString = require("@sinonjs/commons").valueToString; + + var matchObject = require("./match-object"); + + var createTypeMap = function (match) { + return { + function: function (m, expectation, message) { + m.test = expectation; + m.message = message || `match(${functionName(expectation)})`; + }, + number: function (m, expectation) { + m.test = function (actual) { + // we need type coercion here + return expectation == actual; // eslint-disable-line eqeqeq + }; + }, + object: function (m, expectation) { + var array = []; + + if (typeof expectation.test === "function") { + m.test = function (actual) { + return expectation.test(actual) === true; + }; + m.message = `match(${functionName(expectation.test)})`; + return m; + } + + array = map(Object.keys(expectation), function (key) { + return `${key}: ${valueToString(expectation[key])}`; + }); + + m.test = function (actual) { + return matchObject(actual, expectation, match); + }; + m.message = `match(${join(array, ", ")})`; + + return m; + }, + regexp: function (m, expectation) { + m.test = function (actual) { + return typeof actual === "string" && expectation.test(actual); + }; + }, + string: function (m, expectation) { + m.test = function (actual) { + return ( + typeof actual === "string" && + stringIndexOf(actual, expectation) !== -1 + ); + }; + m.message = `match("${expectation}")`; + }, + }; + }; + + module.exports = createTypeMap; + + },{"./match-object":68,"@sinonjs/commons":94}],71:[function(require,module,exports){ + + var valueToString = require("@sinonjs/commons").valueToString; + var className = require("@sinonjs/commons").className; + var typeOf = require("@sinonjs/commons").typeOf; + var arrayProto = require("@sinonjs/commons").prototypes.array; + var objectProto = require("@sinonjs/commons").prototypes.object; + var mapForEach = require("@sinonjs/commons").prototypes.map.forEach; + + var getClass = require("./get-class"); + var identical = require("./identical"); + var isArguments = require("./is-arguments"); + var isArrayType = require("./is-array-type"); + var isDate = require("./is-date"); + var isElement = require("./is-element"); + var isIterable = require("./is-iterable"); + var isMap = require("./is-map"); + var isNaN = require("./is-nan"); + var isObject = require("./is-object"); + var isSet = require("./is-set"); + var isSubset = require("./is-subset"); + + var concat = arrayProto.concat; + var every = arrayProto.every; + var push = arrayProto.push; + + var getTime = Date.prototype.getTime; + var hasOwnProperty = objectProto.hasOwnProperty; + var indexOf = arrayProto.indexOf; + var keys = Object.keys; + var getOwnPropertySymbols = Object.getOwnPropertySymbols; + + /** + * Deep equal comparison. Two values are "deep equal" when: + * + * - They are equal, according to samsam.identical + * - They are both date objects representing the same time + * - They are both arrays containing elements that are all deepEqual + * - They are objects with the same set of properties, and each property + * in ``actual`` is deepEqual to the corresponding property in ``expectation`` + * + * Supports cyclic objects. + * + * @alias module:samsam.deepEqual + * @param {*} actual The object to examine + * @param {*} expectation The object actual is expected to be equal to + * @param {object} match A value to match on + * @returns {boolean} Returns true when actual and expectation are considered equal + */ + function deepEqualCyclic(actual, expectation, match) { + // used for cyclic comparison + // contain already visited objects + var actualObjects = []; + var expectationObjects = []; + // contain pathes (position in the object structure) + // of the already visited objects + // indexes same as in objects arrays + var actualPaths = []; + var expectationPaths = []; + // contains combinations of already compared objects + // in the manner: { "$1['ref']$2['ref']": true } + var compared = {}; + + // does the recursion for the deep equal check + // eslint-disable-next-line complexity + return (function deepEqual( + actualObj, + expectationObj, + actualPath, + expectationPath + ) { + // If both are matchers they must be the same instance in order to be + // considered equal If we didn't do that we would end up running one + // matcher against the other + if (match && match.isMatcher(expectationObj)) { + if (match.isMatcher(actualObj)) { + return actualObj === expectationObj; + } + return expectationObj.test(actualObj); + } + + var actualType = typeof actualObj; + var expectationType = typeof expectationObj; + + if ( + actualObj === expectationObj || + isNaN(actualObj) || + isNaN(expectationObj) || + actualObj === null || + expectationObj === null || + actualObj === undefined || + expectationObj === undefined || + actualType !== "object" || + expectationType !== "object" + ) { + return identical(actualObj, expectationObj); + } + + // Elements are only equal if identical(expected, actual) + if (isElement(actualObj) || isElement(expectationObj)) { + return false; + } + + var isActualDate = isDate(actualObj); + var isExpectationDate = isDate(expectationObj); + if (isActualDate || isExpectationDate) { + if ( + !isActualDate || + !isExpectationDate || + getTime.call(actualObj) !== getTime.call(expectationObj) + ) { + return false; + } + } + + if (actualObj instanceof RegExp && expectationObj instanceof RegExp) { + if (valueToString(actualObj) !== valueToString(expectationObj)) { + return false; + } + } + + if (actualObj instanceof Promise && expectationObj instanceof Promise) { + return actualObj === expectationObj; + } + + if (actualObj instanceof Error && expectationObj instanceof Error) { + return actualObj === expectationObj; + } + + var actualClass = getClass(actualObj); + var expectationClass = getClass(expectationObj); + var actualKeys = keys(actualObj); + var expectationKeys = keys(expectationObj); + var actualName = className(actualObj); + var expectationName = className(expectationObj); + var expectationSymbols = + typeOf(getOwnPropertySymbols) === "function" + ? getOwnPropertySymbols(expectationObj) + : /* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */ + []; + var expectationKeysAndSymbols = concat( + expectationKeys, + expectationSymbols + ); + + if (isArguments(actualObj) || isArguments(expectationObj)) { + if (actualObj.length !== expectationObj.length) { + return false; + } + } else { + if ( + actualType !== expectationType || + actualClass !== expectationClass || + actualKeys.length !== expectationKeys.length || + (actualName && + expectationName && + actualName !== expectationName) + ) { + return false; + } + } + + if (isSet(actualObj) || isSet(expectationObj)) { + if ( + !isSet(actualObj) || + !isSet(expectationObj) || + actualObj.size !== expectationObj.size + ) { + return false; + } + + return isSubset(actualObj, expectationObj, deepEqual); + } + + if (isMap(actualObj) || isMap(expectationObj)) { + if ( + !isMap(actualObj) || + !isMap(expectationObj) || + actualObj.size !== expectationObj.size + ) { + return false; + } + + var mapsDeeplyEqual = true; + mapForEach(actualObj, function (value, key) { + mapsDeeplyEqual = + mapsDeeplyEqual && + deepEqualCyclic(value, expectationObj.get(key)); + }); + + return mapsDeeplyEqual; + } + + // jQuery objects have iteration protocols + // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols + // But, they don't work well with the implementation concerning iterables below, + // so we will detect them and use jQuery's own equality function + /* istanbul ignore next -- this can only be tested in the `test-headless` script */ + if ( + actualObj.constructor && + actualObj.constructor.name === "jQuery" && + typeof actualObj.is === "function" + ) { + return actualObj.is(expectationObj); + } + + var isActualNonArrayIterable = + isIterable(actualObj) && + !isArrayType(actualObj) && + !isArguments(actualObj); + var isExpectationNonArrayIterable = + isIterable(expectationObj) && + !isArrayType(expectationObj) && + !isArguments(expectationObj); + if (isActualNonArrayIterable || isExpectationNonArrayIterable) { + var actualArray = Array.from(actualObj); + var expectationArray = Array.from(expectationObj); + if (actualArray.length !== expectationArray.length) { + return false; + } + + var arrayDeeplyEquals = true; + every(actualArray, function (key) { + arrayDeeplyEquals = + arrayDeeplyEquals && + deepEqualCyclic(actualArray[key], expectationArray[key]); + }); + + return arrayDeeplyEquals; + } + + return every(expectationKeysAndSymbols, function (key) { + if (!hasOwnProperty(actualObj, key)) { + return false; + } + + var actualValue = actualObj[key]; + var expectationValue = expectationObj[key]; + var actualObject = isObject(actualValue); + var expectationObject = isObject(expectationValue); + // determines, if the objects were already visited + // (it's faster to check for isObject first, than to + // get -1 from getIndex for non objects) + var actualIndex = actualObject + ? indexOf(actualObjects, actualValue) + : -1; + var expectationIndex = expectationObject + ? indexOf(expectationObjects, expectationValue) + : -1; + // determines the new paths of the objects + // - for non cyclic objects the current path will be extended + // by current property name + // - for cyclic objects the stored path is taken + var newActualPath = + actualIndex !== -1 + ? actualPaths[actualIndex] + : `${actualPath}[${JSON.stringify(key)}]`; + var newExpectationPath = + expectationIndex !== -1 + ? expectationPaths[expectationIndex] + : `${expectationPath}[${JSON.stringify(key)}]`; + var combinedPath = newActualPath + newExpectationPath; + + // stop recursion if current objects are already compared + if (compared[combinedPath]) { + return true; + } + + // remember the current objects and their paths + if (actualIndex === -1 && actualObject) { + push(actualObjects, actualValue); + push(actualPaths, newActualPath); + } + if (expectationIndex === -1 && expectationObject) { + push(expectationObjects, expectationValue); + push(expectationPaths, newExpectationPath); + } + + // remember that the current objects are already compared + if (actualObject && expectationObject) { + compared[combinedPath] = true; + } + + // End of cyclic logic + + // neither actualValue nor expectationValue is a cycle + // continue with next level + return deepEqual( + actualValue, + expectationValue, + newActualPath, + newExpectationPath + ); + }); + })(actual, expectation, "$1", "$2"); + } + + deepEqualCyclic.use = function (match) { + return function deepEqual(a, b) { + return deepEqualCyclic(a, b, match); + }; + }; + + module.exports = deepEqualCyclic; + + },{"./get-class":72,"./identical":73,"./is-arguments":74,"./is-array-type":75,"./is-date":76,"./is-element":77,"./is-iterable":78,"./is-map":79,"./is-nan":80,"./is-object":82,"./is-set":83,"./is-subset":84,"@sinonjs/commons":94}],72:[function(require,module,exports){ + + var toString = require("@sinonjs/commons").prototypes.object.toString; + + /** + * Returns the internal `Class` by calling `Object.prototype.toString` + * with the provided value as `this`. Return value is a `String`, naming the + * internal class, e.g. "Array" + * + * @private + * @param {*} value - Any value + * @returns {string} - A string representation of the `Class` of `value` + */ + function getClass(value) { + return toString(value).split(/[ \]]/)[1]; + } + + module.exports = getClass; + + },{"@sinonjs/commons":94}],73:[function(require,module,exports){ + + var isNaN = require("./is-nan"); + var isNegZero = require("./is-neg-zero"); + + /** + * Strict equality check according to EcmaScript Harmony's `egal`. + * + * **From the Harmony wiki:** + * > An `egal` function simply makes available the internal `SameValue` function + * > from section 9.12 of the ES5 spec. If two values are egal, then they are not + * > observably distinguishable. + * + * `identical` returns `true` when `===` is `true`, except for `-0` and + * `+0`, where it returns `false`. Additionally, it returns `true` when + * `NaN` is compared to itself. + * + * @alias module:samsam.identical + * @param {*} obj1 The first value to compare + * @param {*} obj2 The second value to compare + * @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise + */ + function identical(obj1, obj2) { + if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { + return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); + } + + return false; + } + + module.exports = identical; + + },{"./is-nan":80,"./is-neg-zero":81}],74:[function(require,module,exports){ + + var getClass = require("./get-class"); + + /** + * Returns `true` when `object` is an `arguments` object, `false` otherwise + * + * @alias module:samsam.isArguments + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an `arguments` object + */ + function isArguments(object) { + return getClass(object) === "Arguments"; + } + + module.exports = isArguments; + + },{"./get-class":72}],75:[function(require,module,exports){ + + var functionName = require("@sinonjs/commons").functionName; + var indexOf = require("@sinonjs/commons").prototypes.array.indexOf; + var map = require("@sinonjs/commons").prototypes.array.map; + var ARRAY_TYPES = require("./array-types"); + var type = require("type-detect"); + + /** + * Returns `true` when `object` is an array type, `false` otherwise + * + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an array type + * @private + */ + function isArrayType(object) { + return indexOf(map(ARRAY_TYPES, functionName), type(object)) !== -1; + } + + module.exports = isArrayType; + + },{"./array-types":61,"@sinonjs/commons":94,"type-detect":150}],76:[function(require,module,exports){ + + /** + * Returns `true` when `value` is an instance of Date + * + * @private + * @param {Date} value The value to examine + * @returns {boolean} `true` when `value` is an instance of Date + */ + function isDate(value) { + return value instanceof Date; + } + + module.exports = isDate; + + },{}],77:[function(require,module,exports){ + + var div = typeof document !== "undefined" && document.createElement("div"); + + /** + * Returns `true` when `object` is a DOM element node. + * + * Unlike Underscore.js/lodash, this function will return `false` if `object` + * is an *element-like* object, i.e. a regular object with a `nodeType` + * property that holds the value `1`. + * + * @alias module:samsam.isElement + * @param {object} object The object to examine + * @returns {boolean} Returns `true` for DOM element nodes + */ + function isElement(object) { + if (!object || object.nodeType !== 1 || !div) { + return false; + } + try { + object.appendChild(div); + object.removeChild(div); + } catch (e) { + return false; + } + return true; + } + + module.exports = isElement; + + },{}],78:[function(require,module,exports){ + + /** + * Returns `true` when the argument is an iterable, `false` otherwise + * + * @alias module:samsam.isIterable + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise + */ + function isIterable(val) { + // checks for null and undefined + if (typeof val !== "object") { + return false; + } + return typeof val[Symbol.iterator] === "function"; + } + + module.exports = isIterable; + + },{}],79:[function(require,module,exports){ + + /** + * Returns `true` when `value` is a Map + * + * @param {*} value A value to examine + * @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise + * @private + */ + function isMap(value) { + return typeof Map !== "undefined" && value instanceof Map; + } + + module.exports = isMap; + + },{}],80:[function(require,module,exports){ + + /** + * Compares a `value` to `NaN` + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `NaN` + */ + function isNaN(value) { + // Unlike global `isNaN`, this function avoids type coercion + // `typeof` check avoids IE host object issues, hat tip to + // lodash + + // eslint-disable-next-line no-self-compare + return typeof value === "number" && value !== value; + } + + module.exports = isNaN; + + },{}],81:[function(require,module,exports){ + + /** + * Returns `true` when `value` is `-0` + * + * @alias module:samsam.isNegZero + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `-0` + */ + function isNegZero(value) { + return value === 0 && 1 / value === -Infinity; + } + + module.exports = isNegZero; + + },{}],82:[function(require,module,exports){ + + /** + * Returns `true` when the value is a regular Object and not a specialized Object + * + * This helps speed up deepEqual cyclic checks + * + * The premise is that only Objects are stored in the visited array. + * So if this function returns false, we don't have to do the + * expensive operation of searching for the value in the the array of already + * visited objects + * + * @private + * @param {object} value The object to examine + * @returns {boolean} `true` when the object is a non-specialised object + */ + function isObject(value) { + return ( + typeof value === "object" && + value !== null && + // none of these are collection objects, so we can return false + !(value instanceof Boolean) && + !(value instanceof Date) && + !(value instanceof Error) && + !(value instanceof Number) && + !(value instanceof RegExp) && + !(value instanceof String) + ); + } + + module.exports = isObject; + + },{}],83:[function(require,module,exports){ + + /** + * Returns `true` when the argument is an instance of Set, `false` otherwise + * + * @alias module:samsam.isSet + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise + */ + function isSet(val) { + return (typeof Set !== "undefined" && val instanceof Set) || false; + } + + module.exports = isSet; + + },{}],84:[function(require,module,exports){ + + var forEach = require("@sinonjs/commons").prototypes.set.forEach; + + /** + * Returns `true` when `s1` is a subset of `s2`, `false` otherwise + * + * @private + * @param {Array|Set} s1 The target value + * @param {Array|Set} s2 The containing value + * @param {Function} compare A comparison function, should return `true` when + * values are considered equal + * @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise + */ + function isSubset(s1, s2, compare) { + var allContained = true; + forEach(s1, function (v1) { + var includes = false; + forEach(s2, function (v2) { + if (compare(v2, v1)) { + includes = true; + } + }); + allContained = allContained && includes; + }); + + return allContained; + } + + module.exports = isSubset; + + },{"@sinonjs/commons":94}],85:[function(require,module,exports){ + + var slice = require("@sinonjs/commons").prototypes.string.slice; + var typeOf = require("@sinonjs/commons").typeOf; + var valueToString = require("@sinonjs/commons").valueToString; + + /** + * Creates a string represenation of an iterable object + * + * @private + * @param {object} obj The iterable object to stringify + * @returns {string} A string representation + */ + function iterableToString(obj) { + if (typeOf(obj) === "map") { + return mapToString(obj); + } + + return genericIterableToString(obj); + } + + /** + * Creates a string representation of a Map + * + * @private + * @param {Map} map The map to stringify + * @returns {string} A string representation + */ + function mapToString(map) { + var representation = ""; + + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + map.forEach(function (value, key) { + representation += `[${stringify(key)},${stringify(value)}],`; + }); + + representation = slice(representation, 0, -1); + return representation; + } + + /** + * Create a string represenation for an iterable + * + * @private + * @param {object} iterable The iterable to stringify + * @returns {string} A string representation + */ + function genericIterableToString(iterable) { + var representation = ""; + + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + iterable.forEach(function (value) { + representation += `${stringify(value)},`; + }); + + representation = slice(representation, 0, -1); + return representation; + } + + /** + * Creates a string representation of the passed `item` + * + * @private + * @param {object} item The item to stringify + * @returns {string} A string representation of `item` + */ + function stringify(item) { + return typeof item === "string" ? `'${item}'` : valueToString(item); + } + + module.exports = iterableToString; + + },{"@sinonjs/commons":94}],86:[function(require,module,exports){ + + var valueToString = require("@sinonjs/commons").valueToString; + var indexOf = require("@sinonjs/commons").prototypes.string.indexOf; + var forEach = require("@sinonjs/commons").prototypes.array.forEach; + var type = require("type-detect"); + + var engineCanCompareMaps = typeof Array.from === "function"; + var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define + var isArrayType = require("./is-array-type"); + var isSubset = require("./is-subset"); + var createMatcher = require("./create-matcher"); + + /** + * Returns true when `array` contains all of `subset` as defined by the `compare` + * argument + * + * @param {Array} array An array to search for a subset + * @param {Array} subset The subset to find in the array + * @param {Function} compare A comparison function + * @returns {boolean} [description] + * @private + */ + function arrayContains(array, subset, compare) { + if (subset.length === 0) { + return true; + } + var i, l, j, k; + for (i = 0, l = array.length; i < l; ++i) { + if (compare(array[i], subset[0])) { + for (j = 0, k = subset.length; j < k; ++j) { + if (i + j >= l) { + return false; + } + if (!compare(array[i + j], subset[j])) { + return false; + } + } + return true; + } + } + return false; + } + + /* eslint-disable complexity */ + /** + * Matches an object with a matcher (or value) + * + * @alias module:samsam.match + * @param {object} object The object candidate to match + * @param {object} matcherOrValue A matcher or value to match against + * @returns {boolean} true when `object` matches `matcherOrValue` + */ + function match(object, matcherOrValue) { + if (matcherOrValue && typeof matcherOrValue.test === "function") { + return matcherOrValue.test(object); + } + + switch (type(matcherOrValue)) { + case "bigint": + case "boolean": + case "number": + case "symbol": + return matcherOrValue === object; + case "function": + return matcherOrValue(object) === true; + case "string": + var notNull = typeof object === "string" || Boolean(object); + return ( + notNull && + indexOf( + valueToString(object).toLowerCase(), + matcherOrValue.toLowerCase() + ) >= 0 + ); + case "null": + return object === null; + case "undefined": + return typeof object === "undefined"; + case "Date": + /* istanbul ignore else */ + if (type(object) === "Date") { + return object.getTime() === matcherOrValue.getTime(); + } + /* istanbul ignore next: this is basically the rest of the function, which is covered */ + break; + case "Array": + case "Int8Array": + case "Uint8Array": + case "Uint8ClampedArray": + case "Int16Array": + case "Uint16Array": + case "Int32Array": + case "Uint32Array": + case "Float32Array": + case "Float64Array": + return ( + isArrayType(matcherOrValue) && + arrayContains(object, matcherOrValue, match) + ); + case "Map": + /* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/ + if (!engineCanCompareMaps) { + throw new Error( + "The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances" + ); + } + + return ( + type(object) === "Map" && + arrayContains( + Array.from(object), + Array.from(matcherOrValue), + match + ) + ); + } + + switch (type(object)) { + case "null": + return false; + case "Set": + return isSubset(matcherOrValue, object, match); + } + + /* istanbul ignore else */ + if (matcherOrValue && typeof matcherOrValue === "object") { + if (matcherOrValue === object) { + return true; + } + if (typeof object !== "object") { + return false; + } + var prop; + // eslint-disable-next-line guard-for-in + for (prop in matcherOrValue) { + var value = object[prop]; + if ( + typeof value === "undefined" && + typeof object.getAttribute === "function" + ) { + value = object.getAttribute(prop); + } + if ( + matcherOrValue[prop] === null || + typeof matcherOrValue[prop] === "undefined" + ) { + if (value !== matcherOrValue[prop]) { + return false; + } + } else if ( + typeof value === "undefined" || + !deepEqual(value, matcherOrValue[prop]) + ) { + return false; + } + } + return true; + } + + /* istanbul ignore next */ + throw new Error("Matcher was an unknown or unsupported type"); + } + /* eslint-enable complexity */ + + forEach(Object.keys(createMatcher), function (key) { + match[key] = createMatcher[key]; + }); + + module.exports = match; + + },{"./create-matcher":62,"./deep-equal":71,"./is-array-type":75,"./is-subset":84,"@sinonjs/commons":94,"type-detect":150}],87:[function(require,module,exports){ + + /** + * @module samsam + */ + var identical = require("./identical"); + var isArguments = require("./is-arguments"); + var isElement = require("./is-element"); + var isNegZero = require("./is-neg-zero"); + var isSet = require("./is-set"); + var isMap = require("./is-map"); + var match = require("./match"); + var deepEqualCyclic = require("./deep-equal").use(match); + var createMatcher = require("./create-matcher"); + + module.exports = { + createMatcher: createMatcher, + deepEqual: deepEqualCyclic, + identical: identical, + isArguments: isArguments, + isElement: isElement, + isMap: isMap, + isNegZero: isNegZero, + isSet: isSet, + match: match, + }; + + },{"./create-matcher":62,"./deep-equal":71,"./identical":73,"./is-arguments":74,"./is-element":77,"./is-map":79,"./is-neg-zero":81,"./is-set":83,"./match":86}],88:[function(require,module,exports){ + arguments[4][41][0].apply(exports,arguments); + },{"./prototypes/array":96,"dup":41}],89:[function(require,module,exports){ + arguments[4][42][0].apply(exports,arguments); + },{"./function-name":92,"dup":42}],90:[function(require,module,exports){ + arguments[4][43][0].apply(exports,arguments); + },{"dup":43}],91:[function(require,module,exports){ + arguments[4][44][0].apply(exports,arguments); + },{"dup":44}],92:[function(require,module,exports){ + arguments[4][45][0].apply(exports,arguments); + },{"dup":45}],93:[function(require,module,exports){ + arguments[4][46][0].apply(exports,arguments); + },{"dup":46}],94:[function(require,module,exports){ + arguments[4][47][0].apply(exports,arguments); + },{"./called-in-order":88,"./class-name":89,"./deprecated":90,"./every":91,"./function-name":92,"./global":93,"./order-by-first-call":95,"./prototypes":99,"./type-of":105,"./value-to-string":106,"dup":47}],95:[function(require,module,exports){ + arguments[4][48][0].apply(exports,arguments); + },{"./prototypes/array":96,"dup":48}],96:[function(require,module,exports){ + arguments[4][49][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":49}],97:[function(require,module,exports){ + arguments[4][50][0].apply(exports,arguments); + },{"./throws-on-proto":104,"dup":50}],98:[function(require,module,exports){ + arguments[4][51][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":51}],99:[function(require,module,exports){ + arguments[4][52][0].apply(exports,arguments); + },{"./array":96,"./function":98,"./map":100,"./object":101,"./set":102,"./string":103,"dup":52}],100:[function(require,module,exports){ + arguments[4][53][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":53}],101:[function(require,module,exports){ + arguments[4][54][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":54}],102:[function(require,module,exports){ + arguments[4][55][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":55}],103:[function(require,module,exports){ + arguments[4][56][0].apply(exports,arguments); + },{"./copy-prototype-methods":97,"dup":56}],104:[function(require,module,exports){ + arguments[4][57][0].apply(exports,arguments); + },{"dup":57}],105:[function(require,module,exports){ + arguments[4][58][0].apply(exports,arguments); + },{"dup":58,"type-detect":150}],106:[function(require,module,exports){ + arguments[4][59][0].apply(exports,arguments); + },{"dup":59}],107:[function(require,module,exports){ + // This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + + var encoding = require("./lib/encoding.js"); + + module.exports = { + TextEncoder: encoding.TextEncoder, + TextDecoder: encoding.TextDecoder, + }; + + },{"./lib/encoding.js":109}],108:[function(require,module,exports){ + (function(global) { + + if (typeof module !== "undefined" && module.exports) { + module.exports = global; + } + + global["encoding-indexes"] = + { + "big5":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,17392,19506,17923,17830,17784,160359,19831,17843,162993,19682,163013,15253,18230,18244,19527,19520,148159,144919,160594,159371,159954,19543,172881,18255,17882,19589,162924,19719,19108,18081,158499,29221,154196,137827,146950,147297,26189,22267,null,32149,22813,166841,15860,38708,162799,23515,138590,23204,13861,171696,23249,23479,23804,26478,34195,170309,29793,29853,14453,138579,145054,155681,16108,153822,15093,31484,40855,147809,166157,143850,133770,143966,17162,33924,40854,37935,18736,34323,22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,36934,13542,29636,155065,29894,40903,22451,18735,21580,16689,145038,22552,31346,162661,35727,18094,159368,16769,155033,31662,140476,40904,140481,140489,140492,40905,34052,144827,16564,40906,17633,175615,25281,28782,40907,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,12736,12737,12738,12739,12740,131340,12741,131281,131277,12742,12743,131275,139240,12744,131274,12745,12746,12747,12748,131342,12749,12750,256,193,461,192,274,201,282,200,332,211,465,210,null,7870,null,7872,202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,null,7871,null,7873,234,609,9178,9179,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,172969,135493,null,25866,null,null,20029,28381,40270,37343,null,null,161589,25745,20250,20264,20392,20822,20852,20892,20964,21153,21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,36711,36718,29713,31996,32205,26950,31433,21031,null,null,null,null,37260,30904,37214,32956,null,36107,33014,133607,null,null,32927,40647,19661,40393,40460,19518,171510,159758,40458,172339,13761,null,28314,33342,29977,null,18705,39532,39567,40857,31111,164972,138698,132560,142054,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,163204,21797,null,134210,134421,151851,21904,142534,14828,131905,36422,150968,169189,16467,164030,30586,142392,14900,18389,164189,158194,151018,25821,134524,135092,134357,135412,25741,36478,134806,134155,135012,142505,164438,148691,null,134470,170573,164073,18420,151207,142530,39602,14951,169460,16365,13574,152263,169940,161992,142660,40302,38933,null,17369,155813,25780,21731,142668,142282,135287,14843,135279,157402,157462,162208,25834,151634,134211,36456,139681,166732,132913,null,18443,131497,16378,22643,142733,null,148936,132348,155799,134988,134550,21881,16571,17338,null,19124,141926,135325,33194,39157,134556,25465,14846,141173,36288,22177,25724,15939,null,173569,134665,142031,142537,null,135368,145858,14738,14854,164507,13688,155209,139463,22098,134961,142514,169760,13500,27709,151099,null,null,161140,142987,139784,173659,167117,134778,134196,157724,32659,135375,141315,141625,13819,152035,134796,135053,134826,16275,134960,134471,135503,134732,null,134827,134057,134472,135360,135485,16377,140950,25650,135085,144372,161337,142286,134526,134527,142417,142421,14872,134808,135367,134958,173618,158544,167122,167321,167114,38314,21708,33476,21945,null,171715,39974,39606,161630,142830,28992,33133,33004,23580,157042,33076,14231,21343,164029,37302,134906,134671,134775,134907,13789,151019,13833,134358,22191,141237,135369,134672,134776,135288,135496,164359,136277,134777,151120,142756,23124,135197,135198,135413,135414,22428,134673,161428,164557,135093,134779,151934,14083,135094,135552,152280,172733,149978,137274,147831,164476,22681,21096,13850,153405,31666,23400,18432,19244,40743,18919,39967,39821,154484,143677,22011,13810,22153,20008,22786,138177,194680,38737,131206,20059,20155,13630,23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,149737,32594,31035,31993,32595,156266,13505,null,156491,32770,32896,157202,158033,21341,34916,35265,161970,35744,36125,38021,38264,38271,38376,167439,38886,39029,39118,39134,39267,170000,40060,40479,40644,27503,63751,20023,131207,38429,25143,38050,null,20539,28158,171123,40870,15817,34959,147790,28791,23797,19232,152013,13657,154928,24866,166450,36775,37366,29073,26393,29626,144001,172295,15499,137600,19216,30948,29698,20910,165647,16393,27235,172730,16931,34319,133743,31274,170311,166634,38741,28749,21284,139390,37876,30425,166371,40871,30685,20131,20464,20668,20015,20247,40872,21556,32139,22674,22736,138678,24210,24217,24514,141074,25995,144377,26905,27203,146531,27903,null,29184,148741,29580,16091,150035,23317,29881,35715,154788,153237,31379,31724,31939,32364,33528,34199,40873,34960,40874,36537,40875,36815,34143,39392,37409,40876,167353,136255,16497,17058,23066,null,null,null,39016,26475,17014,22333,null,34262,149883,33471,160013,19585,159092,23931,158485,159678,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,143958,141206,17306,17718,null,23765,146202,35577,23672,15634,144721,23928,40882,29015,17752,147692,138787,19575,14712,13386,131492,158785,35532,20404,131641,22975,33132,38998,170234,24379,134047,null,139713,166253,16642,18107,168057,16135,40883,172469,16632,14294,18167,158790,16764,165554,160767,17773,14548,152730,17761,17691,19849,19579,19830,17898,16328,150287,13921,17630,17597,16877,23870,23880,23894,15868,14351,23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,26111,26195,15090,26258,15138,26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,28033,15599,28068,28081,28181,28184,28201,28294,166336,28347,28386,28378,40831,28392,28393,28452,28468,15686,147265,28545,28606,15722,15733,29111,23705,15754,28716,15761,28752,28756,28783,28799,28809,131877,17345,13809,134872,147159,22462,159443,28990,153568,13902,27042,166889,23412,31305,153825,169177,31333,31357,154028,31419,31408,31426,31427,29137,156813,16842,31450,31453,31466,16879,21682,154625,31499,31573,31529,152334,154878,31650,31599,33692,154548,158847,31696,33825,31634,31672,154912,15789,154725,33938,31738,31750,31797,154817,31812,31875,149634,31910,26237,148856,31945,31943,31974,31860,31987,31989,31950,32359,17693,159300,32093,159446,29837,32137,32171,28981,32179,32210,147543,155689,32228,15635,32245,137209,32229,164717,32285,155937,155994,32366,32402,17195,37996,32295,32576,32577,32583,31030,156368,39393,32663,156497,32675,136801,131176,17756,145254,17667,164666,32762,156809,32773,32776,32797,32808,32815,172167,158915,32827,32828,32865,141076,18825,157222,146915,157416,26405,32935,166472,33031,33050,22704,141046,27775,156824,151480,25831,136330,33304,137310,27219,150117,150165,17530,33321,133901,158290,146814,20473,136445,34018,33634,158474,149927,144688,137075,146936,33450,26907,194964,16859,34123,33488,33562,134678,137140,14017,143741,144730,33403,33506,33560,147083,159139,158469,158615,144846,15807,33565,21996,33669,17675,159141,33708,33729,33747,13438,159444,27223,34138,13462,159298,143087,33880,154596,33905,15827,17636,27303,33866,146613,31064,33960,158614,159351,159299,34014,33807,33681,17568,33939,34020,154769,16960,154816,17731,34100,23282,159385,17703,34163,17686,26559,34326,165413,165435,34241,159880,34306,136578,159949,194994,17770,34344,13896,137378,21495,160666,34430,34673,172280,34798,142375,34737,34778,34831,22113,34412,26710,17935,34885,34886,161248,146873,161252,34910,34972,18011,34996,34997,25537,35013,30583,161551,35207,35210,35238,35241,35239,35260,166437,35303,162084,162493,35484,30611,37374,35472,162393,31465,162618,147343,18195,162616,29052,35596,35615,152624,152933,35647,35660,35661,35497,150138,35728,35739,35503,136927,17941,34895,35995,163156,163215,195028,14117,163155,36054,163224,163261,36114,36099,137488,36059,28764,36113,150729,16080,36215,36265,163842,135188,149898,15228,164284,160012,31463,36525,36534,36547,37588,36633,36653,164709,164882,36773,37635,172703,133712,36787,18730,166366,165181,146875,24312,143970,36857,172052,165564,165121,140069,14720,159447,36919,165180,162494,36961,165228,165387,37032,165651,37060,165606,37038,37117,37223,15088,37289,37316,31916,166195,138889,37390,27807,37441,37474,153017,37561,166598,146587,166668,153051,134449,37676,37739,166625,166891,28815,23235,166626,166629,18789,37444,166892,166969,166911,37747,37979,36540,38277,38310,37926,38304,28662,17081,140922,165592,135804,146990,18911,27676,38523,38550,16748,38563,159445,25050,38582,30965,166624,38589,21452,18849,158904,131700,156688,168111,168165,150225,137493,144138,38705,34370,38710,18959,17725,17797,150249,28789,23361,38683,38748,168405,38743,23370,168427,38751,37925,20688,143543,143548,38793,38815,38833,38846,38848,38866,38880,152684,38894,29724,169011,38911,38901,168989,162170,19153,38964,38963,38987,39014,15118,160117,15697,132656,147804,153350,39114,39095,39112,39111,19199,159015,136915,21936,39137,39142,39148,37752,39225,150057,19314,170071,170245,39413,39436,39483,39440,39512,153381,14020,168113,170965,39648,39650,170757,39668,19470,39700,39725,165376,20532,39732,158120,14531,143485,39760,39744,171326,23109,137315,39822,148043,39938,39935,39948,171624,40404,171959,172434,172459,172257,172323,172511,40318,40323,172340,40462,26760,40388,139611,172435,172576,137531,172595,40249,172217,172724,40592,40597,40606,40610,19764,40618,40623,148324,40641,15200,14821,15645,20274,14270,166955,40706,40712,19350,37924,159138,40727,40726,40761,22175,22154,40773,39352,168075,38898,33919,40802,40809,31452,40846,29206,19390,149877,149947,29047,150008,148296,150097,29598,166874,137466,31135,166270,167478,37737,37875,166468,37612,37761,37835,166252,148665,29207,16107,30578,31299,28880,148595,148472,29054,137199,28835,137406,144793,16071,137349,152623,137208,14114,136955,137273,14049,137076,137425,155467,14115,136896,22363,150053,136190,135848,136134,136374,34051,145062,34051,33877,149908,160101,146993,152924,147195,159826,17652,145134,170397,159526,26617,14131,15381,15847,22636,137506,26640,16471,145215,147681,147595,147727,158753,21707,22174,157361,22162,135135,134056,134669,37830,166675,37788,20216,20779,14361,148534,20156,132197,131967,20299,20362,153169,23144,131499,132043,14745,131850,132116,13365,20265,131776,167603,131701,35546,131596,20120,20685,20749,20386,20227,150030,147082,20290,20526,20588,20609,20428,20453,20568,20732,20825,20827,20829,20830,28278,144789,147001,147135,28018,137348,147081,20904,20931,132576,17629,132259,132242,132241,36218,166556,132878,21081,21156,133235,21217,37742,18042,29068,148364,134176,149932,135396,27089,134685,29817,16094,29849,29716,29782,29592,19342,150204,147597,21456,13700,29199,147657,21940,131909,21709,134086,22301,37469,38644,37734,22493,22413,22399,13886,22731,23193,166470,136954,137071,136976,23084,22968,37519,23166,23247,23058,153926,137715,137313,148117,14069,27909,29763,23073,155267,23169,166871,132115,37856,29836,135939,28933,18802,37896,166395,37821,14240,23582,23710,24158,24136,137622,137596,146158,24269,23375,137475,137476,14081,137376,14045,136958,14035,33066,166471,138682,144498,166312,24332,24334,137511,137131,23147,137019,23364,34324,161277,34912,24702,141408,140843,24539,16056,140719,140734,168072,159603,25024,131134,131142,140827,24985,24984,24693,142491,142599,149204,168269,25713,149093,142186,14889,142114,144464,170218,142968,25399,173147,25782,25393,25553,149987,142695,25252,142497,25659,25963,26994,15348,143502,144045,149897,144043,21773,144096,137433,169023,26318,144009,143795,15072,16784,152964,166690,152975,136956,152923,152613,30958,143619,137258,143924,13412,143887,143746,148169,26254,159012,26219,19347,26160,161904,138731,26211,144082,144097,26142,153714,14545,145466,145340,15257,145314,144382,29904,15254,26511,149034,26806,26654,15300,27326,14435,145365,148615,27187,27218,27337,27397,137490,25873,26776,27212,15319,27258,27479,147392,146586,37792,37618,166890,166603,37513,163870,166364,37991,28069,28427,149996,28007,147327,15759,28164,147516,23101,28170,22599,27940,30786,28987,148250,148086,28913,29264,29319,29332,149391,149285,20857,150180,132587,29818,147192,144991,150090,149783,155617,16134,16049,150239,166947,147253,24743,16115,29900,29756,37767,29751,17567,159210,17745,30083,16227,150745,150790,16216,30037,30323,173510,15129,29800,166604,149931,149902,15099,15821,150094,16127,149957,149747,37370,22322,37698,166627,137316,20703,152097,152039,30584,143922,30478,30479,30587,149143,145281,14942,149744,29752,29851,16063,150202,150215,16584,150166,156078,37639,152961,30750,30861,30856,30930,29648,31065,161601,153315,16654,31131,33942,31141,27181,147194,31290,31220,16750,136934,16690,37429,31217,134476,149900,131737,146874,137070,13719,21867,13680,13994,131540,134157,31458,23129,141045,154287,154268,23053,131675,30960,23082,154566,31486,16889,31837,31853,16913,154547,155324,155302,31949,150009,137136,31886,31868,31918,27314,32220,32263,32211,32590,156257,155996,162632,32151,155266,17002,158581,133398,26582,131150,144847,22468,156690,156664,149858,32733,31527,133164,154345,154947,31500,155150,39398,34373,39523,27164,144447,14818,150007,157101,39455,157088,33920,160039,158929,17642,33079,17410,32966,33033,33090,157620,39107,158274,33378,33381,158289,33875,159143,34320,160283,23174,16767,137280,23339,137377,23268,137432,34464,195004,146831,34861,160802,23042,34926,20293,34951,35007,35046,35173,35149,153219,35156,161669,161668,166901,166873,166812,166393,16045,33955,18165,18127,14322,35389,35356,169032,24397,37419,148100,26068,28969,28868,137285,40301,35999,36073,163292,22938,30659,23024,17262,14036,36394,36519,150537,36656,36682,17140,27736,28603,140065,18587,28537,28299,137178,39913,14005,149807,37051,37015,21873,18694,37307,37892,166475,16482,166652,37927,166941,166971,34021,35371,38297,38311,38295,38294,167220,29765,16066,149759,150082,148458,16103,143909,38543,167655,167526,167525,16076,149997,150136,147438,29714,29803,16124,38721,168112,26695,18973,168083,153567,38749,37736,166281,166950,166703,156606,37562,23313,35689,18748,29689,147995,38811,38769,39224,134950,24001,166853,150194,38943,169178,37622,169431,37349,17600,166736,150119,166756,39132,166469,16128,37418,18725,33812,39227,39245,162566,15869,39323,19311,39338,39516,166757,153800,27279,39457,23294,39471,170225,19344,170312,39356,19389,19351,37757,22642,135938,22562,149944,136424,30788,141087,146872,26821,15741,37976,14631,24912,141185,141675,24839,40015,40019,40059,39989,39952,39807,39887,171565,39839,172533,172286,40225,19630,147716,40472,19632,40204,172468,172269,172275,170287,40357,33981,159250,159711,158594,34300,17715,159140,159364,159216,33824,34286,159232,145367,155748,31202,144796,144960,18733,149982,15714,37851,37566,37704,131775,30905,37495,37965,20452,13376,36964,152925,30781,30804,30902,30795,137047,143817,149825,13978,20338,28634,28633,28702,28702,21524,147893,22459,22771,22410,40214,22487,28980,13487,147884,29163,158784,151447,23336,137141,166473,24844,23246,23051,17084,148616,14124,19323,166396,37819,37816,137430,134941,33906,158912,136211,148218,142374,148417,22932,146871,157505,32168,155995,155812,149945,149899,166394,37605,29666,16105,29876,166755,137375,16097,150195,27352,29683,29691,16086,150078,150164,137177,150118,132007,136228,149989,29768,149782,28837,149878,37508,29670,37727,132350,37681,166606,166422,37766,166887,153045,18741,166530,29035,149827,134399,22180,132634,134123,134328,21762,31172,137210,32254,136898,150096,137298,17710,37889,14090,166592,149933,22960,137407,137347,160900,23201,14050,146779,14000,37471,23161,166529,137314,37748,15565,133812,19094,14730,20724,15721,15692,136092,29045,17147,164376,28175,168164,17643,27991,163407,28775,27823,15574,147437,146989,28162,28428,15727,132085,30033,14012,13512,18048,16090,18545,22980,37486,18750,36673,166940,158656,22546,22472,14038,136274,28926,148322,150129,143331,135856,140221,26809,26983,136088,144613,162804,145119,166531,145366,144378,150687,27162,145069,158903,33854,17631,17614,159014,159057,158850,159710,28439,160009,33597,137018,33773,158848,159827,137179,22921,23170,137139,23137,23153,137477,147964,14125,23023,137020,14023,29070,37776,26266,148133,23150,23083,148115,27179,147193,161590,148571,148170,28957,148057,166369,20400,159016,23746,148686,163405,148413,27148,148054,135940,28838,28979,148457,15781,27871,194597,150095,32357,23019,23855,15859,24412,150109,137183,32164,33830,21637,146170,144128,131604,22398,133333,132633,16357,139166,172726,28675,168283,23920,29583,31955,166489,168992,20424,32743,29389,29456,162548,29496,29497,153334,29505,29512,16041,162584,36972,29173,149746,29665,33270,16074,30476,16081,27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,151388,29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,23646,30654,30667,22770,30744,28857,30748,16552,30777,30791,30801,30822,33864,152885,31027,26627,31026,16643,16649,31121,31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,31981,36755,28864,134351,32207,32212,32208,32253,32686,32692,29343,17303,32800,32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,38469,34699,17926,17943,34990,35071,35108,35143,35217,162151,35369,35384,35476,35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,39809,39901,39921,39924,19565,39968,14191,138178,40265,39994,40702,22096,40339,40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,40696,31432,40772,131220,131767,132000,26906,38083,22956,132311,22592,38081,14265,132565,132629,132726,136890,22359,29043,133826,133837,134079,21610,194619,134091,21662,134139,134203,134227,134245,134268,24807,134285,22138,134325,134365,134381,134511,134578,134600,26965,39983,34725,134660,134670,134871,135056,134957,134771,23584,135100,24075,135260,135247,135286,26398,135291,135304,135318,13895,135359,135379,135471,135483,21348,33965,135907,136053,135990,35713,136567,136729,137155,137159,20088,28859,137261,137578,137773,137797,138282,138352,138412,138952,25283,138965,139029,29080,26709,139333,27113,14024,139900,140247,140282,141098,141425,141647,33533,141671,141715,142037,35237,142056,36768,142094,38840,142143,38983,39613,142412,null,142472,142519,154600,142600,142610,142775,142741,142914,143220,143308,143411,143462,144159,144350,24497,26184,26303,162425,144743,144883,29185,149946,30679,144922,145174,32391,131910,22709,26382,26904,146087,161367,155618,146961,147129,161278,139418,18640,19128,147737,166554,148206,148237,147515,148276,148374,150085,132554,20946,132625,22943,138920,15294,146687,148484,148694,22408,149108,14747,149295,165352,170441,14178,139715,35678,166734,39382,149522,149755,150037,29193,150208,134264,22885,151205,151430,132985,36570,151596,21135,22335,29041,152217,152601,147274,150183,21948,152646,152686,158546,37332,13427,152895,161330,152926,18200,152930,152934,153543,149823,153693,20582,13563,144332,24798,153859,18300,166216,154286,154505,154630,138640,22433,29009,28598,155906,162834,36950,156082,151450,35682,156674,156746,23899,158711,36662,156804,137500,35562,150006,156808,147439,156946,19392,157119,157365,141083,37989,153569,24981,23079,194765,20411,22201,148769,157436,20074,149812,38486,28047,158909,13848,35191,157593,157806,156689,157790,29151,157895,31554,168128,133649,157990,37124,158009,31301,40432,158202,39462,158253,13919,156777,131105,31107,158260,158555,23852,144665,33743,158621,18128,158884,30011,34917,159150,22710,14108,140685,159819,160205,15444,160384,160389,37505,139642,160395,37680,160486,149968,27705,38047,160848,134904,34855,35061,141606,164979,137137,28344,150058,137248,14756,14009,23568,31203,17727,26294,171181,170148,35139,161740,161880,22230,16607,136714,14753,145199,164072,136133,29101,33638,162269,168360,23143,19639,159919,166315,162301,162314,162571,163174,147834,31555,31102,163849,28597,172767,27139,164632,21410,159239,37823,26678,38749,164207,163875,158133,136173,143919,163912,23941,166960,163971,22293,38947,166217,23979,149896,26046,27093,21458,150181,147329,15377,26422,163984,164084,164142,139169,164175,164233,164271,164378,164614,164655,164746,13770,164968,165546,18682,25574,166230,30728,37461,166328,17394,166375,17375,166376,166726,166868,23032,166921,36619,167877,168172,31569,168208,168252,15863,168286,150218,36816,29327,22155,169191,169449,169392,169400,169778,170193,170313,170346,170435,170536,170766,171354,171419,32415,171768,171811,19620,38215,172691,29090,172799,19857,36882,173515,19868,134300,36798,21953,36794,140464,36793,150163,17673,32383,28502,27313,20202,13540,166700,161949,14138,36480,137205,163876,166764,166809,162366,157359,15851,161365,146615,153141,153942,20122,155265,156248,22207,134765,36366,23405,147080,150686,25566,25296,137206,137339,25904,22061,154698,21530,152337,15814,171416,19581,22050,22046,32585,155352,22901,146752,34672,19996,135146,134473,145082,33047,40286,36120,30267,40005,30286,30649,37701,21554,33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,134813,13774,22021,22001,26353,164578,13869,30004,22000,21946,21655,21874,134209,134294,24272,151880,134774,142434,134818,40619,32090,21982,135285,25245,38765,21652,36045,29174,37238,25596,25529,25598,21865,142147,40050,143027,20890,13535,134567,20903,21581,21790,21779,30310,36397,157834,30129,32950,34820,34694,35015,33206,33820,135361,17644,29444,149254,23440,33547,157843,22139,141044,163119,147875,163187,159440,160438,37232,135641,37384,146684,173737,134828,134905,29286,138402,18254,151490,163833,135147,16634,40029,25887,142752,18675,149472,171388,135148,134666,24674,161187,135149,null,155720,135559,29091,32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,149016,22682,150382,33325,21579,22442,154261,133497,null,14930,140389,29556,171692,19721,39917,146686,171824,19547,151465,169374,171998,33884,146870,160434,157619,145184,25390,32037,147191,146988,14890,36872,21196,15988,13946,17897,132238,30272,23280,134838,30842,163630,22695,16575,22140,39819,23924,30292,173108,40581,19681,30201,14331,24857,143578,148466,null,22109,135849,22439,149859,171526,21044,159918,13741,27722,40316,31830,39737,22494,137068,23635,25811,169168,156469,160100,34477,134440,159010,150242,134513,null,20990,139023,23950,38659,138705,40577,36940,31519,39682,23761,31651,25192,25397,39679,31695,39722,31870,39726,31810,31878,39957,31740,39689,40727,39963,149822,40794,21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,38465,27008,20646,30022,137069,39386,21107,null,37209,38529,37212,null,37201,167575,25471,159011,27338,22033,37262,30074,25221,132092,29519,31856,154657,146685,null,149785,30422,39837,20010,134356,33726,34882,null,23626,27072,20717,22394,21023,24053,20174,27697,131570,20281,21660,21722,21146,36226,13822,24332,13811,null,27474,37244,40869,39831,38958,39092,39610,40616,40580,29050,31508,null,27642,34840,32632,null,22048,173642,36471,40787,null,36308,36431,40476,36353,25218,164733,36392,36469,31443,150135,31294,30936,27882,35431,30215,166490,40742,27854,34774,30147,172722,30803,194624,36108,29410,29553,35629,29442,29937,36075,150203,34351,24506,34976,17591,null,137275,159237,null,35454,140571,null,24829,30311,39639,40260,37742,39823,34805,null,34831,36087,29484,38689,39856,13782,29362,19463,31825,39242,155993,24921,19460,40598,24957,null,22367,24943,25254,25145,25294,14940,25058,21418,144373,25444,26626,13778,23895,166850,36826,167481,null,20697,138566,30982,21298,38456,134971,16485,null,30718,null,31938,155418,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,160902,32859,29936,33027,30500,35209,157644,30035,159441,34729,34766,33224,34700,35401,36013,35651,30507,29944,34010,13877,27058,36262,null,35241,29800,28089,34753,147473,29927,15835,29046,24740,24988,15569,29026,24695,null,32625,166701,29264,24809,19326,21024,15384,146631,155351,161366,152881,137540,135934,170243,159196,159917,23745,156077,166415,145015,131310,157766,151310,17762,23327,156492,40784,40614,156267,12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,12321,12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19968,20057,19969,19971,20035,20061,20102,20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,20800,20995,21242,21315,21449,21475,22303,22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,20887,20982,20998,20999,21000,21243,21246,21247,21270,21305,21320,21319,21317,21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,29916,29926,29976,29983,29992,29993,30000,30001,30002,30003,30091,30333,30382,30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,20073,20121,20132,20134,20133,20223,20233,20249,20234,20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,22930,22952,22942,22947,22937,22934,22925,22948,22931,22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,21658,21602,21608,21643,21629,21646,22266,22403,22391,22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,32937,32948,32938,32943,33253,33278,33293,33459,33437,33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,22865,22863,22862,22864,23004,23000,23039,23011,23016,23043,23013,23018,23002,23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,27954,27946,27969,27941,27916,27953,27934,27927,27963,27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,31361,31487,31485,31869,32002,32005,32000,32009,32007,32004,32006,32568,32654,32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,35331,35998,36000,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,21769,21742,21738,21734,21799,21767,21757,21775,22275,22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,32020,32016,32021,32026,32028,32013,32025,32027,32570,32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,24246,24245,24254,24373,24375,24407,24428,24425,24427,24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,33333,33335,33334,33337,33678,33694,33688,33656,33698,33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,25954,25955,26001,26000,26031,26222,26224,26228,26230,26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,36024,36234,36229,36225,36302,36317,36299,36314,36305,36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,28998,29032,29014,29242,29266,29495,29509,29503,29502,29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,39156,39165,39166,39347,39345,39348,39649,40169,40578,40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,32862,32858,32903,33104,33152,33167,33160,33162,33151,33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,26292,26289,27171,27167,27112,27137,27166,27161,27133,27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,39389,39376,39391,39387,39377,39381,39378,39385,39607,39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,36986,37172,37266,37664,37686,37624,37683,37679,37666,37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,35140,35128,35133,35244,35598,35607,35609,35611,35594,35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37000,37291,37292,37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,40672,40725,40748,20787,22181,22750,22751,22754,23541,40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,38876,38907,39006,39000,39003,39100,39237,39241,39446,39449,39693,39912,39911,39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,25885,25884,26005,26345,27387,27396,27386,27570,28748,29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,38002,38000,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,24027,12083,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,710,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,65339,65341,10045,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8679,8632,8633,12751,131276,20058,131210,20994,17553,40880,20872,40881,161287,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,12003,null,null,null,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,32917,32921,32912,32914,32924,33424,33423,33413,33422,33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,27842,27834,27843,27846,27885,27890,27858,27869,27828,27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,24631,24633,24660,24690,24670,24645,24659,24647,24649,24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,32969,32975,32983,32998,32973,33279,33313,33428,33497,33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,26702,26692,26676,26653,26642,26644,26662,26664,26670,26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28000,28055,28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,33607,33605,33612,33619,33566,33580,33611,33575,33608,34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,24720,24710,24766,24752,24762,24787,24788,24783,24804,24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,31531,31533,31535,31538,31544,31514,31523,31892,31896,31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,21902,22284,22569,22583,22553,22558,22567,22563,22568,22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,28252,28257,28209,28200,28256,28273,28267,28217,28194,28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,35000,35008,35006,34998,35004,34999,35005,34994,35073,35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,24886,24882,24878,24902,24879,24911,24873,24896,25120,37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,27002,26952,26953,26933,26988,26931,26941,26981,26864,27000,26932,26985,26944,26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,30873,30848,30870,30843,31100,31106,31101,31097,31249,31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,37470,37507,37422,37450,37446,37485,37484,37455,37472,37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,27050,27041,27038,27097,27031,27024,27074,27061,27045,27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,33972,33985,33997,33962,33946,33969,34000,33949,33959,33979,33954,33940,33991,33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,34587,34627,34604,34625,34622,34630,34592,34610,34602,34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,25005,24991,24978,25002,24993,24973,24934,25011,25133,25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,33362,33360,33358,33361,34084,34107,34063,34048,34089,34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,39382,39384,39371,39383,39372,39603,39660,39659,39667,39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,24296,24293,24395,24508,24989,25000,24982,25029,25012,25030,25025,25036,25018,25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,30261,30258,30256,30395,30438,30618,30621,30625,30620,30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,37634,37668,37631,37673,37689,37685,37674,37652,37644,37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,31730,31744,31743,31739,31758,31732,31755,31731,31746,31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,39421,39422,39420,39427,39614,39678,39677,39681,39676,39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,22169,22896,23356,23657,23658,24000,24173,24174,25048,25055,25069,25070,25073,25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,35621,35639,35622,35638,35630,35620,35643,35645,35642,35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,31788,31803,31980,31978,32374,32373,32376,32368,32375,32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,26079,26344,26339,26340,27379,27376,27370,27368,27385,27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,40000,39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,28740,28746,28744,28745,28741,28742,29213,29210,29209,29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,39502,39507,39508,39500,39503,39496,39498,39497,39506,39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,31990,32410,32408,32411,32409,33248,33249,34374,34375,34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,9584,9583,65517,132423,37595,132575,147397,34124,17077,29679,20917,13897,149826,166372,37700,137691,33518,146632,30780,26436,25311,149811,166314,131744,158643,135941,20395,140525,20488,159017,162436,144896,150193,140563,20521,131966,24484,131968,131911,28379,132127,20605,20737,13434,20750,39020,14147,33814,149924,132231,20832,144308,20842,134143,139516,131813,140592,132494,143923,137603,23426,34685,132531,146585,20914,20920,40244,20937,20943,20945,15580,20947,150182,20915,20962,21314,20973,33741,26942,145197,24443,21003,21030,21052,21173,21079,21140,21177,21189,31765,34114,21216,34317,158483,21253,166622,21833,28377,147328,133460,147436,21299,21316,134114,27851,136998,26651,29653,24650,16042,14540,136936,29149,17570,21357,21364,165547,21374,21375,136598,136723,30694,21395,166555,21408,21419,21422,29607,153458,16217,29596,21441,21445,27721,20041,22526,21465,15019,134031,21472,147435,142755,21494,134263,21523,28793,21803,26199,27995,21613,158547,134516,21853,21647,21668,18342,136973,134877,15796,134477,166332,140952,21831,19693,21551,29719,21894,21929,22021,137431,147514,17746,148533,26291,135348,22071,26317,144010,26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,166758,13859,135759,22342,147877,27758,28811,22338,14001,158846,22502,136214,22531,136276,148323,22566,150517,22620,22698,13665,22752,22748,135740,22779,23551,22339,172368,148088,37843,13729,22815,26790,14019,28249,136766,23076,21843,136850,34053,22985,134478,158849,159018,137180,23001,137211,137138,159142,28017,137256,136917,23033,159301,23211,23139,14054,149929,23159,14088,23190,29797,23251,159649,140628,15749,137489,14130,136888,24195,21200,23414,25992,23420,162318,16388,18525,131588,23509,24928,137780,154060,132517,23539,23453,19728,23557,138052,23571,29646,23572,138405,158504,23625,18653,23685,23785,23791,23947,138745,138807,23824,23832,23878,138916,23738,24023,33532,14381,149761,139337,139635,33415,14390,15298,24110,27274,24181,24186,148668,134355,21414,20151,24272,21416,137073,24073,24308,164994,24313,24315,14496,24316,26686,37915,24333,131521,194708,15070,18606,135994,24378,157832,140240,24408,140401,24419,38845,159342,24434,37696,166454,24487,23990,15711,152144,139114,159992,140904,37334,131742,166441,24625,26245,137335,14691,15815,13881,22416,141236,31089,15936,24734,24740,24755,149890,149903,162387,29860,20705,23200,24932,33828,24898,194726,159442,24961,20980,132694,24967,23466,147383,141407,25043,166813,170333,25040,14642,141696,141505,24611,24924,25886,25483,131352,25285,137072,25301,142861,25452,149983,14871,25656,25592,136078,137212,25744,28554,142902,38932,147596,153373,25825,25829,38011,14950,25658,14935,25933,28438,150056,150051,25989,25965,25951,143486,26037,149824,19255,26065,16600,137257,26080,26083,24543,144384,26136,143863,143864,26180,143780,143781,26187,134773,26215,152038,26227,26228,138813,143921,165364,143816,152339,30661,141559,39332,26370,148380,150049,15147,27130,145346,26462,26471,26466,147917,168173,26583,17641,26658,28240,37436,26625,144358,159136,26717,144495,27105,27147,166623,26995,26819,144845,26881,26880,15666,14849,144956,15232,26540,26977,166474,17148,26934,27032,15265,132041,33635,20624,27129,144985,139562,27205,145155,27293,15347,26545,27336,168348,15373,27421,133411,24798,27445,27508,141261,28341,146139,132021,137560,14144,21537,146266,27617,147196,27612,27703,140427,149745,158545,27738,33318,27769,146876,17605,146877,147876,149772,149760,146633,14053,15595,134450,39811,143865,140433,32655,26679,159013,159137,159211,28054,27996,28284,28420,149887,147589,159346,34099,159604,20935,27804,28189,33838,166689,28207,146991,29779,147330,31180,28239,23185,143435,28664,14093,28573,146992,28410,136343,147517,17749,37872,28484,28508,15694,28532,168304,15675,28575,147780,28627,147601,147797,147513,147440,147380,147775,20959,147798,147799,147776,156125,28747,28798,28839,28801,28876,28885,28886,28895,16644,15848,29108,29078,148087,28971,28997,23176,29002,29038,23708,148325,29007,37730,148161,28972,148570,150055,150050,29114,166888,28861,29198,37954,29205,22801,37955,29220,37697,153093,29230,29248,149876,26813,29269,29271,15957,143428,26637,28477,29314,29482,29483,149539,165931,18669,165892,29480,29486,29647,29610,134202,158254,29641,29769,147938,136935,150052,26147,14021,149943,149901,150011,29687,29717,26883,150054,29753,132547,16087,29788,141485,29792,167602,29767,29668,29814,33721,29804,14128,29812,37873,27180,29826,18771,150156,147807,150137,166799,23366,166915,137374,29896,137608,29966,29929,29982,167641,137803,23511,167596,37765,30029,30026,30055,30062,151426,16132,150803,30094,29789,30110,30132,30210,30252,30289,30287,30319,30326,156661,30352,33263,14328,157969,157966,30369,30373,30391,30412,159647,33890,151709,151933,138780,30494,30502,30528,25775,152096,30552,144044,30639,166244,166248,136897,30708,30729,136054,150034,26826,30895,30919,30931,38565,31022,153056,30935,31028,30897,161292,36792,34948,166699,155779,140828,31110,35072,26882,31104,153687,31133,162617,31036,31145,28202,160038,16040,31174,168205,31188], + "euc-kr":[44034,44035,44037,44038,44043,44044,44045,44046,44047,44056,44062,44063,44065,44066,44067,44069,44070,44071,44072,44073,44074,44075,44078,44082,44083,44084,null,null,null,null,null,null,44085,44086,44087,44090,44091,44093,44094,44095,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44108,44110,44111,44112,44113,44114,44115,44117,null,null,null,null,null,null,44118,44119,44121,44122,44123,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44146,44147,44149,44150,44153,44155,44156,44157,44158,44159,44162,44167,44168,44173,44174,44175,44177,44178,44179,44181,44182,44183,44184,44185,44186,44187,44190,44194,44195,44196,44197,44198,44199,44203,44205,44206,44209,44210,44211,44212,44213,44214,44215,44218,44222,44223,44224,44226,44227,44229,44230,44231,44233,44234,44235,44237,44238,44239,44240,44241,44242,44243,44244,44246,44248,44249,44250,44251,44252,44253,44254,44255,44258,44259,44261,44262,44265,44267,44269,44270,44274,44276,44279,44280,44281,44282,44283,44286,44287,44289,44290,44291,44293,44295,44296,44297,44298,44299,44302,44304,44306,44307,44308,44309,44310,44311,44313,44314,44315,44317,44318,44319,44321,44322,44323,44324,44325,44326,44327,44328,44330,44331,44334,44335,44336,44337,44338,44339,null,null,null,null,null,null,44342,44343,44345,44346,44347,44349,44350,44351,44352,44353,44354,44355,44358,44360,44362,44363,44364,44365,44366,44367,44369,44370,44371,44373,44374,44375,null,null,null,null,null,null,44377,44378,44379,44380,44381,44382,44383,44384,44386,44388,44389,44390,44391,44392,44393,44394,44395,44398,44399,44401,44402,44407,44408,44409,44410,44414,44416,44419,44420,44421,44422,44423,44426,44427,44429,44430,44431,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44446,44447,44448,44449,44450,44451,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44472,44473,44474,44475,44476,44477,44478,44479,44482,44483,44485,44486,44487,44489,44490,44491,44492,44493,44494,44495,44498,44500,44501,44502,44503,44504,44505,44506,44507,44509,44510,44511,44513,44514,44515,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44538,44539,44541,44542,44546,44547,44548,44549,44550,44551,44554,44556,44558,44559,44560,44561,44562,44563,44565,44566,44567,44568,44569,44570,44571,44572,null,null,null,null,null,null,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44594,44595,44597,44598,44601,44603,44604,null,null,null,null,null,null,44605,44606,44607,44610,44612,44615,44616,44617,44619,44623,44625,44626,44627,44629,44631,44632,44633,44634,44635,44638,44642,44643,44644,44646,44647,44650,44651,44653,44654,44655,44657,44658,44659,44660,44661,44662,44663,44666,44670,44671,44672,44673,44674,44675,44678,44679,44680,44681,44682,44683,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44735,44737,44738,44739,44741,44742,44743,44744,44745,44746,44747,44750,44754,44755,44756,44757,44758,44759,44762,44763,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44777,44778,44780,44782,44783,44784,44785,44786,44787,44789,44790,44791,44793,44794,44795,44797,44798,44799,44800,44801,44802,44803,44804,44805,null,null,null,null,null,null,44806,44809,44810,44811,44812,44814,44815,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,null,null,null,null,null,null,44836,44837,44838,44839,44840,44841,44842,44843,44846,44847,44849,44851,44853,44854,44855,44856,44857,44858,44859,44862,44864,44868,44869,44870,44871,44874,44875,44876,44877,44878,44879,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44894,44895,44896,44897,44898,44899,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44922,44923,44924,44925,44926,44927,44929,44930,44931,44933,44934,44935,44937,44938,44939,44940,44941,44942,44943,44946,44947,44948,44950,44951,44952,44953,44954,44955,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44986,44987,44989,44990,44991,44993,44994,44995,44996,44997,44998,45002,45004,45007,45008,45009,45010,45011,45013,45014,45015,45016,45017,45018,45019,45021,45022,45023,45024,45025,null,null,null,null,null,null,45026,45027,45028,45029,45030,45031,45034,45035,45036,45037,45038,45039,45042,45043,45045,45046,45047,45049,45050,45051,45052,45053,45054,45055,45058,45059,null,null,null,null,null,null,45061,45062,45063,45064,45065,45066,45067,45069,45070,45071,45073,45074,45075,45077,45078,45079,45080,45081,45082,45083,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45126,45127,45129,45131,45133,45135,45136,45137,45138,45142,45144,45146,45147,45148,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45182,45183,45185,45186,45187,45189,45190,45191,45192,45193,45194,45195,45198,45200,45202,45203,45204,45205,45206,45207,45211,45213,45214,45219,45220,45221,45222,45223,45226,45232,45234,45238,45239,45241,45242,45243,45245,45246,45247,45248,45249,45250,45251,45254,45258,45259,45260,45261,45262,45263,45266,null,null,null,null,null,null,45267,45269,45270,45271,45273,45274,45275,45276,45277,45278,45279,45281,45282,45283,45284,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,null,null,null,null,null,null,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45322,45325,45326,45327,45329,45332,45333,45334,45335,45338,45342,45343,45344,45345,45346,45350,45351,45353,45354,45355,45357,45358,45359,45360,45361,45362,45363,45366,45370,45371,45372,45373,45374,45375,45378,45379,45381,45382,45383,45385,45386,45387,45388,45389,45390,45391,45394,45395,45398,45399,45401,45402,45403,45405,45406,45407,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45434,45435,45437,45438,45439,45441,45443,45444,45445,45446,45447,45450,45452,45454,45455,45456,45457,45461,45462,45463,45465,45466,45467,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,null,null,null,null,null,null,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45517,45518,45519,45521,45522,45523,45525,null,null,null,null,null,null,45526,45527,45528,45529,45530,45531,45534,45536,45537,45538,45539,45540,45541,45542,45543,45546,45547,45549,45550,45551,45553,45554,45555,45556,45557,45558,45559,45560,45562,45564,45566,45567,45568,45569,45570,45571,45574,45575,45577,45578,45581,45582,45583,45584,45585,45586,45587,45590,45592,45594,45595,45596,45597,45598,45599,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45621,45622,45623,45624,45625,45626,45627,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45657,45658,45659,45661,45662,45663,45665,45666,45667,45668,45669,45670,45671,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45686,45687,45688,45689,45690,45691,45693,45694,45695,45696,45697,45698,45699,45702,45703,45704,45706,45707,45708,45709,45710,null,null,null,null,null,null,45711,45714,45715,45717,45718,45719,45723,45724,45725,45726,45727,45730,45732,45735,45736,45737,45739,45741,45742,45743,45745,45746,45747,45749,45750,45751,null,null,null,null,null,null,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45770,45771,45773,45774,45775,45777,45779,45780,45781,45782,45783,45786,45788,45790,45791,45792,45793,45795,45799,45801,45802,45808,45809,45810,45814,45820,45821,45822,45826,45827,45829,45830,45831,45833,45834,45835,45836,45837,45838,45839,45842,45846,45847,45848,45849,45850,45851,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45911,45913,45914,45917,45920,45921,45922,45923,45926,45928,45930,45932,45933,45935,45938,45939,45941,45942,45943,45945,45946,45947,45948,45949,45950,45951,45954,45958,45959,45960,45961,45962,45963,45965,null,null,null,null,null,null,45966,45967,45969,45970,45971,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45986,45987,45988,45989,45990,45991,45993,45994,45995,45997,null,null,null,null,null,null,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46022,46023,46025,46026,46029,46031,46033,46034,46035,46038,46040,46042,46044,46046,46047,46049,46050,46051,46053,46054,46055,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46097,46098,46099,46100,46101,46102,46103,46105,46106,46107,46109,46110,46111,46113,46114,46115,46116,46117,46118,46119,46122,46124,46125,46126,46127,46128,46129,46130,46131,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46162,46163,46165,46166,46167,46169,46170,46171,46172,46173,46174,46175,46178,46180,46182,null,null,null,null,null,null,46183,46184,46185,46186,46187,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46209,46210,null,null,null,null,null,null,46211,46212,46213,46214,46215,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46238,46239,46240,46241,46242,46243,46245,46246,46247,46249,46250,46251,46253,46254,46255,46256,46257,46258,46259,46260,46262,46264,46266,46267,46268,46269,46270,46271,46273,46274,46275,46277,46278,46279,46281,46282,46283,46284,46285,46286,46287,46289,46290,46291,46292,46294,46295,46296,46297,46298,46299,46302,46303,46305,46306,46309,46311,46312,46313,46314,46315,46318,46320,46322,46323,46324,46325,46326,46327,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46358,46359,46361,46362,46365,46366,46367,46368,46369,46370,46371,46374,46379,46380,46381,46382,46383,46386,46387,46389,46390,46391,46393,46394,46395,46396,46397,46398,46399,46402,46406,null,null,null,null,null,null,46407,46408,46409,46410,46414,46415,46417,46418,46419,46421,46422,46423,46424,46425,46426,46427,46430,46434,46435,46436,46437,46438,46439,46440,46441,46442,null,null,null,null,null,null,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46498,46499,46501,46502,46503,46505,46508,46509,46510,46511,46514,46518,46519,46520,46521,46522,46526,46527,46529,46530,46531,46533,46534,46535,46536,46537,46538,46539,46542,46546,46547,46548,46549,46550,46551,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46610,46611,46613,46614,46615,46617,46618,46619,46620,46621,null,null,null,null,null,null,46622,46623,46624,46625,46626,46627,46628,46630,46631,46632,46633,46634,46635,46637,46638,46639,46640,46641,46642,46643,46645,46646,46647,46648,46649,46650,null,null,null,null,null,null,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46693,46694,46695,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46750,46751,46753,46754,46755,46757,46758,46759,46760,46761,46762,46765,46766,46767,46768,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46805,46806,46807,46808,46809,46810,46811,46812,46813,null,null,null,null,null,null,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46833,46834,46835,46837,46838,46839,46841,46842,null,null,null,null,null,null,46843,46844,46845,46846,46847,46850,46851,46852,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46890,46891,46893,46894,46897,46898,46899,46900,46901,46902,46903,46906,46908,46909,46910,46911,46912,46913,46914,46915,46917,46918,46919,46921,46922,46923,46925,46926,46927,46928,46929,46930,46931,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46945,46946,46947,46949,46950,46951,46953,46954,46955,46956,46957,46958,46959,46962,46964,46966,46967,46968,46969,46970,46971,46974,46975,46977,46978,46979,46981,46982,46983,46984,46985,46986,46987,46990,46995,46996,46997,47002,47003,47005,47006,47007,47009,47010,47011,47012,47013,47014,47015,47018,47022,47023,47024,47025,47026,47027,47030,47031,47033,47034,47035,47036,47037,47038,47039,47040,47041,null,null,null,null,null,null,47042,47043,47044,47045,47046,47048,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,null,null,null,null,null,null,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47086,47087,47089,47090,47091,47093,47094,47095,47096,47097,47098,47099,47102,47106,47107,47108,47109,47110,47114,47115,47117,47118,47119,47121,47122,47123,47124,47125,47126,47127,47130,47132,47134,47135,47136,47137,47138,47139,47142,47143,47145,47146,47147,47149,47150,47151,47152,47153,47154,47155,47158,47162,47163,47164,47165,47166,47167,47169,47170,47171,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47186,47188,47189,47190,47191,47192,47193,47194,47195,47198,47199,47201,47202,47203,47205,47206,47207,47208,47209,47210,47211,47214,47216,47218,47219,47220,47221,47222,47223,47225,47226,47227,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,null,null,null,null,null,null,47264,47265,47266,47267,47268,47269,47270,47271,47273,47274,47275,47276,47277,47278,47279,47281,47282,47283,47285,47286,47287,47289,47290,47291,47292,47293,null,null,null,null,null,null,47294,47295,47298,47300,47302,47303,47304,47305,47306,47307,47309,47310,47311,47313,47314,47315,47317,47318,47319,47320,47321,47322,47323,47324,47326,47328,47330,47331,47332,47333,47334,47335,47338,47339,47341,47342,47343,47345,47346,47347,47348,47349,47350,47351,47354,47356,47358,47359,47360,47361,47362,47363,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47385,47386,47387,47388,47389,47390,47391,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47422,47423,47425,47426,47427,47429,47430,47431,47432,47433,47434,47435,47437,47438,47440,47442,47443,47444,47445,47446,47447,47450,47451,47453,47454,47455,47457,47458,47459,47460,47461,47462,47463,47466,47468,47470,47471,47472,47473,47474,47475,47478,47479,47481,47482,47483,47485,null,null,null,null,null,null,47486,47487,47488,47489,47490,47491,47494,47496,47499,47500,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,null,null,null,null,null,null,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47534,47535,47537,47538,47539,47541,47542,47543,47544,47545,47546,47547,47550,47552,47554,47555,47556,47557,47558,47559,47562,47563,47565,47571,47572,47573,47574,47575,47578,47580,47583,47584,47586,47590,47591,47593,47594,47595,47597,47598,47599,47600,47601,47602,47603,47606,47611,47612,47613,47614,47615,47618,47619,47620,47621,47622,47623,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47674,47675,47677,47678,47679,47681,47683,47684,47685,47686,47687,47690,47692,47695,47696,47697,47698,47702,47703,47705,47706,47707,47709,47710,47711,47712,47713,47714,47715,47718,47722,47723,47724,47725,47726,47727,null,null,null,null,null,null,47730,47731,47733,47734,47735,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47750,47752,47753,47754,47755,47757,47758,47759,47760,47761,47762,null,null,null,null,null,null,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47786,47789,47790,47791,47793,47795,47796,47797,47798,47799,47802,47804,47806,47807,47808,47809,47810,47811,47813,47814,47815,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47869,47870,47871,47873,47874,47875,47877,47878,47879,47880,47881,47882,47883,47884,47886,47888,47890,47891,47892,47893,47894,47895,47897,47898,47899,47901,47902,47903,47905,47906,47907,47908,47909,47910,47911,47912,47914,47916,47917,47918,47919,47920,47921,47922,47923,47927,47929,47930,47935,47936,47937,47938,47939,47942,47944,47946,47947,47948,47950,47953,47954,null,null,null,null,null,null,47955,47957,47958,47959,47961,47962,47963,47964,47965,47966,47967,47968,47970,47972,47973,47974,47975,47976,47977,47978,47979,47981,47982,47983,47984,47985,null,null,null,null,null,null,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48009,48010,48011,48013,48014,48015,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48037,48038,48039,48041,48042,48043,48045,48046,48047,48048,48049,48050,48051,48053,48054,48056,48057,48058,48059,48060,48061,48062,48063,48065,48066,48067,48069,48070,48071,48073,48074,48075,48076,48077,48078,48079,48081,48082,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48122,48123,48125,48126,48129,48131,48132,48133,48134,48135,48138,48142,48144,48146,48147,48153,48154,48160,48161,48162,48163,48166,48168,48170,48171,48172,48174,48175,48178,48179,48181,null,null,null,null,null,null,48182,48183,48185,48186,48187,48188,48189,48190,48191,48194,48198,48199,48200,48202,48203,48206,48207,48209,48210,48211,48212,48213,48214,48215,48216,48217,null,null,null,null,null,null,48218,48219,48220,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48262,48263,48265,48266,48269,48271,48272,48273,48274,48275,48278,48280,48283,48284,48285,48286,48287,48290,48291,48293,48294,48297,48298,48299,48300,48301,48302,48303,48306,48310,48311,48312,48313,48314,48315,48318,48319,48321,48322,48323,48325,48326,48327,48328,48329,48330,48331,48332,48334,48338,48339,48340,48342,48343,48345,48346,48347,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48375,48377,48378,48379,48381,48382,48383,48384,48385,48386,48387,48390,48392,48394,48395,48396,48397,48398,48399,48401,48402,48403,48405,48406,48407,48408,48409,48410,48411,48412,48413,null,null,null,null,null,null,48414,48415,48416,48417,48418,48419,48421,48422,48423,48424,48425,48426,48427,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,null,null,null,null,null,null,48442,48443,48444,48445,48446,48447,48449,48450,48451,48452,48453,48454,48455,48458,48459,48461,48462,48463,48465,48466,48467,48468,48469,48470,48471,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48485,48486,48487,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48514,48515,48517,48518,48523,48524,48525,48526,48527,48530,48532,48534,48535,48536,48539,48541,48542,48543,48544,48545,48546,48547,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48561,48562,48563,48564,48565,48566,48567,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48598,48599,48601,48602,48603,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48618,48619,48620,48621,48622,48623,48625,null,null,null,null,null,null,48626,48627,48629,48630,48631,48633,48634,48635,48636,48637,48638,48639,48641,48642,48644,48646,48647,48648,48649,48650,48651,48654,48655,48657,48658,48659,null,null,null,null,null,null,48661,48662,48663,48664,48665,48666,48667,48670,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48710,48711,48713,48714,48715,48717,48719,48720,48721,48722,48723,48726,48728,48732,48733,48734,48735,48738,48739,48741,48742,48743,48745,48747,48748,48749,48750,48751,48754,48758,48759,48760,48761,48762,48766,48767,48769,48770,48771,48773,48774,48775,48776,48777,48778,48779,48782,48786,48787,48788,48789,48790,48791,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48850,48851,null,null,null,null,null,null,48853,48854,48857,48858,48859,48860,48861,48862,48863,48865,48866,48870,48871,48872,48873,48874,48875,48877,48878,48879,48880,48881,48882,48883,48884,48885,null,null,null,null,null,null,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48898,48899,48900,48901,48902,48903,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48922,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48962,48963,48965,48966,48967,48969,48970,48971,48972,48973,48974,48975,48978,48979,48980,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49045,49046,49047,49048,49049,49050,49051,49052,49053,null,null,null,null,null,null,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49073,49074,49075,49076,49077,49078,49079,49080,null,null,null,null,null,null,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49094,49095,49096,49097,49098,49099,49102,49103,49105,49106,49107,49109,49110,49111,49112,49113,49114,49115,49117,49118,49120,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49234,49235,49236,49237,49238,49239,49241,49242,49243,null,null,null,null,null,null,49245,49246,49247,49249,49250,49251,49252,49253,49254,49255,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,null,null,null,null,null,null,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49298,49299,49301,49302,49303,49305,49306,49307,49308,49309,49310,49311,49314,49316,49318,49319,49320,49321,49322,49323,49326,49329,49330,49335,49336,49337,49338,49339,49342,49346,49347,49348,49350,49351,49354,49355,49357,49358,49359,49361,49362,49363,49364,49365,49366,49367,49370,49374,49375,49376,49377,49378,49379,49382,49383,49385,49386,49387,49389,49390,49391,49392,49393,49394,49395,49398,49400,49402,49403,49404,49405,49406,49407,49409,49410,49411,49413,49414,49415,49417,49418,49419,49420,49421,49422,49423,49425,49426,49427,49428,49430,49431,49432,49433,49434,49435,49441,49442,49445,49448,49449,49450,49451,49454,49458,49459,49460,49461,49463,49466,49467,49469,49470,49471,49473,49474,49475,49476,49477,49478,49479,49482,49486,49487,49488,49489,49490,49491,49494,49495,null,null,null,null,null,null,49497,49498,49499,49501,49502,49503,49504,49505,49506,49507,49510,49514,49515,49516,49517,49518,49519,49521,49522,49523,49525,49526,49527,49529,49530,49531,null,null,null,null,null,null,49532,49533,49534,49535,49536,49537,49538,49539,49540,49542,49543,49544,49545,49546,49547,49551,49553,49554,49555,49557,49559,49560,49561,49562,49563,49566,49568,49570,49571,49572,49574,49575,49578,49579,49581,49582,49583,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49598,49599,49600,49601,49602,49603,49605,49606,49607,49609,49610,49611,49613,49614,49615,49616,49617,49618,49619,49621,49622,49625,49626,49627,49628,49629,49630,49631,49633,49634,49635,49637,49638,49639,49641,49642,49643,49644,49645,49646,49647,49650,49652,49653,49654,49655,49656,49657,49658,49659,49662,49663,49665,49666,49667,49669,49670,49671,49672,49673,49674,49675,49678,49680,49682,49683,49684,49685,49686,49687,49690,49691,49693,49694,49697,49698,49699,49700,49701,49702,49703,49706,49708,49710,49712,49715,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,null,null,null,null,null,null,49734,49735,49737,49738,49739,49740,49741,49742,49743,49746,49747,49749,49750,49751,49753,49754,49755,49756,49757,49758,49759,49761,49762,49763,49764,49766,null,null,null,null,null,null,49767,49768,49769,49770,49771,49774,49775,49777,49778,49779,49781,49782,49783,49784,49785,49786,49787,49790,49792,49794,49795,49796,49797,49798,49799,49802,49803,49804,49805,49806,49807,49809,49810,49811,49812,49813,49814,49815,49817,49818,49820,49822,49823,49824,49825,49826,49827,49830,49831,49833,49834,49835,49838,49839,49840,49841,49842,49843,49846,49848,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49886,49887,49889,49890,49893,49894,49895,49896,49897,49898,49902,49904,49906,49907,49908,49909,49911,49914,49917,49918,49919,49921,49922,49923,49924,49925,49926,49927,49930,49931,49934,49935,49936,49937,49938,49942,49943,49945,49946,49947,49949,49950,49951,49952,49953,49954,49955,49958,49959,49962,49963,49964,49965,49966,49967,49968,49969,49970,null,null,null,null,null,null,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49990,49991,49992,49993,49994,49995,49996,49997,null,null,null,null,null,null,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50026,50027,50029,50030,50031,50033,50035,50036,50037,50038,50039,50042,50043,50046,50047,50048,50049,50050,50051,50053,50054,50055,50057,50058,50059,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50138,50139,50141,50142,50145,50147,50148,50149,50150,50151,50154,50155,50156,50158,50159,50160,50161,50162,50163,50166,50167,50169,50170,50171,50172,50173,50174,null,null,null,null,null,null,50175,50176,50177,50178,50179,50180,50181,50182,50183,50185,50186,50187,50188,50189,50190,50191,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,null,null,null,null,null,null,50203,50204,50205,50206,50207,50208,50209,50210,50211,50213,50214,50215,50216,50217,50218,50219,50221,50222,50223,50225,50226,50227,50229,50230,50231,50232,50233,50234,50235,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50278,50279,50281,50282,50283,50285,50286,50287,50288,50289,50290,50291,50294,50295,50296,50298,50299,50300,50301,50302,50303,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50325,50326,50327,50328,50329,50330,50331,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50361,50362,50363,50365,50366,50367,50368,50369,50370,50371,50372,50373,null,null,null,null,null,null,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,null,null,null,null,null,null,50400,50401,50402,50403,50404,50405,50406,50407,50408,50410,50411,50412,50413,50414,50415,50418,50419,50421,50422,50423,50425,50427,50428,50429,50430,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50445,50446,50447,50449,50450,50451,50453,50454,50455,50456,50457,50458,50459,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50474,50475,50477,50478,50479,50481,50482,50483,50484,50485,50486,50487,50490,50492,50494,50495,50496,50497,50498,50499,50502,50503,50507,50511,50512,50513,50514,50518,50522,50523,50524,50527,50530,50531,50533,50534,50535,50537,50538,50539,50540,50541,50542,50543,50546,50550,50551,50552,50553,50554,50555,50558,50559,50561,50562,50563,50565,50566,50568,50569,50570,50571,50574,50576,50578,50579,50580,50582,50585,50586,50587,50589,50590,50591,50593,50594,50595,50596,50597,50598,50599,50600,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50614,null,null,null,null,null,null,50615,50618,50623,50624,50625,50626,50627,50635,50637,50639,50642,50643,50645,50646,50647,50649,50650,50651,50652,50653,50654,50655,50658,50660,50662,50663,null,null,null,null,null,null,50664,50665,50666,50667,50671,50673,50674,50675,50677,50680,50681,50682,50683,50690,50691,50692,50697,50698,50699,50701,50702,50703,50705,50706,50707,50708,50709,50710,50711,50714,50717,50718,50719,50720,50721,50722,50723,50726,50727,50729,50730,50731,50735,50737,50738,50742,50744,50746,50748,50749,50750,50751,50754,50755,50757,50758,50759,50761,50762,50763,50764,50765,50766,50767,50770,50774,50775,50776,50777,50778,50779,50782,50783,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50797,50798,50800,50802,50803,50804,50805,50806,50807,50810,50811,50813,50814,50815,50817,50818,50819,50820,50821,50822,50823,50826,50828,50830,50831,50832,50833,50834,50835,50838,50839,50841,50842,50843,50845,50846,50847,50848,50849,50850,50851,50854,50856,50858,50859,50860,50861,50862,50863,50866,50867,50869,50870,50871,50875,50876,50877,50878,50879,50882,50884,50886,50887,50888,50889,50890,50891,50894,null,null,null,null,null,null,50895,50897,50898,50899,50901,50902,50903,50904,50905,50906,50907,50910,50911,50914,50915,50916,50917,50918,50919,50922,50923,50925,50926,50927,50929,50930,null,null,null,null,null,null,50931,50932,50933,50934,50935,50938,50939,50940,50942,50943,50944,50945,50946,50947,50950,50951,50953,50954,50955,50957,50958,50959,50960,50961,50962,50963,50966,50968,50970,50971,50972,50973,50974,50975,50978,50979,50981,50982,50983,50985,50986,50987,50988,50989,50990,50991,50994,50996,50998,51000,51001,51002,51003,51006,51007,51009,51010,51011,51013,51014,51015,51016,51017,51019,51022,51024,51033,51034,51035,51037,51038,51039,51041,51042,51043,51044,51045,51046,51047,51049,51050,51052,51053,51054,51055,51056,51057,51058,51059,51062,51063,51065,51066,51067,51071,51072,51073,51074,51078,51083,51084,51085,51087,51090,51091,51093,51097,51099,51100,51101,51102,51103,51106,51111,51112,51113,51114,51115,51118,51119,51121,51122,51123,51125,51126,51127,51128,51129,51130,51131,51134,51138,51139,51140,51141,51142,51143,51146,51147,51149,51151,51153,51154,51155,51156,51157,51158,51159,51161,51162,51163,51164,null,null,null,null,null,null,51166,51167,51168,51169,51170,51171,51173,51174,51175,51177,51178,51179,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,null,null,null,null,null,null,51195,51196,51197,51198,51199,51202,51203,51205,51206,51207,51209,51211,51212,51213,51214,51215,51218,51220,51223,51224,51225,51226,51227,51230,51231,51233,51234,51235,51237,51238,51239,51240,51241,51242,51243,51246,51248,51250,51251,51252,51253,51254,51255,51257,51258,51259,51261,51262,51263,51265,51266,51267,51268,51269,51270,51271,51274,51275,51278,51279,51280,51281,51282,51283,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51314,51315,51317,51318,51319,51321,51323,51324,51325,51326,51327,51330,51332,51336,51337,51338,51342,51343,51344,51345,51346,51347,51349,51350,51351,51352,51353,51354,51355,51356,51358,51360,51362,51363,51364,51365,51366,51367,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51390,51391,51392,51393,null,null,null,null,null,null,51394,51395,51397,51398,51399,51401,51402,51403,51405,51406,51407,51408,51409,51410,51411,51414,51416,51418,51419,51420,51421,51422,51423,51426,51427,51429,null,null,null,null,null,null,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51446,51447,51448,51449,51450,51451,51454,51455,51457,51458,51459,51463,51464,51465,51466,51467,51470,12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,8835,8746,8745,8743,8744,65506,51472,51474,51475,51476,51477,51478,51479,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,null,null,null,null,null,null,51501,51502,51503,51504,51505,51506,51507,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,null,null,null,null,null,null,51528,51529,51530,51531,51532,51533,51534,51535,51538,51539,51541,51542,51543,51545,51546,51547,51548,51549,51550,51551,51554,51556,51557,51558,51559,51560,51561,51562,51563,51565,51566,51567,8658,8660,8704,8707,180,65374,711,728,733,730,729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51569,51570,51571,51573,51574,51575,51576,51577,51578,51579,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51594,51595,51597,51598,51599,null,null,null,null,null,null,51601,51602,51603,51604,51605,51606,51607,51610,51612,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,null,null,null,null,null,null,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51650,51651,51653,51654,51657,51659,51660,51661,51662,51663,51666,51668,51671,51672,51675,65281,65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,51678,51679,51681,51683,51685,51686,51688,51689,51690,51691,51694,51698,51699,51700,51701,51702,51703,51706,51707,51709,51710,51711,51713,51714,51715,51716,null,null,null,null,null,null,51717,51718,51719,51722,51726,51727,51728,51729,51730,51731,51733,51734,51735,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,null,null,null,null,null,null,51750,51751,51752,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,51783,51784,51785,51786,51787,51790,51791,51793,51794,51795,51797,51798,51799,51800,51801,51802,51803,51806,51810,51811,51812,51813,51814,51815,51817,51818,null,null,null,null,null,null,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51838,51839,51840,51841,51842,51843,51845,51846,null,null,null,null,null,null,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,null,null,null,null,null,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51902,51903,51905,51906,51907,51909,null,null,null,null,null,null,51910,51911,51912,51913,51914,51915,51918,51920,51922,51924,51925,51926,51927,51930,51931,51932,51933,51934,51935,51937,51938,51939,51940,51941,51942,51943,null,null,null,null,null,null,51944,51945,51946,51947,51949,51950,51951,51952,51953,51954,51955,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51977,51978,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51979,51980,51981,51982,51983,51985,51986,51987,51989,51990,51991,51993,51994,51995,51996,51997,51998,51999,52002,52003,52004,52005,52006,52007,52008,52009,null,null,null,null,null,null,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52034,52035,52036,null,null,null,null,null,null,52037,52038,52039,52042,52043,52045,52046,52047,52049,52050,52051,52052,52053,52054,52055,52058,52059,52060,52062,52063,52064,52065,52066,52067,52069,52070,52071,52072,52073,52074,52075,52076,13205,13206,13207,8467,13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,null,null,null,null,null,null,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52125,52126,52127,52128,52129,52130,52131,null,null,null,null,null,null,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,198,208,170,294,null,306,null,319,321,216,338,186,222,358,330,null,12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,190,8539,8540,8541,8542,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,null,null,null,null,null,null,52192,52193,52194,52195,52197,52198,52200,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,null,null,null,null,null,null,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52238,52239,52241,52242,52243,52245,52246,52247,52248,52249,52250,52251,52254,52255,52256,52259,52260,230,273,240,295,305,307,312,320,322,248,339,223,254,359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,185,178,179,8308,8319,8321,8322,8323,8324,52261,52262,52266,52267,52269,52271,52273,52274,52275,52276,52277,52278,52279,52282,52287,52288,52289,52290,52291,52294,52295,52297,52298,52299,52301,52302,null,null,null,null,null,null,52303,52304,52305,52306,52307,52310,52314,52315,52316,52317,52318,52319,52321,52322,52323,52325,52327,52329,52330,52331,52332,52333,52334,52335,52337,52338,null,null,null,null,null,null,52339,52340,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,52372,52373,52374,52375,52378,52379,52381,52382,52383,52385,52386,52387,52388,52389,52390,52391,52394,52398,52399,52400,52401,52402,52403,52406,52407,52409,null,null,null,null,null,null,52410,52411,52413,52414,52415,52416,52417,52418,52419,52422,52424,52426,52427,52428,52429,52430,52431,52433,52434,52435,52437,52438,52439,52440,52441,52442,null,null,null,null,null,null,52443,52444,52445,52446,52447,52448,52449,52450,52451,52453,52454,52455,52456,52457,52458,52459,52461,52462,52463,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,52478,52479,52480,52482,52483,52484,52485,52486,52487,52490,52491,52493,52494,52495,52497,52498,52499,52500,52501,52502,52503,52506,52508,52510,52511,52512,null,null,null,null,null,null,52513,52514,52515,52517,52518,52519,52521,52522,52523,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52538,52539,52540,52541,52542,null,null,null,null,null,null,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52573,52574,52575,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,52577,52578,52579,52581,52582,52583,52584,52585,52586,52587,52590,52592,52594,52595,52596,52597,52598,52599,52601,52602,52603,52604,52605,52606,52607,52608,null,null,null,null,null,null,52609,52610,52611,52612,52613,52614,52615,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52630,52631,52633,52634,52635,52637,52638,52639,null,null,null,null,null,null,52640,52641,52642,52643,52646,52648,52650,52651,52652,52653,52654,52655,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52677,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52678,52679,52680,52681,52682,52683,52685,52686,52687,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,null,null,null,null,null,null,52706,52707,52708,52709,52710,52711,52713,52714,52715,52717,52718,52719,52721,52722,52723,52724,52725,52726,52727,52730,52732,52734,52735,52736,52737,52738,null,null,null,null,null,null,52739,52741,52742,52743,52745,52746,52747,52749,52750,52751,52752,52753,52754,52755,52757,52758,52759,52760,52762,52763,52764,52765,52766,52767,52770,52771,52773,52774,52775,52777,52778,52779,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52780,52781,52782,52783,52786,52788,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,null,null,null,null,null,null,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52826,52827,52829,52830,52834,52835,52836,52837,52838,52839,52842,52844,null,null,null,null,null,null,52846,52847,52848,52849,52850,52851,52854,52855,52857,52858,52859,52861,52862,52863,52864,52865,52866,52867,52870,52872,52874,52875,52876,52877,52878,52879,52882,52883,52885,52886,52887,52889,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52890,52891,52892,52893,52894,52895,52898,52902,52903,52904,52905,52906,52907,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,null,null,null,null,null,null,52923,52924,52925,52926,52927,52928,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,null,null,null,null,null,null,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52966,52967,52969,52970,52973,52974,52975,52976,52977,52978,52979,52982,52986,52987,52988,52989,52990,52991,44032,44033,44036,44039,44040,44041,44042,44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,44273,44275,44277,44278,44284,44285,44288,44292,44294,52994,52995,52997,52998,52999,53001,53002,53003,53004,53005,53006,53007,53010,53012,53014,53015,53016,53017,53018,53019,53021,53022,53023,53025,53026,53027,null,null,null,null,null,null,53029,53030,53031,53032,53033,53034,53035,53038,53042,53043,53044,53045,53046,53047,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,null,null,null,null,null,null,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53078,53079,53081,53082,53083,53085,53086,53087,53088,53089,53090,53091,53094,53096,53098,53099,53100,44300,44301,44303,44305,44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,53101,53102,53103,53106,53107,53109,53110,53111,53113,53114,53115,53116,53117,53118,53119,53121,53122,53123,53124,53126,53127,53128,53129,53130,53131,53133,null,null,null,null,null,null,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53154,53155,53156,53157,53158,53159,53161,null,null,null,null,null,null,53162,53163,53164,53165,53166,53167,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53189,53190,53191,53192,53193,53194,53195,44665,44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,44945,44949,44956,44984,44985,44988,44992,44999,45000,45001,45003,45005,45006,45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,45143,45145,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53218,53219,53221,53222,53223,53225,null,null,null,null,null,null,53226,53227,53228,53229,53230,53231,53234,53236,53238,53239,53240,53241,53242,53243,53245,53246,53247,53249,53250,53251,53253,53254,53255,53256,53257,53258,null,null,null,null,null,null,53259,53260,53261,53262,53263,53264,53266,53267,53268,53269,53270,53271,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,45516,45520,45524,45532,45533,53294,53295,53296,53297,53298,53299,53302,53303,53305,53306,53307,53309,53310,53311,53312,53313,53314,53315,53318,53320,53322,53323,53324,53325,53326,53327,null,null,null,null,null,null,53329,53330,53331,53333,53334,53335,53337,53338,53339,53340,53341,53342,53343,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53358,53359,null,null,null,null,null,null,53361,53362,53363,53365,53366,53367,53368,53369,53370,53371,53374,53375,53376,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,45535,45544,45545,45548,45552,45561,45563,45565,45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,45910,45912,45915,45916,45918,45919,45924,45925,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53414,53415,53417,53418,53419,53421,53422,53423,53424,53425,53426,null,null,null,null,null,null,53427,53430,53432,53434,53435,53436,53437,53438,53439,53442,53443,53445,53446,53447,53450,53451,53452,53453,53454,53455,53458,53462,53463,53464,53465,53466,null,null,null,null,null,null,53467,53470,53471,53473,53474,53475,53477,53478,53479,53480,53481,53482,53483,53486,53490,53491,53492,53493,53494,53495,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,45927,45929,45931,45934,45936,45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,53509,53510,53511,53512,53513,53514,53515,53516,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,null,null,null,null,null,null,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53554,53555,53557,53558,53559,53561,53563,53564,53565,53566,null,null,null,null,null,null,53567,53570,53574,53575,53576,53577,53578,53579,53582,53583,53585,53586,53587,53589,53590,53591,53592,53593,53594,53595,53598,53600,53602,53603,53604,53605,53606,53607,53609,53610,53611,53613,46400,46401,46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,46999,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53629,53630,53631,53632,53633,53634,53635,53637,53638,53639,53641,53642,null,null,null,null,null,null,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53666,53667,53669,53670,53671,null,null,null,null,null,null,53673,53674,53675,53676,53677,53678,53679,53682,53684,53686,53687,53688,53689,53691,53693,53694,53695,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,47000,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,47452,47456,47464,47465,53712,53713,53714,53715,53716,53717,53718,53719,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,null,null,null,null,null,null,53739,53740,53741,53742,53743,53744,53745,53746,53747,53749,53750,53751,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,null,null,null,null,null,null,53768,53770,53771,53772,53773,53774,53775,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,47467,47469,47476,47477,47480,47484,47492,47493,47495,47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,47803,47805,47812,47816,47832,47833,47868,53802,53803,53806,53807,53809,53810,53811,53813,53814,53815,53816,53817,53818,53819,53822,53824,53826,53827,53828,53829,53830,53831,53833,53834,53835,53836,null,null,null,null,null,null,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53853,53854,53855,53856,53857,53858,53859,53861,53862,53863,53864,null,null,null,null,null,null,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53890,53891,53893,53894,53895,53897,53898,53899,53900,47872,47876,47885,47887,47889,47896,47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,53901,53902,53903,53906,53907,53908,53910,53911,53912,53913,53914,53915,53917,53918,53919,53921,53922,53923,53925,53926,53927,53928,53929,53930,53931,53933,null,null,null,null,null,null,53934,53935,53936,53938,53939,53940,53941,53942,53943,53946,53947,53949,53950,53953,53955,53956,53957,53958,53959,53962,53964,53965,53966,53967,53968,53969,null,null,null,null,null,null,53970,53971,53973,53974,53975,53977,53978,53979,53981,53982,53983,53984,53985,53986,53987,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54002,54003,54005,54006,54007,54009,54010,48281,48282,48288,48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,54011,54012,54013,54014,54015,54018,54020,54022,54023,54024,54025,54026,54027,54031,54033,54034,54035,54037,54039,54040,54041,54042,54043,54046,54050,54051,null,null,null,null,null,null,54052,54054,54055,54058,54059,54061,54062,54063,54065,54066,54067,54068,54069,54070,54071,54074,54078,54079,54080,54081,54082,54083,54086,54087,54088,54089,null,null,null,null,null,null,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,49372,49373,49380,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54142,54143,54145,54146,54147,54149,54150,54151,null,null,null,null,null,null,54152,54153,54154,54155,54158,54162,54163,54164,54165,54166,54167,54170,54171,54173,54174,54175,54177,54178,54179,54180,54181,54182,54183,54186,54188,54190,null,null,null,null,null,null,54191,54192,54193,54194,54195,54197,54198,54199,54201,54202,54203,54205,54206,54207,54208,54209,54210,54211,54214,54215,54218,54219,54220,54221,54222,54223,54225,54226,54227,54228,54229,54230,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,49695,49696,49704,49705,49707,49709,54231,54233,54234,54235,54236,54237,54238,54239,54240,54242,54244,54245,54246,54247,54248,54249,54250,54251,54254,54255,54257,54258,54259,54261,54262,54263,null,null,null,null,null,null,54264,54265,54266,54267,54270,54272,54274,54275,54276,54277,54278,54279,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,null,null,null,null,null,null,54295,54296,54297,54298,54299,54300,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,49711,49713,49714,49716,49736,49744,49745,49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,50157,50164,50165,50168,50184,50192,50212,50220,50224,54328,54329,54330,54331,54332,54333,54334,54335,54337,54338,54339,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,null,null,null,null,null,null,54356,54357,54358,54359,54360,54361,54362,54363,54365,54366,54367,54369,54370,54371,54373,54374,54375,54376,54377,54378,54379,54380,54382,54384,54385,54386,null,null,null,null,null,null,54387,54388,54389,54390,54391,54394,54395,54397,54398,54401,54403,54404,54405,54406,54407,54410,54412,54414,54415,54416,54417,54418,54419,54421,54422,54423,54424,54425,54426,54427,54428,54429,50228,50236,50237,50248,50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,null,null,null,null,null,null,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54477,54478,54479,54481,54482,54483,54485,null,null,null,null,null,null,54486,54487,54488,54489,54490,54491,54493,54494,54496,54497,54498,54499,54500,54501,54502,54503,54505,54506,54507,54509,54510,54511,54513,54514,54515,54516,54517,54518,54519,54521,54522,54524,50640,50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,50913,50920,54526,54527,54528,54529,54530,54531,54533,54534,54535,54537,54538,54539,54541,54542,54543,54544,54545,54546,54547,54550,54552,54553,54554,54555,54556,54557,null,null,null,null,null,null,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,null,null,null,null,null,null,54584,54585,54586,54587,54590,54591,54593,54594,54595,54597,54598,54599,54600,54601,54602,54603,54606,54608,54610,54611,54612,54613,54614,54615,54618,54619,54621,54622,54623,54625,54626,54627,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,51200,51201,51204,51208,51210,54628,54630,54631,54634,54636,54638,54639,54640,54641,54642,54643,54646,54647,54649,54650,54651,54653,54654,54655,54656,54657,54658,54659,54662,54666,54667,null,null,null,null,null,null,54668,54669,54670,54671,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54694,54695,null,null,null,null,null,null,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,51216,51217,51219,51221,51222,51228,51229,51232,51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,51649,51652,51655,51656,51658,51664,51665,51667,54730,54731,54733,54734,54735,54737,54739,54740,54741,54742,54743,54746,54748,54750,54751,54752,54753,54754,54755,54758,54759,54761,54762,54763,54765,54766,null,null,null,null,null,null,54767,54768,54769,54770,54771,54774,54776,54778,54779,54780,54781,54782,54783,54786,54787,54789,54790,54791,54793,54794,54795,54796,54797,54798,54799,54802,null,null,null,null,null,null,54806,54807,54808,54809,54810,54811,54813,54814,54815,54817,54818,54819,54821,54822,54823,54824,54825,54826,54827,54828,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54842,54843,51669,51670,51673,51674,51676,51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,51992,52000,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,54845,54846,54847,54849,54850,54851,54852,54854,54855,54858,54860,54862,54863,54864,54866,54867,54870,54871,54873,54874,54875,54877,54878,54879,54880,54881,null,null,null,null,null,null,54882,54883,54884,54885,54886,54888,54890,54891,54892,54893,54894,54895,54898,54899,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,null,null,null,null,null,null,54913,54914,54916,54918,54919,54920,54921,54922,54923,54926,54927,54929,54930,54931,54933,54934,54935,54936,54937,54938,54939,54940,54942,54944,54946,54947,54948,54949,54950,54951,54953,54954,52284,52285,52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,52789,54955,54957,54958,54959,54961,54962,54963,54964,54965,54966,54967,54968,54970,54972,54973,54974,54975,54976,54977,54978,54979,54982,54983,54985,54986,54987,null,null,null,null,null,null,54989,54990,54991,54992,54994,54995,54997,54998,55000,55002,55003,55004,55005,55006,55007,55009,55010,55011,55013,55014,55015,55017,55018,55019,55020,55021,null,null,null,null,null,null,55022,55023,55025,55026,55027,55028,55030,55031,55032,55033,55034,55035,55038,55039,55041,55042,55043,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55058,55059,55060,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,52984,52985,52992,52993,52996,53000,53008,53009,53011,53013,53020,53024,53028,53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,53300,53301,53304,53308,55061,55062,55063,55066,55067,55069,55070,55071,55073,55074,55075,55076,55077,55078,55079,55082,55084,55086,55087,55088,55089,55090,55091,55094,55095,55097,null,null,null,null,null,null,55098,55099,55101,55102,55103,55104,55105,55106,55107,55109,55110,55112,55114,55115,55116,55117,55118,55119,55122,55123,55125,55130,55131,55132,55133,55134,null,null,null,null,null,null,55135,55138,55140,55142,55143,55144,55146,55147,55149,55150,55151,55153,55154,55155,55157,55158,55159,55160,55161,55162,55163,55166,55167,55168,55170,55171,55172,55173,55174,55175,55178,55179,53316,53317,53319,53321,53328,53332,53336,53344,53356,53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,53812,53820,53821,53823,53825,53832,53852,55181,55182,55183,55185,55186,55187,55188,55189,55190,55191,55194,55196,55198,55199,55200,55201,55202,55203,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,53860,53888,53889,53892,53896,53904,53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,53960,53961,53963,53972,53976,53980,53988,53989,54000,54001,54004,54008,54016,54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54280,54301,54336,54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,55193,55195,55197,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20285,20339,20551,20729,21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21283,23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,21138,27298,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,23622,24760,25106,26690,26800,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26856,28330,30028,30328,30926,31293,31995,32363,32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,34467,36002,38799,20018,23521,25096,26524,29916,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31185,33747,35463,35506,36328,36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21312,21475,21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,36020,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,24524,25216,26071,26083,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26398,26399,26462,26827,26820,27231,27450,27683,27773,27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,31048,31098,31637,32000,32186,32648,32774,32813,32908,35352,35663,35912,36215,37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,26976,28275,63778,30007,63779,63780,63781,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32013,63782,63783,34930,22218,23064,63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20025,20150,20294,21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,63835,30313,32645,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,36706,38722,24976,25088,25891,28451,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29001,29833,32244,32879,34030,36646,36899,37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,20698,23534,24278,26009,29134,30274,30637,32842,34044,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36988,39719,40845,22744,23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31435,31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,33180,33707,37000,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,40629,28357,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,20497,21006,21563,21839,25991,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27766,32010,32011,32862,34442,38272,38639,21247,27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,36820,38930,39151,21187,25300,25765,28196,28497,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30332,36299,37297,37474,39662,39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30887,34327,38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,23142,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,31807,32566,33104,33105,33178,33344,33433,33705,35331,36000,36070,36091,36212,36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26000,26503,27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,31875,32203,32737,32933,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,33086,33218,33778,34586,35048,35513,35692,36027,37145,38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,39164,39391,40605,21066,63849,26388,63850,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20632,21034,23665,25955,27733,29642,29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32997,33298,34223,35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,23744,24101,24833,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,25100,34899,36848,37477,23815,23847,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23913,29791,33181,34664,28629,25342,32722,35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,36805,22833,23460,23526,24713,23529,23563,24515,27777,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63858,28145,28683,29978,33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27387,32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,22914,63874,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,28814,28976,29744,33398,33490,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63910,38331,39653,40573,26308,63911,29121,33865,63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,63924,20034,20522,63925,21000,21473,26355,27757,28618,29450,30591,31330,33454,34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,63929,25034,25942,26111,26212,26791,27738,28595,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28879,29100,29522,31613,34568,35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31368,31407,32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,34131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,29232,29503,29783,33489,34945,36677,36960,63942,38498,39000,40219,26376,36234,37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,27943,63946,28216,63947,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28641,29494,29495,63948,29788,30001,63949,30290,63950,63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,30691,32681,33380,34191,34811,34915,35516,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,35696,37291,20108,20197,20234,63965,63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63991,63992,63993,20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,27583,27656,28593,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29006,29728,30000,30008,30033,30322,31564,31627,31661,31686,32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,37336,37478,37580,37664,38662,38742,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38748,38914,40718,21046,21137,21884,22564,24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,24939,26837,28121,29742,31278,32066,32156,32305,33131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36394,36405,37758,37912,20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21675,22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,32221,36655,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,37319,37365,20874,26613,31574,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36012,20932,22971,24765,34389,20508,63999,21076,23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,33729,35531,38737,39894,64000,21059,26367,28053,28399,32224,35558,36910,36958,39636,21021,21119,21736,24980,25220,25307,26786,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26898,26970,27189,28818,28966,30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,22684,25277,25512,26894,27000,27166,28267,30394,31179,33467,33833,35535,36264,36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36101,21462,21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,35351,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,29923,36009,36774,37393,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38442,20843,21485,25420,20329,21764,24726,25943,27803,28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,29922,31080,34920,35961,39111,39108,39491,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21697,31263,26963,35575,35914,39080,39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,64008,64009,38917,20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,27194,28779,30069,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,25928,25989,26313,26783,28045,28102,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29243,32948,37237,39501,20399,20505,21402,21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,26342,29081,29113,29114,29351,31143,31232,32690,35440,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "gb18030":[19970,19972,19973,19974,19983,19986,19991,19999,20000,20001,20003,20006,20009,20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,21979,21982,21984,21986,21991,21993,21997,21998,22000,22001,22004,22006,22008,22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24006,24007,24008,24009,24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28998,28999,29000,29001,29003,29005,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,58850,58851,58852,12288,65281,65282,65283,65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,234,593,7743,324,328,505,609,59337,59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,27686,20133,23475,39559,37219,25000,37039,38889,21547,28085,23506,20989,21898,32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,30000,29980,24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,34996,34997,34998,35000,35001,35002,35003,35005,35006,35007,35008,35011,35012,35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,21310,36188,21350,21347,20994,21000,21006,21037,21043,21055,21056,21068,21086,21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34000,34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,28049,28015,28062,28064,27998,28051,28052,27996,28000,28028,28003,28186,28103,28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,26297,36980,36989,36994,37000,36995,37003,24400,24407,24406,24408,23611,21675,23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,23000,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27000,26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,32951,32999,33000,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26000,40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,58000,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565], + "gb18030-ranges":[[0,128],[36,165],[38,169],[45,178],[50,184],[81,216],[89,226],[95,235],[96,238],[100,244],[103,248],[104,251],[105,253],[109,258],[126,276],[133,284],[148,300],[172,325],[175,329],[179,334],[208,364],[306,463],[307,465],[308,467],[309,469],[310,471],[311,473],[312,475],[313,477],[341,506],[428,594],[443,610],[544,712],[545,716],[558,730],[741,930],[742,938],[749,962],[750,970],[805,1026],[819,1104],[820,1106],[7922,8209],[7924,8215],[7925,8218],[7927,8222],[7934,8231],[7943,8241],[7944,8244],[7945,8246],[7950,8252],[8062,8365],[8148,8452],[8149,8454],[8152,8458],[8164,8471],[8174,8482],[8236,8556],[8240,8570],[8262,8596],[8264,8602],[8374,8713],[8380,8720],[8381,8722],[8384,8726],[8388,8731],[8390,8737],[8392,8740],[8393,8742],[8394,8748],[8396,8751],[8401,8760],[8406,8766],[8416,8777],[8419,8781],[8424,8787],[8437,8802],[8439,8808],[8445,8816],[8482,8854],[8485,8858],[8496,8870],[8521,8896],[8603,8979],[8936,9322],[8946,9372],[9046,9548],[9050,9588],[9063,9616],[9066,9622],[9076,9634],[9092,9652],[9100,9662],[9108,9672],[9111,9676],[9113,9680],[9131,9702],[9162,9735],[9164,9738],[9218,9793],[9219,9795],[11329,11906],[11331,11909],[11334,11913],[11336,11917],[11346,11928],[11361,11944],[11363,11947],[11366,11951],[11370,11956],[11372,11960],[11375,11964],[11389,11979],[11682,12284],[11686,12292],[11687,12312],[11692,12319],[11694,12330],[11714,12351],[11716,12436],[11723,12447],[11725,12535],[11730,12543],[11736,12586],[11982,12842],[11989,12850],[12102,12964],[12336,13200],[12348,13215],[12350,13218],[12384,13253],[12393,13263],[12395,13267],[12397,13270],[12510,13384],[12553,13428],[12851,13727],[12962,13839],[12973,13851],[13738,14617],[13823,14703],[13919,14801],[13933,14816],[14080,14964],[14298,15183],[14585,15471],[14698,15585],[15583,16471],[15847,16736],[16318,17208],[16434,17325],[16438,17330],[16481,17374],[16729,17623],[17102,17997],[17122,18018],[17315,18212],[17320,18218],[17402,18301],[17418,18318],[17859,18760],[17909,18811],[17911,18814],[17915,18820],[17916,18823],[17936,18844],[17939,18848],[17961,18872],[18664,19576],[18703,19620],[18814,19738],[18962,19887],[19043,40870],[33469,59244],[33470,59336],[33471,59367],[33484,59413],[33485,59417],[33490,59423],[33497,59431],[33501,59437],[33505,59443],[33513,59452],[33520,59460],[33536,59478],[33550,59493],[37845,63789],[37921,63866],[37948,63894],[38029,63976],[38038,63986],[38064,64016],[38065,64018],[38066,64021],[38069,64025],[38075,64034],[38076,64037],[38078,64042],[39108,65074],[39109,65093],[39113,65107],[39114,65112],[39115,65127],[39116,65132],[39265,65375],[39394,65510],[189000,65536]], + "jis0208":[12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,8213,8208,65295,65340,65374,8741,65372,8230,8229,8216,8217,8220,8221,65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,65291,65293,177,215,247,65309,8800,65308,65310,8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,65504,65505,65285,65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,null,null,null,null,null,null,null,null,null,null,null,8712,8715,8838,8839,8834,8835,8746,8745,null,null,null,null,null,null,null,null,8743,8744,65506,8658,8660,8704,8707,null,null,null,null,null,null,null,null,null,null,null,8736,8869,8978,8706,8711,8801,8786,8810,8811,8730,8765,8733,8757,8747,8748,null,null,null,null,null,null,null,8491,8240,9839,9837,9834,8224,8225,182,null,null,null,null,9711,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,null,null,null,null,null,null,null,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,null,null,null,null,null,null,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,null,null,null,null,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,13129,13076,13090,13133,13080,13095,13059,13110,13137,13143,13069,13094,13091,13099,13130,13115,13212,13213,13214,13198,13199,13252,13217,null,null,null,null,null,null,null,null,13179,12317,12319,8470,13261,8481,12964,12965,12966,12967,12968,12849,12850,12857,13182,13181,13180,8786,8801,8747,8750,8721,8730,8869,8736,8735,8895,8757,8745,8746,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20124,21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21000,33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,23721,32747,36107,38593,38929,38996,39000,20225,20238,21361,21916,22120,22522,22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32000,24509,35215,35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,36578,39003,28857,20253,27583,28593,30000,38651,20814,21520,22581,22615,22956,23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,21329,21542,22915,24199,24444,24754,25161,25209,25259,26000,27604,27852,30130,30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,33178,33433,35676,36000,36070,36212,38428,38468,20398,25771,27494,33310,33889,34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,26906,26915,26913,26822,27001,26999,26972,27000,26987,26964,27006,26990,26937,26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,33983,33951,34009,33997,33979,34010,34000,33985,33990,34006,33953,34081,34047,34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38000,38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,65506,65508,65287,65282,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,65506,65508,65287,65282,12849,8470,8481,8757,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "jis0212":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,728,711,184,729,733,175,731,730,65374,900,901,null,null,null,null,null,null,null,null,161,166,191,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,186,170,169,174,8482,164,8470,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,902,904,905,906,938,null,908,null,910,939,null,911,null,null,null,null,940,941,942,943,970,912,972,962,973,971,944,974,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,198,272,null,294,null,306,null,321,319,null,330,216,338,null,358,222,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,230,273,240,295,305,307,312,322,320,329,331,248,339,223,359,254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,193,192,196,194,258,461,256,260,197,195,262,264,268,199,266,270,201,200,203,202,282,278,274,280,null,284,286,290,288,292,205,204,207,206,463,304,298,302,296,308,310,313,317,315,323,327,325,209,211,210,214,212,465,336,332,213,340,344,342,346,348,352,350,356,354,218,217,220,219,364,467,368,362,370,366,360,471,475,473,469,372,221,376,374,377,381,379,null,null,null,null,null,null,null,225,224,228,226,259,462,257,261,229,227,263,265,269,231,267,271,233,232,235,234,283,279,275,281,501,285,287,null,289,293,237,236,239,238,464,null,299,303,297,309,311,314,318,316,324,328,326,241,243,242,246,244,466,337,333,245,341,345,343,347,349,353,351,357,355,250,249,252,251,365,468,369,363,371,367,361,472,476,474,470,373,253,255,375,378,382,380,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19970,19972,19973,19980,19986,19999,20003,20004,20008,20011,20014,20015,20016,20021,20032,20033,20036,20039,20049,20058,20060,20067,20072,20073,20084,20085,20089,20095,20109,20118,20119,20125,20143,20153,20163,20176,20186,20187,20192,20193,20194,20200,20207,20209,20211,20213,20221,20222,20223,20224,20226,20227,20232,20235,20236,20242,20245,20246,20247,20249,20270,20273,20320,20275,20277,20279,20281,20283,20286,20288,20290,20296,20297,20299,20300,20306,20308,20310,20312,20319,20323,20330,20332,20334,20337,20343,20344,20345,20346,20349,20350,20353,20354,20356,20357,20361,20362,20364,20366,20368,20370,20371,20372,20375,20377,20378,20382,20383,20402,20407,20409,20411,20412,20413,20414,20416,20417,20421,20422,20424,20425,20427,20428,20429,20431,20434,20444,20448,20450,20464,20466,20476,20477,20479,20480,20481,20484,20487,20490,20492,20494,20496,20499,20503,20504,20507,20508,20509,20510,20514,20519,20526,20528,20530,20531,20533,20544,20545,20546,20549,20550,20554,20556,20558,20561,20562,20563,20567,20569,20575,20576,20578,20579,20582,20583,20586,20589,20592,20593,20539,20609,20611,20612,20614,20618,20622,20623,20624,20626,20627,20628,20630,20635,20636,20638,20639,20640,20641,20642,20650,20655,20656,20665,20666,20669,20672,20675,20676,20679,20684,20686,20688,20691,20692,20696,20700,20701,20703,20706,20708,20710,20712,20713,20719,20721,20726,20730,20734,20739,20742,20743,20744,20747,20748,20749,20750,20722,20752,20759,20761,20763,20764,20765,20766,20771,20775,20776,20780,20781,20783,20785,20787,20788,20789,20792,20793,20802,20810,20815,20819,20821,20823,20824,20831,20836,20838,20862,20867,20868,20875,20878,20888,20893,20897,20899,20909,20920,20922,20924,20926,20927,20930,20936,20943,20945,20946,20947,20949,20952,20958,20962,20965,20974,20978,20979,20980,20983,20993,20994,20997,21010,21011,21013,21014,21016,21026,21032,21041,21042,21045,21052,21061,21065,21077,21079,21080,21082,21084,21087,21088,21089,21094,21102,21111,21112,21113,21120,21122,21125,21130,21132,21139,21141,21142,21143,21144,21146,21148,21156,21157,21158,21159,21167,21168,21174,21175,21176,21178,21179,21181,21184,21188,21190,21192,21196,21199,21201,21204,21206,21211,21212,21217,21221,21224,21225,21226,21228,21232,21233,21236,21238,21239,21248,21251,21258,21259,21260,21265,21267,21272,21275,21276,21278,21279,21285,21287,21288,21289,21291,21292,21293,21296,21298,21301,21308,21309,21310,21314,21324,21323,21337,21339,21345,21347,21349,21356,21357,21362,21369,21374,21379,21383,21384,21390,21395,21396,21401,21405,21409,21412,21418,21419,21423,21426,21428,21429,21431,21432,21434,21437,21440,21445,21455,21458,21459,21461,21466,21469,21470,21472,21478,21479,21493,21506,21523,21530,21537,21543,21544,21546,21551,21553,21556,21557,21571,21572,21575,21581,21583,21598,21602,21604,21606,21607,21609,21611,21613,21614,21620,21631,21633,21635,21637,21640,21641,21645,21649,21653,21654,21660,21663,21665,21670,21671,21673,21674,21677,21678,21681,21687,21689,21690,21691,21695,21702,21706,21709,21710,21728,21738,21740,21743,21750,21756,21758,21759,21760,21761,21765,21768,21769,21772,21773,21774,21781,21802,21803,21810,21813,21814,21819,21820,21821,21825,21831,21833,21834,21837,21840,21841,21848,21850,21851,21854,21856,21857,21860,21862,21887,21889,21890,21894,21896,21902,21903,21905,21906,21907,21908,21911,21923,21924,21933,21938,21951,21953,21955,21958,21961,21963,21964,21966,21969,21970,21971,21975,21976,21979,21982,21986,21993,22006,22015,22021,22024,22026,22029,22030,22031,22032,22033,22034,22041,22060,22064,22067,22069,22071,22073,22075,22076,22077,22079,22080,22081,22083,22084,22086,22089,22091,22093,22095,22100,22110,22112,22113,22114,22115,22118,22121,22125,22127,22129,22130,22133,22148,22149,22152,22155,22156,22165,22169,22170,22173,22174,22175,22182,22183,22184,22185,22187,22188,22189,22193,22195,22199,22206,22213,22217,22218,22219,22223,22224,22220,22221,22233,22236,22237,22239,22241,22244,22245,22246,22247,22248,22257,22251,22253,22262,22263,22273,22274,22279,22282,22284,22289,22293,22298,22299,22301,22304,22306,22307,22308,22309,22313,22314,22316,22318,22319,22323,22324,22333,22334,22335,22341,22342,22348,22349,22354,22370,22373,22375,22376,22379,22381,22382,22383,22384,22385,22387,22388,22389,22391,22393,22394,22395,22396,22398,22401,22403,22412,22420,22423,22425,22426,22428,22429,22430,22431,22433,22421,22439,22440,22441,22444,22456,22461,22471,22472,22476,22479,22485,22493,22494,22500,22502,22503,22505,22509,22512,22517,22518,22520,22525,22526,22527,22531,22532,22536,22537,22497,22540,22541,22555,22558,22559,22560,22566,22567,22573,22578,22585,22591,22601,22604,22605,22607,22608,22613,22623,22625,22628,22631,22632,22648,22652,22655,22656,22657,22663,22664,22665,22666,22668,22669,22671,22672,22676,22678,22685,22688,22689,22690,22694,22697,22705,22706,22724,22716,22722,22728,22733,22734,22736,22738,22740,22742,22746,22749,22753,22754,22761,22771,22789,22790,22795,22796,22802,22803,22804,34369,22813,22817,22819,22820,22824,22831,22832,22835,22837,22838,22847,22851,22854,22866,22867,22873,22875,22877,22878,22879,22881,22883,22891,22893,22895,22898,22901,22902,22905,22907,22908,22923,22924,22926,22930,22933,22935,22943,22948,22951,22957,22958,22959,22960,22963,22967,22970,22972,22977,22979,22980,22984,22986,22989,22994,23005,23006,23007,23011,23012,23015,23022,23023,23025,23026,23028,23031,23040,23044,23052,23053,23054,23058,23059,23070,23075,23076,23079,23080,23082,23085,23088,23108,23109,23111,23112,23116,23120,23125,23134,23139,23141,23143,23149,23159,23162,23163,23166,23179,23184,23187,23190,23193,23196,23198,23199,23200,23202,23207,23212,23217,23218,23219,23221,23224,23226,23227,23231,23236,23238,23240,23247,23258,23260,23264,23269,23274,23278,23285,23286,23293,23296,23297,23304,23319,23348,23321,23323,23325,23329,23333,23341,23352,23361,23371,23372,23378,23382,23390,23400,23406,23407,23420,23421,23422,23423,23425,23428,23430,23434,23438,23440,23441,23443,23444,23446,23464,23465,23468,23469,23471,23473,23474,23479,23482,23484,23488,23489,23501,23503,23510,23511,23512,23513,23514,23520,23535,23537,23540,23549,23564,23575,23582,23583,23587,23590,23593,23595,23596,23598,23600,23602,23605,23606,23641,23642,23644,23650,23651,23655,23656,23657,23661,23664,23668,23669,23674,23675,23676,23677,23687,23688,23690,23695,23698,23709,23711,23712,23714,23715,23718,23722,23730,23732,23733,23738,23753,23755,23762,23773,23767,23790,23793,23794,23796,23809,23814,23821,23826,23851,23843,23844,23846,23847,23857,23860,23865,23869,23871,23874,23875,23878,23880,23893,23889,23897,23882,23903,23904,23905,23906,23908,23914,23917,23920,23929,23930,23934,23935,23937,23939,23944,23946,23954,23955,23956,23957,23961,23963,23967,23968,23975,23979,23984,23988,23992,23993,24003,24007,24011,24016,24014,24024,24025,24032,24036,24041,24056,24057,24064,24071,24077,24082,24084,24085,24088,24095,24096,24110,24104,24114,24117,24126,24139,24144,24137,24145,24150,24152,24155,24156,24158,24168,24170,24171,24172,24173,24174,24176,24192,24203,24206,24226,24228,24229,24232,24234,24236,24241,24243,24253,24254,24255,24262,24268,24267,24270,24273,24274,24276,24277,24284,24286,24293,24299,24322,24326,24327,24328,24334,24345,24348,24349,24353,24354,24355,24356,24360,24363,24364,24366,24368,24372,24374,24379,24381,24383,24384,24388,24389,24391,24397,24400,24404,24408,24411,24416,24419,24420,24423,24431,24434,24436,24437,24440,24442,24445,24446,24457,24461,24463,24470,24476,24477,24482,24487,24491,24484,24492,24495,24496,24497,24504,24516,24519,24520,24521,24523,24528,24529,24530,24531,24532,24542,24545,24546,24552,24553,24554,24556,24557,24558,24559,24562,24563,24566,24570,24572,24583,24586,24589,24595,24596,24599,24600,24602,24607,24612,24621,24627,24629,24640,24647,24648,24649,24652,24657,24660,24662,24663,24669,24673,24679,24689,24702,24703,24706,24710,24712,24714,24718,24721,24723,24725,24728,24733,24734,24738,24740,24741,24744,24752,24753,24759,24763,24766,24770,24772,24776,24777,24778,24779,24782,24783,24788,24789,24793,24795,24797,24798,24802,24805,24818,24821,24824,24828,24829,24834,24839,24842,24844,24848,24849,24850,24851,24852,24854,24855,24857,24860,24862,24866,24874,24875,24880,24881,24885,24886,24887,24889,24897,24901,24902,24905,24926,24928,24940,24946,24952,24955,24956,24959,24960,24961,24963,24964,24971,24973,24978,24979,24983,24984,24988,24989,24991,24992,24997,25000,25002,25005,25016,25017,25020,25024,25025,25026,25038,25039,25045,25052,25053,25054,25055,25057,25058,25063,25065,25061,25068,25069,25071,25089,25091,25092,25095,25107,25109,25116,25120,25122,25123,25127,25129,25131,25145,25149,25154,25155,25156,25158,25164,25168,25169,25170,25172,25174,25178,25180,25188,25197,25199,25203,25210,25213,25229,25230,25231,25232,25254,25256,25267,25270,25271,25274,25278,25279,25284,25294,25301,25302,25306,25322,25330,25332,25340,25341,25347,25348,25354,25355,25357,25360,25363,25366,25368,25385,25386,25389,25397,25398,25401,25404,25409,25410,25411,25412,25414,25418,25419,25422,25426,25427,25428,25432,25435,25445,25446,25452,25453,25457,25460,25461,25464,25468,25469,25471,25474,25476,25479,25482,25488,25492,25493,25497,25498,25502,25508,25510,25517,25518,25519,25533,25537,25541,25544,25550,25553,25555,25556,25557,25564,25568,25573,25578,25580,25586,25587,25589,25592,25593,25609,25610,25616,25618,25620,25624,25630,25632,25634,25636,25637,25641,25642,25647,25648,25653,25661,25663,25675,25679,25681,25682,25683,25684,25690,25691,25692,25693,25695,25696,25697,25699,25709,25715,25716,25723,25725,25733,25735,25743,25744,25745,25752,25753,25755,25757,25759,25761,25763,25766,25768,25772,25779,25789,25790,25791,25796,25801,25802,25803,25804,25806,25808,25809,25813,25815,25828,25829,25833,25834,25837,25840,25845,25847,25851,25855,25857,25860,25864,25865,25866,25871,25875,25876,25878,25881,25883,25886,25887,25890,25894,25897,25902,25905,25914,25916,25917,25923,25927,25929,25936,25938,25940,25951,25952,25959,25963,25978,25981,25985,25989,25994,26002,26005,26008,26013,26016,26019,26022,26030,26034,26035,26036,26047,26050,26056,26057,26062,26064,26068,26070,26072,26079,26096,26098,26100,26101,26105,26110,26111,26112,26116,26120,26121,26125,26129,26130,26133,26134,26141,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26161,26163,26169,26167,26176,26181,26182,26186,26188,26193,26190,26199,26200,26201,26203,26204,26208,26209,26363,26218,26219,26220,26238,26227,26229,26239,26231,26232,26233,26235,26240,26236,26251,26252,26253,26256,26258,26265,26266,26267,26268,26271,26272,26276,26285,26289,26290,26293,26299,26303,26304,26306,26307,26312,26316,26318,26319,26324,26331,26335,26344,26347,26348,26350,26362,26373,26375,26382,26387,26393,26396,26400,26402,26419,26430,26437,26439,26440,26444,26452,26453,26461,26470,26476,26478,26484,26486,26491,26497,26500,26510,26511,26513,26515,26518,26520,26521,26523,26544,26545,26546,26549,26555,26556,26557,26617,26560,26562,26563,26565,26568,26569,26578,26583,26585,26588,26593,26598,26608,26610,26614,26615,26706,26644,26649,26653,26655,26664,26663,26668,26669,26671,26672,26673,26675,26683,26687,26692,26693,26698,26700,26709,26711,26712,26715,26731,26734,26735,26736,26737,26738,26741,26745,26746,26747,26748,26754,26756,26758,26760,26774,26776,26778,26780,26785,26787,26789,26793,26794,26798,26802,26811,26821,26824,26828,26831,26832,26833,26835,26838,26841,26844,26845,26853,26856,26858,26859,26860,26861,26864,26865,26869,26870,26875,26876,26877,26886,26889,26890,26896,26897,26899,26902,26903,26929,26931,26933,26936,26939,26946,26949,26953,26958,26967,26971,26979,26980,26981,26982,26984,26985,26988,26992,26993,26994,27002,27003,27007,27008,27021,27026,27030,27032,27041,27045,27046,27048,27051,27053,27055,27063,27064,27066,27068,27077,27080,27089,27094,27095,27106,27109,27118,27119,27121,27123,27125,27134,27136,27137,27139,27151,27153,27157,27162,27165,27168,27172,27176,27184,27186,27188,27191,27195,27198,27199,27205,27206,27209,27210,27214,27216,27217,27218,27221,27222,27227,27236,27239,27242,27249,27251,27262,27265,27267,27270,27271,27273,27275,27281,27291,27293,27294,27295,27301,27307,27311,27312,27313,27316,27325,27326,27327,27334,27337,27336,27340,27344,27348,27349,27350,27356,27357,27364,27367,27372,27376,27377,27378,27388,27389,27394,27395,27398,27399,27401,27407,27408,27409,27415,27419,27422,27428,27432,27435,27436,27439,27445,27446,27451,27455,27462,27466,27469,27474,27478,27480,27485,27488,27495,27499,27502,27504,27509,27517,27518,27522,27525,27543,27547,27551,27552,27554,27555,27560,27561,27564,27565,27566,27568,27576,27577,27581,27582,27587,27588,27593,27596,27606,27610,27617,27619,27622,27623,27630,27633,27639,27641,27647,27650,27652,27653,27657,27661,27662,27664,27666,27673,27679,27686,27687,27688,27692,27694,27699,27701,27702,27706,27707,27711,27722,27723,27725,27727,27730,27732,27737,27739,27740,27755,27757,27759,27764,27766,27768,27769,27771,27781,27782,27783,27785,27796,27797,27799,27800,27804,27807,27824,27826,27828,27842,27846,27853,27855,27856,27857,27858,27860,27862,27866,27868,27872,27879,27881,27883,27884,27886,27890,27892,27908,27911,27914,27918,27919,27921,27923,27930,27942,27943,27944,27751,27950,27951,27953,27961,27964,27967,27991,27998,27999,28001,28005,28007,28015,28016,28028,28034,28039,28049,28050,28052,28054,28055,28056,28074,28076,28084,28087,28089,28093,28095,28100,28104,28106,28110,28111,28118,28123,28125,28127,28128,28130,28133,28137,28143,28144,28148,28150,28156,28160,28164,28190,28194,28199,28210,28214,28217,28219,28220,28228,28229,28232,28233,28235,28239,28241,28242,28243,28244,28247,28252,28253,28254,28258,28259,28264,28275,28283,28285,28301,28307,28313,28320,28327,28333,28334,28337,28339,28347,28351,28352,28353,28355,28359,28360,28362,28365,28366,28367,28395,28397,28398,28409,28411,28413,28420,28424,28426,28428,28429,28438,28440,28442,28443,28454,28457,28458,28463,28464,28467,28470,28475,28476,28461,28495,28497,28498,28499,28503,28505,28506,28509,28510,28513,28514,28520,28524,28541,28542,28547,28551,28552,28555,28556,28557,28560,28562,28563,28564,28566,28570,28575,28576,28581,28582,28583,28584,28590,28591,28592,28597,28598,28604,28613,28615,28616,28618,28634,28638,28648,28649,28656,28661,28665,28668,28669,28672,28677,28678,28679,28685,28695,28704,28707,28719,28724,28727,28729,28732,28739,28740,28744,28745,28746,28747,28756,28757,28765,28766,28750,28772,28773,28780,28782,28789,28790,28798,28801,28805,28806,28820,28821,28822,28823,28824,28827,28836,28843,28848,28849,28852,28855,28874,28881,28883,28884,28885,28886,28888,28892,28900,28922,28931,28932,28933,28934,28935,28939,28940,28943,28958,28960,28971,28973,28975,28976,28977,28984,28993,28997,28998,28999,29002,29003,29008,29010,29015,29018,29020,29022,29024,29032,29049,29056,29061,29063,29068,29074,29082,29083,29088,29090,29103,29104,29106,29107,29114,29119,29120,29121,29124,29131,29132,29139,29142,29145,29146,29148,29176,29182,29184,29191,29192,29193,29203,29207,29210,29213,29215,29220,29227,29231,29236,29240,29241,29249,29250,29251,29253,29262,29263,29264,29267,29269,29270,29274,29276,29278,29280,29283,29288,29291,29294,29295,29297,29303,29304,29307,29308,29311,29316,29321,29325,29326,29331,29339,29352,29357,29358,29361,29364,29374,29377,29383,29385,29388,29397,29398,29400,29407,29413,29427,29428,29434,29435,29438,29442,29444,29445,29447,29451,29453,29458,29459,29464,29465,29470,29474,29476,29479,29480,29484,29489,29490,29493,29498,29499,29501,29507,29517,29520,29522,29526,29528,29533,29534,29535,29536,29542,29543,29545,29547,29548,29550,29551,29553,29559,29561,29564,29568,29569,29571,29573,29574,29582,29584,29587,29589,29591,29592,29596,29598,29599,29600,29602,29605,29606,29610,29611,29613,29621,29623,29625,29628,29629,29631,29637,29638,29641,29643,29644,29647,29650,29651,29654,29657,29661,29665,29667,29670,29671,29673,29684,29685,29687,29689,29690,29691,29693,29695,29696,29697,29700,29703,29706,29713,29722,29723,29732,29734,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29753,29760,29763,29764,29766,29767,29771,29773,29777,29778,29783,29789,29794,29798,29799,29800,29803,29805,29806,29809,29810,29824,29825,29829,29830,29831,29833,29839,29840,29841,29842,29848,29849,29850,29852,29855,29856,29857,29859,29862,29864,29865,29866,29867,29870,29871,29873,29874,29877,29881,29883,29887,29896,29897,29900,29904,29907,29912,29914,29915,29918,29919,29924,29928,29930,29931,29935,29940,29946,29947,29948,29951,29958,29970,29974,29975,29984,29985,29988,29991,29993,29994,29999,30006,30009,30013,30014,30015,30016,30019,30023,30024,30030,30032,30034,30039,30046,30047,30049,30063,30065,30073,30074,30075,30076,30077,30078,30081,30085,30096,30098,30099,30101,30105,30108,30114,30116,30132,30138,30143,30144,30145,30148,30150,30156,30158,30159,30167,30172,30175,30176,30177,30180,30183,30188,30190,30191,30193,30201,30208,30210,30211,30212,30215,30216,30218,30220,30223,30226,30227,30229,30230,30233,30235,30236,30237,30238,30243,30245,30246,30249,30253,30258,30259,30261,30264,30265,30266,30268,30282,30272,30273,30275,30276,30277,30281,30283,30293,30297,30303,30308,30309,30317,30318,30319,30321,30324,30337,30341,30348,30349,30357,30363,30364,30365,30367,30368,30370,30371,30372,30373,30374,30375,30376,30378,30381,30397,30401,30405,30409,30411,30412,30414,30420,30425,30432,30438,30440,30444,30448,30449,30454,30457,30460,30464,30470,30474,30478,30482,30484,30485,30487,30489,30490,30492,30498,30504,30509,30510,30511,30516,30517,30518,30521,30525,30526,30530,30533,30534,30538,30541,30542,30543,30546,30550,30551,30556,30558,30559,30560,30562,30564,30567,30570,30572,30576,30578,30579,30580,30586,30589,30592,30596,30604,30605,30612,30613,30614,30618,30623,30626,30631,30634,30638,30639,30641,30645,30654,30659,30665,30673,30674,30677,30681,30686,30687,30688,30692,30694,30698,30700,30704,30705,30708,30712,30715,30725,30726,30729,30733,30734,30737,30749,30753,30754,30755,30765,30766,30768,30773,30775,30787,30788,30791,30792,30796,30798,30802,30812,30814,30816,30817,30819,30820,30824,30826,30830,30842,30846,30858,30863,30868,30872,30881,30877,30878,30879,30884,30888,30892,30893,30896,30897,30898,30899,30907,30909,30911,30919,30920,30921,30924,30926,30930,30931,30933,30934,30948,30939,30943,30944,30945,30950,30954,30962,30963,30976,30966,30967,30970,30971,30975,30982,30988,30992,31002,31004,31006,31007,31008,31013,31015,31017,31021,31025,31028,31029,31035,31037,31039,31044,31045,31046,31050,31051,31055,31057,31060,31064,31067,31068,31079,31081,31083,31090,31097,31099,31100,31102,31115,31116,31121,31123,31124,31125,31126,31128,31131,31132,31137,31144,31145,31147,31151,31153,31156,31160,31163,31170,31172,31175,31176,31178,31183,31188,31190,31194,31197,31198,31200,31202,31205,31210,31211,31213,31217,31224,31228,31234,31235,31239,31241,31242,31244,31249,31253,31259,31262,31265,31271,31275,31277,31279,31280,31284,31285,31288,31289,31290,31300,31301,31303,31304,31308,31317,31318,31321,31324,31325,31327,31328,31333,31335,31338,31341,31349,31352,31358,31360,31362,31365,31366,31370,31371,31376,31377,31380,31390,31392,31395,31404,31411,31413,31417,31419,31420,31430,31433,31436,31438,31441,31451,31464,31465,31467,31468,31473,31476,31483,31485,31486,31495,31508,31519,31523,31527,31529,31530,31531,31533,31534,31535,31536,31537,31540,31549,31551,31552,31553,31559,31566,31573,31584,31588,31590,31593,31594,31597,31599,31602,31603,31607,31620,31625,31630,31632,31633,31638,31643,31646,31648,31653,31660,31663,31664,31666,31669,31670,31674,31675,31676,31677,31682,31685,31688,31690,31700,31702,31703,31705,31706,31707,31720,31722,31730,31732,31733,31736,31737,31738,31740,31742,31745,31746,31747,31748,31750,31753,31755,31756,31758,31759,31769,31771,31776,31781,31782,31784,31788,31793,31795,31796,31798,31801,31802,31814,31818,31829,31825,31826,31827,31833,31834,31835,31836,31837,31838,31841,31843,31847,31849,31853,31854,31856,31858,31865,31868,31869,31878,31879,31887,31892,31902,31904,31910,31920,31926,31927,31930,31931,31932,31935,31940,31943,31944,31945,31949,31951,31955,31956,31957,31959,31961,31962,31965,31974,31977,31979,31989,32003,32007,32008,32009,32015,32017,32018,32019,32022,32029,32030,32035,32038,32042,32045,32049,32060,32061,32062,32064,32065,32071,32072,32077,32081,32083,32087,32089,32090,32092,32093,32101,32103,32106,32112,32120,32122,32123,32127,32129,32130,32131,32133,32134,32136,32139,32140,32141,32145,32150,32151,32157,32158,32166,32167,32170,32179,32182,32183,32185,32194,32195,32196,32197,32198,32204,32205,32206,32215,32217,32256,32226,32229,32230,32234,32235,32237,32241,32245,32246,32249,32250,32264,32272,32273,32277,32279,32284,32285,32288,32295,32296,32300,32301,32303,32307,32310,32319,32324,32325,32327,32334,32336,32338,32344,32351,32353,32354,32357,32363,32366,32367,32371,32376,32382,32385,32390,32391,32394,32397,32401,32405,32408,32410,32413,32414,32572,32571,32573,32574,32575,32579,32580,32583,32591,32594,32595,32603,32604,32605,32609,32611,32612,32613,32614,32621,32625,32637,32638,32639,32640,32651,32653,32655,32656,32657,32662,32663,32668,32673,32674,32678,32682,32685,32692,32700,32703,32704,32707,32712,32718,32719,32731,32735,32739,32741,32744,32748,32750,32751,32754,32762,32765,32766,32767,32775,32776,32778,32781,32782,32783,32785,32787,32788,32790,32797,32798,32799,32800,32804,32806,32812,32814,32816,32820,32821,32823,32825,32826,32828,32830,32832,32836,32864,32868,32870,32877,32881,32885,32897,32904,32910,32924,32926,32934,32935,32939,32952,32953,32968,32973,32975,32978,32980,32981,32983,32984,32992,33005,33006,33008,33010,33011,33014,33017,33018,33022,33027,33035,33046,33047,33048,33052,33054,33056,33060,33063,33068,33072,33077,33082,33084,33093,33095,33098,33100,33106,33111,33120,33121,33127,33128,33129,33133,33135,33143,33153,33168,33156,33157,33158,33163,33166,33174,33176,33179,33182,33186,33198,33202,33204,33211,33227,33219,33221,33226,33230,33231,33237,33239,33243,33245,33246,33249,33252,33259,33260,33264,33265,33266,33269,33270,33272,33273,33277,33279,33280,33283,33295,33299,33300,33305,33306,33309,33313,33314,33320,33330,33332,33338,33347,33348,33349,33350,33355,33358,33359,33361,33366,33372,33376,33379,33383,33389,33396,33403,33405,33407,33408,33409,33411,33412,33415,33417,33418,33422,33425,33428,33430,33432,33434,33435,33440,33441,33443,33444,33447,33448,33449,33450,33454,33456,33458,33460,33463,33466,33468,33470,33471,33478,33488,33493,33498,33504,33506,33508,33512,33514,33517,33519,33526,33527,33533,33534,33536,33537,33543,33544,33546,33547,33620,33563,33565,33566,33567,33569,33570,33580,33581,33582,33584,33587,33591,33594,33596,33597,33602,33603,33604,33607,33613,33614,33617,33621,33622,33623,33648,33656,33661,33663,33664,33666,33668,33670,33677,33682,33684,33685,33688,33689,33691,33692,33693,33702,33703,33705,33708,33726,33727,33728,33735,33737,33743,33744,33745,33748,33757,33619,33768,33770,33782,33784,33785,33788,33793,33798,33802,33807,33809,33813,33817,33709,33839,33849,33861,33863,33864,33866,33869,33871,33873,33874,33878,33880,33881,33882,33884,33888,33892,33893,33895,33898,33904,33907,33908,33910,33912,33916,33917,33921,33925,33938,33939,33941,33950,33958,33960,33961,33962,33967,33969,33972,33978,33981,33982,33984,33986,33991,33992,33996,33999,34003,34012,34023,34026,34031,34032,34033,34034,34039,34098,34042,34043,34045,34050,34051,34055,34060,34062,34064,34076,34078,34082,34083,34084,34085,34087,34090,34091,34095,34099,34100,34102,34111,34118,34127,34128,34129,34130,34131,34134,34137,34140,34141,34142,34143,34144,34145,34146,34148,34155,34159,34169,34170,34171,34173,34175,34177,34181,34182,34185,34187,34188,34191,34195,34200,34205,34207,34208,34210,34213,34215,34228,34230,34231,34232,34236,34237,34238,34239,34242,34247,34250,34251,34254,34221,34264,34266,34271,34272,34278,34280,34285,34291,34294,34300,34303,34304,34308,34309,34317,34318,34320,34321,34322,34328,34329,34331,34334,34337,34343,34345,34358,34360,34362,34364,34365,34368,34370,34374,34386,34387,34390,34391,34392,34393,34397,34400,34401,34402,34403,34404,34409,34412,34415,34421,34422,34423,34426,34445,34449,34454,34456,34458,34460,34465,34470,34471,34472,34477,34481,34483,34484,34485,34487,34488,34489,34495,34496,34497,34499,34501,34513,34514,34517,34519,34522,34524,34528,34531,34533,34535,34440,34554,34556,34557,34564,34565,34567,34571,34574,34575,34576,34579,34580,34585,34590,34591,34593,34595,34600,34606,34607,34609,34610,34617,34618,34620,34621,34622,34624,34627,34629,34637,34648,34653,34657,34660,34661,34671,34673,34674,34683,34691,34692,34693,34694,34695,34696,34697,34699,34700,34704,34707,34709,34711,34712,34713,34718,34720,34723,34727,34732,34733,34734,34737,34741,34750,34751,34753,34760,34761,34762,34766,34773,34774,34777,34778,34780,34783,34786,34787,34788,34794,34795,34797,34801,34803,34808,34810,34815,34817,34819,34822,34825,34826,34827,34832,34841,34834,34835,34836,34840,34842,34843,34844,34846,34847,34856,34861,34862,34864,34866,34869,34874,34876,34881,34883,34885,34888,34889,34890,34891,34894,34897,34901,34902,34904,34906,34908,34911,34912,34916,34921,34929,34937,34939,34944,34968,34970,34971,34972,34975,34976,34984,34986,35002,35005,35006,35008,35018,35019,35020,35021,35022,35025,35026,35027,35035,35038,35047,35055,35056,35057,35061,35063,35073,35078,35085,35086,35087,35093,35094,35096,35097,35098,35100,35104,35110,35111,35112,35120,35121,35122,35125,35129,35130,35134,35136,35138,35141,35142,35145,35151,35154,35159,35162,35163,35164,35169,35170,35171,35179,35182,35184,35187,35189,35194,35195,35196,35197,35209,35213,35216,35220,35221,35227,35228,35231,35232,35237,35248,35252,35253,35254,35255,35260,35284,35285,35286,35287,35288,35301,35305,35307,35309,35313,35315,35318,35321,35325,35327,35332,35333,35335,35343,35345,35346,35348,35349,35358,35360,35362,35364,35366,35371,35372,35375,35381,35383,35389,35390,35392,35395,35397,35399,35401,35405,35406,35411,35414,35415,35416,35420,35421,35425,35429,35431,35445,35446,35447,35449,35450,35451,35454,35455,35456,35459,35462,35467,35471,35472,35474,35478,35479,35481,35487,35495,35497,35502,35503,35507,35510,35511,35515,35518,35523,35526,35528,35529,35530,35537,35539,35540,35541,35543,35549,35551,35564,35568,35572,35573,35574,35580,35583,35589,35590,35595,35601,35612,35614,35615,35594,35629,35632,35639,35644,35650,35651,35652,35653,35654,35656,35666,35667,35668,35673,35661,35678,35683,35693,35702,35704,35705,35708,35710,35713,35716,35717,35723,35725,35727,35732,35733,35740,35742,35743,35896,35897,35901,35902,35909,35911,35913,35915,35919,35921,35923,35924,35927,35928,35931,35933,35929,35939,35940,35942,35944,35945,35949,35955,35957,35958,35963,35966,35974,35975,35979,35984,35986,35987,35993,35995,35996,36004,36025,36026,36037,36038,36041,36043,36047,36054,36053,36057,36061,36065,36072,36076,36079,36080,36082,36085,36087,36088,36094,36095,36097,36099,36105,36114,36119,36123,36197,36201,36204,36206,36223,36226,36228,36232,36237,36240,36241,36245,36254,36255,36256,36262,36267,36268,36271,36274,36277,36279,36281,36283,36288,36293,36294,36295,36296,36298,36302,36305,36308,36309,36311,36313,36324,36325,36327,36332,36336,36284,36337,36338,36340,36349,36353,36356,36357,36358,36363,36369,36372,36374,36384,36385,36386,36387,36390,36391,36401,36403,36406,36407,36408,36409,36413,36416,36417,36427,36429,36430,36431,36436,36443,36444,36445,36446,36449,36450,36457,36460,36461,36463,36464,36465,36473,36474,36475,36482,36483,36489,36496,36498,36501,36506,36507,36509,36510,36514,36519,36521,36525,36526,36531,36533,36538,36539,36544,36545,36547,36548,36551,36559,36561,36564,36572,36584,36590,36592,36593,36599,36601,36602,36589,36608,36610,36615,36616,36623,36624,36630,36631,36632,36638,36640,36641,36643,36645,36647,36648,36652,36653,36654,36660,36661,36662,36663,36666,36672,36673,36675,36679,36687,36689,36690,36691,36692,36693,36696,36701,36702,36709,36765,36768,36769,36772,36773,36774,36789,36790,36792,36798,36800,36801,36806,36810,36811,36813,36816,36818,36819,36821,36832,36835,36836,36840,36846,36849,36853,36854,36859,36862,36866,36868,36872,36876,36888,36891,36904,36905,36911,36906,36908,36909,36915,36916,36919,36927,36931,36932,36940,36955,36957,36962,36966,36967,36972,36976,36980,36985,36997,37000,37003,37004,37006,37008,37013,37015,37016,37017,37019,37024,37025,37026,37029,37040,37042,37043,37044,37046,37053,37068,37054,37059,37060,37061,37063,37064,37077,37079,37080,37081,37084,37085,37087,37093,37074,37110,37099,37103,37104,37108,37118,37119,37120,37124,37125,37126,37128,37133,37136,37140,37142,37143,37144,37146,37148,37150,37152,37157,37154,37155,37159,37161,37166,37167,37169,37172,37174,37175,37177,37178,37180,37181,37187,37191,37192,37199,37203,37207,37209,37210,37211,37217,37220,37223,37229,37236,37241,37242,37243,37249,37251,37253,37254,37258,37262,37265,37267,37268,37269,37272,37278,37281,37286,37288,37292,37293,37294,37296,37297,37298,37299,37302,37307,37308,37309,37311,37314,37315,37317,37331,37332,37335,37337,37338,37342,37348,37349,37353,37354,37356,37357,37358,37359,37360,37361,37367,37369,37371,37373,37376,37377,37380,37381,37382,37383,37385,37386,37388,37392,37394,37395,37398,37400,37404,37405,37411,37412,37413,37414,37416,37422,37423,37424,37427,37429,37430,37432,37433,37434,37436,37438,37440,37442,37443,37446,37447,37450,37453,37454,37455,37457,37464,37465,37468,37469,37472,37473,37477,37479,37480,37481,37486,37487,37488,37493,37494,37495,37496,37497,37499,37500,37501,37503,37512,37513,37514,37517,37518,37522,37527,37529,37535,37536,37540,37541,37543,37544,37547,37551,37554,37558,37560,37562,37563,37564,37565,37567,37568,37569,37570,37571,37573,37574,37575,37576,37579,37580,37581,37582,37584,37587,37589,37591,37592,37593,37596,37597,37599,37600,37601,37603,37605,37607,37608,37612,37614,37616,37625,37627,37631,37632,37634,37640,37645,37649,37652,37653,37660,37661,37662,37663,37665,37668,37669,37671,37673,37674,37683,37684,37686,37687,37703,37704,37705,37712,37713,37714,37717,37719,37720,37722,37726,37732,37733,37735,37737,37738,37741,37743,37744,37745,37747,37748,37750,37754,37757,37759,37760,37761,37762,37768,37770,37771,37773,37775,37778,37781,37784,37787,37790,37793,37795,37796,37798,37800,37803,37812,37813,37814,37818,37801,37825,37828,37829,37830,37831,37833,37834,37835,37836,37837,37843,37849,37852,37854,37855,37858,37862,37863,37881,37879,37880,37882,37883,37885,37889,37890,37892,37896,37897,37901,37902,37903,37909,37910,37911,37919,37934,37935,37937,37938,37939,37940,37947,37951,37949,37955,37957,37960,37962,37964,37973,37977,37980,37983,37985,37987,37992,37995,37997,37998,37999,38001,38002,38020,38019,38264,38265,38270,38276,38280,38284,38285,38286,38301,38302,38303,38305,38310,38313,38315,38316,38324,38326,38330,38333,38335,38342,38344,38345,38347,38352,38353,38354,38355,38361,38362,38365,38366,38367,38368,38372,38374,38429,38430,38434,38436,38437,38438,38444,38449,38451,38455,38456,38457,38458,38460,38461,38465,38482,38484,38486,38487,38488,38497,38510,38516,38523,38524,38526,38527,38529,38530,38531,38532,38537,38545,38550,38554,38557,38559,38564,38565,38566,38569,38574,38575,38579,38586,38602,38610,23986,38616,38618,38621,38622,38623,38633,38639,38641,38650,38658,38659,38661,38665,38682,38683,38685,38689,38690,38691,38696,38705,38707,38721,38723,38730,38734,38735,38741,38743,38744,38746,38747,38755,38759,38762,38766,38771,38774,38775,38776,38779,38781,38783,38784,38793,38805,38806,38807,38809,38810,38814,38815,38818,38828,38830,38833,38834,38837,38838,38840,38841,38842,38844,38846,38847,38849,38852,38853,38855,38857,38858,38860,38861,38862,38864,38865,38868,38871,38872,38873,38877,38878,38880,38875,38881,38884,38895,38897,38900,38903,38904,38906,38919,38922,38937,38925,38926,38932,38934,38940,38942,38944,38947,38950,38955,38958,38959,38960,38962,38963,38965,38949,38974,38980,38983,38986,38993,38994,38995,38998,38999,39001,39002,39010,39011,39013,39014,39018,39020,39083,39085,39086,39088,39092,39095,39096,39098,39099,39103,39106,39109,39112,39116,39137,39139,39141,39142,39143,39146,39155,39158,39170,39175,39176,39185,39189,39190,39191,39194,39195,39196,39199,39202,39206,39207,39211,39217,39218,39219,39220,39221,39225,39226,39227,39228,39232,39233,39238,39239,39240,39245,39246,39252,39256,39257,39259,39260,39262,39263,39264,39323,39325,39327,39334,39344,39345,39346,39349,39353,39354,39357,39359,39363,39369,39379,39380,39385,39386,39388,39390,39399,39402,39403,39404,39408,39412,39413,39417,39421,39422,39426,39427,39428,39435,39436,39440,39441,39446,39454,39456,39458,39459,39460,39463,39469,39470,39475,39477,39478,39480,39495,39489,39492,39498,39499,39500,39502,39505,39508,39510,39517,39594,39596,39598,39599,39602,39604,39605,39606,39609,39611,39614,39615,39617,39619,39622,39624,39630,39632,39634,39637,39638,39639,39643,39644,39648,39652,39653,39655,39657,39660,39666,39667,39669,39673,39674,39677,39679,39680,39681,39682,39683,39684,39685,39688,39689,39691,39692,39693,39694,39696,39698,39702,39705,39707,39708,39712,39718,39723,39725,39731,39732,39733,39735,39737,39738,39741,39752,39755,39756,39765,39766,39767,39771,39774,39777,39779,39781,39782,39784,39786,39787,39788,39789,39790,39795,39797,39799,39800,39801,39807,39808,39812,39813,39814,39815,39817,39818,39819,39821,39823,39824,39828,39834,39837,39838,39846,39847,39849,39852,39856,39857,39858,39863,39864,39867,39868,39870,39871,39873,39879,39880,39886,39888,39895,39896,39901,39903,39909,39911,39914,39915,39919,39923,39927,39928,39929,39930,39933,39935,39936,39938,39947,39951,39953,39958,39960,39961,39962,39964,39966,39970,39971,39974,39975,39976,39977,39978,39985,39989,39990,39991,39997,40001,40003,40004,40005,40009,40010,40014,40015,40016,40019,40020,40022,40024,40027,40029,40030,40031,40035,40041,40042,40028,40043,40040,40046,40048,40050,40053,40055,40059,40166,40178,40183,40185,40203,40194,40209,40215,40216,40220,40221,40222,40239,40240,40242,40243,40244,40250,40252,40261,40253,40258,40259,40263,40266,40275,40276,40287,40291,40290,40293,40297,40298,40299,40304,40310,40311,40315,40316,40318,40323,40324,40326,40330,40333,40334,40338,40339,40341,40342,40343,40344,40353,40362,40364,40366,40369,40373,40377,40380,40383,40387,40391,40393,40394,40404,40405,40406,40407,40410,40414,40415,40416,40421,40423,40425,40427,40430,40432,40435,40436,40446,40458,40450,40455,40462,40464,40465,40466,40469,40470,40473,40476,40477,40570,40571,40572,40576,40578,40579,40580,40581,40583,40590,40591,40598,40600,40603,40606,40612,40616,40620,40622,40623,40624,40627,40628,40629,40646,40648,40651,40661,40671,40676,40679,40684,40685,40686,40688,40689,40690,40693,40696,40703,40706,40707,40713,40719,40720,40721,40722,40724,40726,40727,40729,40730,40731,40735,40738,40742,40746,40747,40751,40753,40754,40756,40759,40761,40762,40764,40765,40767,40769,40771,40772,40773,40774,40775,40787,40789,40790,40791,40792,40794,40797,40798,40808,40809,40813,40814,40815,40816,40817,40819,40821,40826,40829,40847,40848,40849,40850,40852,40854,40855,40862,40865,40866,40867,40869,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160], + "iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729], + "iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729], + "iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119], + "iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null], + "iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312], + "iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217], + "iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255], + "iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255], + "koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711], + "windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null], + "windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103], + "windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255], + "windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746], + "windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729], + "windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255], + "x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364] + }; + + // For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + }(this || {})); + },{}],109:[function(require,module,exports){ + // This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + + /** + * @fileoverview Global |this| required for resolving indexes in node. + * @suppress {globalThis} + */ + (function(global) { + + // If we're in node require encoding-indexes and attach it to the global. + if (typeof module !== "undefined" && module.exports && + !global["encoding-indexes"]) { + global["encoding-indexes"] = + require("./encoding-indexes.js")["encoding-indexes"]; + } + + // + // Utilities + // + + /** + * @param {number} a The number to test. + * @param {number} min The minimum value in the range, inclusive. + * @param {number} max The maximum value in the range, inclusive. + * @return {boolean} True if a >= min and a <= max. + */ + function inRange(a, min, max) { + return min <= a && a <= max; + } + + /** + * @param {!Array.<*>} array The array to check. + * @param {*} item The item to look for in the array. + * @return {boolean} True if the item appears in the array. + */ + function includes(array, item) { + return array.indexOf(item) !== -1; + } + + var floor = Math.floor; + + /** + * @param {*} o + * @return {Object} + */ + function ToDictionary(o) { + if (o === undefined) return {}; + if (o === Object(o)) return o; + throw TypeError('Could not convert argument to dictionary'); + } + + /** + * @param {string} string Input string of UTF-16 code units. + * @return {!Array.} Code points. + */ + function stringToCodePoints(string) { + // https://heycam.github.io/webidl/#dfn-obtain-unicode + + // 1. Let S be the DOMString value. + var s = String(string); + + // 2. Let n be the length of S. + var n = s.length; + + // 3. Initialize i to 0. + var i = 0; + + // 4. Initialize U to be an empty sequence of Unicode characters. + var u = []; + + // 5. While i < n: + while (i < n) { + + // 1. Let c be the code unit in S at index i. + var c = s.charCodeAt(i); + + // 2. Depending on the value of c: + + // c < 0xD800 or c > 0xDFFF + if (c < 0xD800 || c > 0xDFFF) { + // Append to U the Unicode character with code point c. + u.push(c); + } + + // 0xDC00 ≤ c ≤ 0xDFFF + else if (0xDC00 <= c && c <= 0xDFFF) { + // Append to U a U+FFFD REPLACEMENT CHARACTER. + u.push(0xFFFD); + } + + // 0xD800 ≤ c ≤ 0xDBFF + else if (0xD800 <= c && c <= 0xDBFF) { + // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT + // CHARACTER. + if (i === n - 1) { + u.push(0xFFFD); + } + // 2. Otherwise, i < n−1: + else { + // 1. Let d be the code unit in S at index i+1. + var d = s.charCodeAt(i + 1); + + // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: + if (0xDC00 <= d && d <= 0xDFFF) { + // 1. Let a be c & 0x3FF. + var a = c & 0x3FF; + + // 2. Let b be d & 0x3FF. + var b = d & 0x3FF; + + // 3. Append to U the Unicode character with code point + // 2^16+2^10*a+b. + u.push(0x10000 + (a << 10) + b); + + // 4. Set i to i+1. + i += 1; + } + + // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a + // U+FFFD REPLACEMENT CHARACTER. + else { + u.push(0xFFFD); + } + } + } + + // 3. Set i to i+1. + i += 1; + } + + // 6. Return U. + return u; + } + + /** + * @param {!Array.} code_points Array of code points. + * @return {string} string String of UTF-16 code units. + */ + function codePointsToString(code_points) { + var s = ''; + for (var i = 0; i < code_points.length; ++i) { + var cp = code_points[i]; + if (cp <= 0xFFFF) { + s += String.fromCharCode(cp); + } else { + cp -= 0x10000; + s += String.fromCharCode((cp >> 10) + 0xD800, + (cp & 0x3FF) + 0xDC00); + } + } + return s; + } + + + // + // Implementation of Encoding specification + // https://encoding.spec.whatwg.org/ + // + + // + // 4. Terminology + // + + /** + * An ASCII byte is a byte in the range 0x00 to 0x7F, inclusive. + * @param {number} a The number to test. + * @return {boolean} True if a is in the range 0x00 to 0x7F, inclusive. + */ + function isASCIIByte(a) { + return 0x00 <= a && a <= 0x7F; + } + + /** + * An ASCII code point is a code point in the range U+0000 to + * U+007F, inclusive. + */ + var isASCIICodePoint = isASCIIByte; + + + /** + * End-of-stream is a special token that signifies no more tokens + * are in the stream. + * @const + */ var end_of_stream = -1; + + /** + * A stream represents an ordered sequence of tokens. + * + * @constructor + * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide + * the stream. + */ + function Stream(tokens) { + /** @type {!Array.} */ + this.tokens = [].slice.call(tokens); + // Reversed as push/pop is more efficient than shift/unshift. + this.tokens.reverse(); + } + + Stream.prototype = { + /** + * @return {boolean} True if end-of-stream has been hit. + */ + endOfStream: function() { + return !this.tokens.length; + }, + + /** + * When a token is read from a stream, the first token in the + * stream must be returned and subsequently removed, and + * end-of-stream must be returned otherwise. + * + * @return {number} Get the next token from the stream, or + * end_of_stream. + */ + read: function() { + if (!this.tokens.length) + return end_of_stream; + return this.tokens.pop(); + }, + + /** + * When one or more tokens are prepended to a stream, those tokens + * must be inserted, in given order, before the first token in the + * stream. + * + * @param {(number|!Array.)} token The token(s) to prepend to the + * stream. + */ + prepend: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.push(tokens.pop()); + } else { + this.tokens.push(token); + } + }, + + /** + * When one or more tokens are pushed to a stream, those tokens + * must be inserted, in given order, after the last token in the + * stream. + * + * @param {(number|!Array.)} token The tokens(s) to push to the + * stream. + */ + push: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.unshift(tokens.shift()); + } else { + this.tokens.unshift(token); + } + } + }; + + // + // 5. Encodings + // + + // 5.1 Encoders and decoders + + /** @const */ + var finished = -1; + + /** + * @param {boolean} fatal If true, decoding errors raise an exception. + * @param {number=} opt_code_point Override the standard fallback code point. + * @return {number} The code point to insert on a decoding error. + */ + function decoderError(fatal, opt_code_point) { + if (fatal) + throw TypeError('Decoder error'); + return opt_code_point || 0xFFFD; + } + + /** + * @param {number} code_point The code point that could not be encoded. + * @return {number} Always throws, no value is actually returned. + */ + function encoderError(code_point) { + throw TypeError('The code point ' + code_point + ' could not be encoded.'); + } + + // 5.2 Names and labels + + // TODO: Define @typedef for Encoding: {name:string,labels:Array.} + // https://github.com/google/closure-compiler/issues/247 + + /** + * @param {string} label The encoding label. + * @return {?{name:string,labels:Array.}} + */ + function getEncoding(label) { + // 1. Remove any leading and trailing ASCII whitespace from label. + label = String(label).trim().toLowerCase(); + + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, return the corresponding + // encoding, and failure otherwise. + if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) { + return label_to_encoding[label]; + } + return null; + } + + /** + * Encodings table: https://encoding.spec.whatwg.org/encodings.json + * @const + * @type {!Array.<{ + * heading: string, + * encodings: Array.<{name:string,labels:Array.}> + * }>} + */ + var encodings = [ + { + "encodings": [ + { + "labels": [ + "unicode-1-1-utf-8", + "utf-8", + "utf8" + ], + "name": "UTF-8" + } + ], + "heading": "The Encoding" + }, + { + "encodings": [ + { + "labels": [ + "866", + "cp866", + "csibm866", + "ibm866" + ], + "name": "IBM866" + }, + { + "labels": [ + "csisolatin2", + "iso-8859-2", + "iso-ir-101", + "iso8859-2", + "iso88592", + "iso_8859-2", + "iso_8859-2:1987", + "l2", + "latin2" + ], + "name": "ISO-8859-2" + }, + { + "labels": [ + "csisolatin3", + "iso-8859-3", + "iso-ir-109", + "iso8859-3", + "iso88593", + "iso_8859-3", + "iso_8859-3:1988", + "l3", + "latin3" + ], + "name": "ISO-8859-3" + }, + { + "labels": [ + "csisolatin4", + "iso-8859-4", + "iso-ir-110", + "iso8859-4", + "iso88594", + "iso_8859-4", + "iso_8859-4:1988", + "l4", + "latin4" + ], + "name": "ISO-8859-4" + }, + { + "labels": [ + "csisolatincyrillic", + "cyrillic", + "iso-8859-5", + "iso-ir-144", + "iso8859-5", + "iso88595", + "iso_8859-5", + "iso_8859-5:1988" + ], + "name": "ISO-8859-5" + }, + { + "labels": [ + "arabic", + "asmo-708", + "csiso88596e", + "csiso88596i", + "csisolatinarabic", + "ecma-114", + "iso-8859-6", + "iso-8859-6-e", + "iso-8859-6-i", + "iso-ir-127", + "iso8859-6", + "iso88596", + "iso_8859-6", + "iso_8859-6:1987" + ], + "name": "ISO-8859-6" + }, + { + "labels": [ + "csisolatingreek", + "ecma-118", + "elot_928", + "greek", + "greek8", + "iso-8859-7", + "iso-ir-126", + "iso8859-7", + "iso88597", + "iso_8859-7", + "iso_8859-7:1987", + "sun_eu_greek" + ], + "name": "ISO-8859-7" + }, + { + "labels": [ + "csiso88598e", + "csisolatinhebrew", + "hebrew", + "iso-8859-8", + "iso-8859-8-e", + "iso-ir-138", + "iso8859-8", + "iso88598", + "iso_8859-8", + "iso_8859-8:1988", + "visual" + ], + "name": "ISO-8859-8" + }, + { + "labels": [ + "csiso88598i", + "iso-8859-8-i", + "logical" + ], + "name": "ISO-8859-8-I" + }, + { + "labels": [ + "csisolatin6", + "iso-8859-10", + "iso-ir-157", + "iso8859-10", + "iso885910", + "l6", + "latin6" + ], + "name": "ISO-8859-10" + }, + { + "labels": [ + "iso-8859-13", + "iso8859-13", + "iso885913" + ], + "name": "ISO-8859-13" + }, + { + "labels": [ + "iso-8859-14", + "iso8859-14", + "iso885914" + ], + "name": "ISO-8859-14" + }, + { + "labels": [ + "csisolatin9", + "iso-8859-15", + "iso8859-15", + "iso885915", + "iso_8859-15", + "l9" + ], + "name": "ISO-8859-15" + }, + { + "labels": [ + "iso-8859-16" + ], + "name": "ISO-8859-16" + }, + { + "labels": [ + "cskoi8r", + "koi", + "koi8", + "koi8-r", + "koi8_r" + ], + "name": "KOI8-R" + }, + { + "labels": [ + "koi8-ru", + "koi8-u" + ], + "name": "KOI8-U" + }, + { + "labels": [ + "csmacintosh", + "mac", + "macintosh", + "x-mac-roman" + ], + "name": "macintosh" + }, + { + "labels": [ + "dos-874", + "iso-8859-11", + "iso8859-11", + "iso885911", + "tis-620", + "windows-874" + ], + "name": "windows-874" + }, + { + "labels": [ + "cp1250", + "windows-1250", + "x-cp1250" + ], + "name": "windows-1250" + }, + { + "labels": [ + "cp1251", + "windows-1251", + "x-cp1251" + ], + "name": "windows-1251" + }, + { + "labels": [ + "ansi_x3.4-1968", + "ascii", + "cp1252", + "cp819", + "csisolatin1", + "ibm819", + "iso-8859-1", + "iso-ir-100", + "iso8859-1", + "iso88591", + "iso_8859-1", + "iso_8859-1:1987", + "l1", + "latin1", + "us-ascii", + "windows-1252", + "x-cp1252" + ], + "name": "windows-1252" + }, + { + "labels": [ + "cp1253", + "windows-1253", + "x-cp1253" + ], + "name": "windows-1253" + }, + { + "labels": [ + "cp1254", + "csisolatin5", + "iso-8859-9", + "iso-ir-148", + "iso8859-9", + "iso88599", + "iso_8859-9", + "iso_8859-9:1989", + "l5", + "latin5", + "windows-1254", + "x-cp1254" + ], + "name": "windows-1254" + }, + { + "labels": [ + "cp1255", + "windows-1255", + "x-cp1255" + ], + "name": "windows-1255" + }, + { + "labels": [ + "cp1256", + "windows-1256", + "x-cp1256" + ], + "name": "windows-1256" + }, + { + "labels": [ + "cp1257", + "windows-1257", + "x-cp1257" + ], + "name": "windows-1257" + }, + { + "labels": [ + "cp1258", + "windows-1258", + "x-cp1258" + ], + "name": "windows-1258" + }, + { + "labels": [ + "x-mac-cyrillic", + "x-mac-ukrainian" + ], + "name": "x-mac-cyrillic" + } + ], + "heading": "Legacy single-byte encodings" + }, + { + "encodings": [ + { + "labels": [ + "chinese", + "csgb2312", + "csiso58gb231280", + "gb2312", + "gb_2312", + "gb_2312-80", + "gbk", + "iso-ir-58", + "x-gbk" + ], + "name": "GBK" + }, + { + "labels": [ + "gb18030" + ], + "name": "gb18030" + } + ], + "heading": "Legacy multi-byte Chinese (simplified) encodings" + }, + { + "encodings": [ + { + "labels": [ + "big5", + "big5-hkscs", + "cn-big5", + "csbig5", + "x-x-big5" + ], + "name": "Big5" + } + ], + "heading": "Legacy multi-byte Chinese (traditional) encodings" + }, + { + "encodings": [ + { + "labels": [ + "cseucpkdfmtjapanese", + "euc-jp", + "x-euc-jp" + ], + "name": "EUC-JP" + }, + { + "labels": [ + "csiso2022jp", + "iso-2022-jp" + ], + "name": "ISO-2022-JP" + }, + { + "labels": [ + "csshiftjis", + "ms932", + "ms_kanji", + "shift-jis", + "shift_jis", + "sjis", + "windows-31j", + "x-sjis" + ], + "name": "Shift_JIS" + } + ], + "heading": "Legacy multi-byte Japanese encodings" + }, + { + "encodings": [ + { + "labels": [ + "cseuckr", + "csksc56011987", + "euc-kr", + "iso-ir-149", + "korean", + "ks_c_5601-1987", + "ks_c_5601-1989", + "ksc5601", + "ksc_5601", + "windows-949" + ], + "name": "EUC-KR" + } + ], + "heading": "Legacy multi-byte Korean encodings" + }, + { + "encodings": [ + { + "labels": [ + "csiso2022kr", + "hz-gb-2312", + "iso-2022-cn", + "iso-2022-cn-ext", + "iso-2022-kr" + ], + "name": "replacement" + }, + { + "labels": [ + "utf-16be" + ], + "name": "UTF-16BE" + }, + { + "labels": [ + "utf-16", + "utf-16le" + ], + "name": "UTF-16LE" + }, + { + "labels": [ + "x-user-defined" + ], + "name": "x-user-defined" + } + ], + "heading": "Legacy miscellaneous encodings" + } + ]; + + // Label to encoding registry. + /** @type {Object.}>} */ + var label_to_encoding = {}; + encodings.forEach(function(category) { + category.encodings.forEach(function(encoding) { + encoding.labels.forEach(function(label) { + label_to_encoding[label] = encoding; + }); + }); + }); + + // Registry of of encoder/decoder factories, by encoding name. + /** @type {Object.} */ + var encoders = {}; + /** @type {Object.} */ + var decoders = {}; + + // + // 6. Indexes + // + + /** + * @param {number} pointer The |pointer| to search for. + * @param {(!Array.|undefined)} index The |index| to search within. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in |index|. + */ + function indexCodePointFor(pointer, index) { + if (!index) return null; + return index[pointer] || null; + } + + /** + * @param {number} code_point The |code point| to search for. + * @param {!Array.} index The |index| to search within. + * @return {?number} The first pointer corresponding to |code point| in + * |index|, or null if |code point| is not in |index|. + */ + function indexPointerFor(code_point, index) { + var pointer = index.indexOf(code_point); + return pointer === -1 ? null : pointer; + } + + /** + * @param {string} name Name of the index. + * @return {(!Array.|!Array.>)} + * */ + function index(name) { + if (!('encoding-indexes' in global)) { + throw Error("Indexes missing." + + " Did you forget to include encoding-indexes.js first?"); + } + return global['encoding-indexes'][name]; + } + + /** + * @param {number} pointer The |pointer| to search for in the gb18030 index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the gb18030 index. + */ + function indexGB18030RangesCodePointFor(pointer) { + // 1. If pointer is greater than 39419 and less than 189000, or + // pointer is greater than 1237575, return null. + if ((pointer > 39419 && pointer < 189000) || (pointer > 1237575)) + return null; + + // 2. If pointer is 7457, return code point U+E7C7. + if (pointer === 7457) return 0xE7C7; + + // 3. Let offset be the last pointer in index gb18030 ranges that + // is equal to or less than pointer and let code point offset be + // its corresponding code point. + var offset = 0; + var code_point_offset = 0; + var idx = index('gb18030-ranges'); + var i; + for (i = 0; i < idx.length; ++i) { + /** @type {!Array.} */ + var entry = idx[i]; + if (entry[0] <= pointer) { + offset = entry[0]; + code_point_offset = entry[1]; + } else { + break; + } + } + + // 4. Return a code point whose value is code point offset + + // pointer − offset. + return code_point_offset + pointer - offset; + } + + /** + * @param {number} code_point The |code point| to locate in the gb18030 index. + * @return {number} The first pointer corresponding to |code point| in the + * gb18030 index. + */ + function indexGB18030RangesPointerFor(code_point) { + // 1. If code point is U+E7C7, return pointer 7457. + if (code_point === 0xE7C7) return 7457; + + // 2. Let offset be the last code point in index gb18030 ranges + // that is equal to or less than code point and let pointer offset + // be its corresponding pointer. + var offset = 0; + var pointer_offset = 0; + var idx = index('gb18030-ranges'); + var i; + for (i = 0; i < idx.length; ++i) { + /** @type {!Array.} */ + var entry = idx[i]; + if (entry[1] <= code_point) { + offset = entry[1]; + pointer_offset = entry[0]; + } else { + break; + } + } + + // 3. Return a pointer whose value is pointer offset + code point + // − offset. + return pointer_offset + code_point - offset; + } + + /** + * @param {number} code_point The |code_point| to search for in the Shift_JIS + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the Shift_JIS index. + */ + function indexShiftJISPointerFor(code_point) { + // 1. Let index be index jis0208 excluding all entries whose + // pointer is in the range 8272 to 8835, inclusive. + shift_jis_index = shift_jis_index || + index('jis0208').map(function(code_point, pointer) { + return inRange(pointer, 8272, 8835) ? null : code_point; + }); + var index_ = shift_jis_index; + + // 2. Return the index pointer for code point in index. + return index_.indexOf(code_point); + } + var shift_jis_index; + + /** + * @param {number} code_point The |code_point| to search for in the big5 + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the big5 index. + */ + function indexBig5PointerFor(code_point) { + // 1. Let index be index Big5 excluding all entries whose pointer + big5_index_no_hkscs = big5_index_no_hkscs || + index('big5').map(function(code_point, pointer) { + return (pointer < (0xA1 - 0x81) * 157) ? null : code_point; + }); + var index_ = big5_index_no_hkscs; + + // 2. If code point is U+2550, U+255E, U+2561, U+256A, U+5341, or + // U+5345, return the last pointer corresponding to code point in + // index. + if (code_point === 0x2550 || code_point === 0x255E || + code_point === 0x2561 || code_point === 0x256A || + code_point === 0x5341 || code_point === 0x5345) { + return index_.lastIndexOf(code_point); + } + + // 3. Return the index pointer for code point in index. + return indexPointerFor(code_point, index_); + } + var big5_index_no_hkscs; + + // + // 8. API + // + + /** @const */ var DEFAULT_ENCODING = 'utf-8'; + + // 8.1 Interface TextDecoder + + /** + * @constructor + * @param {string=} label The label of the encoding; + * defaults to 'utf-8'. + * @param {Object=} options + */ + function TextDecoder(label, options) { + // Web IDL conventions + if (!(this instanceof TextDecoder)) + throw TypeError('Called as a function. Did you forget \'new\'?'); + label = label !== undefined ? String(label) : DEFAULT_ENCODING; + options = ToDictionary(options); + + // A TextDecoder object has an associated encoding, decoder, + // stream, ignore BOM flag (initially unset), BOM seen flag + // (initially unset), error mode (initially replacement), and do + // not flush flag (initially unset). + + /** @private */ + this._encoding = null; + /** @private @type {?Decoder} */ + this._decoder = null; + /** @private @type {boolean} */ + this._ignoreBOM = false; + /** @private @type {boolean} */ + this._BOMseen = false; + /** @private @type {string} */ + this._error_mode = 'replacement'; + /** @private @type {boolean} */ + this._do_not_flush = false; + + + // 1. Let encoding be the result of getting an encoding from + // label. + var encoding = getEncoding(label); + + // 2. If encoding is failure or replacement, throw a RangeError. + if (encoding === null || encoding.name === 'replacement') + throw RangeError('Unknown encoding: ' + label); + if (!decoders[encoding.name]) { + throw Error('Decoder not present.' + + ' Did you forget to include encoding-indexes.js first?'); + } + + // 3. Let dec be a new TextDecoder object. + var dec = this; + + // 4. Set dec's encoding to encoding. + dec._encoding = encoding; + + // 5. If options's fatal member is true, set dec's error mode to + // fatal. + if (Boolean(options['fatal'])) + dec._error_mode = 'fatal'; + + // 6. If options's ignoreBOM member is true, set dec's ignore BOM + // flag. + if (Boolean(options['ignoreBOM'])) + dec._ignoreBOM = true; + + // For pre-ES5 runtimes: + if (!Object.defineProperty) { + this.encoding = dec._encoding.name.toLowerCase(); + this.fatal = dec._error_mode === 'fatal'; + this.ignoreBOM = dec._ignoreBOM; + } + + // 7. Return dec. + return dec; + } + + if (Object.defineProperty) { + // The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextDecoder.prototype, 'encoding', { + /** @this {TextDecoder} */ + get: function() { return this._encoding.name.toLowerCase(); } + }); + + // The fatal attribute's getter must return true if error mode + // is fatal, and false otherwise. + Object.defineProperty(TextDecoder.prototype, 'fatal', { + /** @this {TextDecoder} */ + get: function() { return this._error_mode === 'fatal'; } + }); + + // The ignoreBOM attribute's getter must return true if ignore + // BOM flag is set, and false otherwise. + Object.defineProperty(TextDecoder.prototype, 'ignoreBOM', { + /** @this {TextDecoder} */ + get: function() { return this._ignoreBOM; } + }); + } + + /** + * @param {BufferSource=} input The buffer of bytes to decode. + * @param {Object=} options + * @return {string} The decoded string. + */ + TextDecoder.prototype.decode = function decode(input, options) { + var bytes; + if (typeof input === 'object' && input instanceof ArrayBuffer) { + bytes = new Uint8Array(input); + } else if (typeof input === 'object' && 'buffer' in input && + input.buffer instanceof ArrayBuffer) { + bytes = new Uint8Array(input.buffer, + input.byteOffset, + input.byteLength); + } else { + bytes = new Uint8Array(0); + } + + options = ToDictionary(options); + + // 1. If the do not flush flag is unset, set decoder to a new + // encoding's decoder, set stream to a new stream, and unset the + // BOM seen flag. + if (!this._do_not_flush) { + this._decoder = decoders[this._encoding.name]({ + fatal: this._error_mode === 'fatal'}); + this._BOMseen = false; + } + + // 2. If options's stream is true, set the do not flush flag, and + // unset the do not flush flag otherwise. + this._do_not_flush = Boolean(options['stream']); + + // 3. If input is given, push a copy of input to stream. + // TODO: Align with spec algorithm - maintain stream on instance. + var input_stream = new Stream(bytes); + + // 4. Let output be a new stream. + var output = []; + + /** @type {?(number|!Array.)} */ + var result; + + // 5. While true: + while (true) { + // 1. Let token be the result of reading from stream. + var token = input_stream.read(); + + // 2. If token is end-of-stream and the do not flush flag is + // set, return output, serialized. + // TODO: Align with spec algorithm. + if (token === end_of_stream) + break; + + // 3. Otherwise, run these subsubsteps: + + // 1. Let result be the result of processing token for decoder, + // stream, output, and error mode. + result = this._decoder.handler(input_stream, token); + + // 2. If result is finished, return output, serialized. + if (result === finished) + break; + + if (result !== null) { + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + + // 3. Otherwise, if result is error, throw a TypeError. + // (Thrown in handler) + + // 4. Otherwise, do nothing. + } + // TODO: Align with spec algorithm. + if (!this._do_not_flush) { + do { + result = this._decoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (result === null) + continue; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } while (!input_stream.endOfStream()); + this._decoder = null; + } + + // A TextDecoder object also has an associated serialize stream + // algorithm... + /** + * @param {!Array.} stream + * @return {string} + * @this {TextDecoder} + */ + function serializeStream(stream) { + // 1. Let token be the result of reading from stream. + // (Done in-place on array, rather than as a stream) + + // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore + // BOM flag and BOM seen flag are unset, run these subsubsteps: + if (includes(['UTF-8', 'UTF-16LE', 'UTF-16BE'], this._encoding.name) && + !this._ignoreBOM && !this._BOMseen) { + if (stream.length > 0 && stream[0] === 0xFEFF) { + // 1. If token is U+FEFF, set BOM seen flag. + this._BOMseen = true; + stream.shift(); + } else if (stream.length > 0) { + // 2. Otherwise, if token is not end-of-stream, set BOM seen + // flag and append token to stream. + this._BOMseen = true; + } else ; + } + // 4. Otherwise, return output. + return codePointsToString(stream); + } + + return serializeStream.call(this, output); + }; + + // 8.2 Interface TextEncoder + + /** + * @constructor + * @param {string=} label The label of the encoding. NONSTANDARD. + * @param {Object=} options NONSTANDARD. + */ + function TextEncoder(label, options) { + // Web IDL conventions + if (!(this instanceof TextEncoder)) + throw TypeError('Called as a function. Did you forget \'new\'?'); + options = ToDictionary(options); + + // A TextEncoder object has an associated encoding and encoder. + + /** @private */ + this._encoding = null; + /** @private @type {?Encoder} */ + this._encoder = null; + + // Non-standard + /** @private @type {boolean} */ + this._do_not_flush = false; + /** @private @type {string} */ + this._fatal = Boolean(options['fatal']) ? 'fatal' : 'replacement'; + + // 1. Let enc be a new TextEncoder object. + var enc = this; + + // 2. Set enc's encoding to UTF-8's encoder. + if (Boolean(options['NONSTANDARD_allowLegacyEncoding'])) { + // NONSTANDARD behavior. + label = label !== undefined ? String(label) : DEFAULT_ENCODING; + var encoding = getEncoding(label); + if (encoding === null || encoding.name === 'replacement') + throw RangeError('Unknown encoding: ' + label); + if (!encoders[encoding.name]) { + throw Error('Encoder not present.' + + ' Did you forget to include encoding-indexes.js first?'); + } + enc._encoding = encoding; + } else { + // Standard behavior. + enc._encoding = getEncoding('utf-8'); + + if (label !== undefined && 'console' in global) { + console.warn('TextEncoder constructor called with encoding label, ' + + 'which is ignored.'); + } + } + + // For pre-ES5 runtimes: + if (!Object.defineProperty) + this.encoding = enc._encoding.name.toLowerCase(); + + // 3. Return enc. + return enc; + } + + if (Object.defineProperty) { + // The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextEncoder.prototype, 'encoding', { + /** @this {TextEncoder} */ + get: function() { return this._encoding.name.toLowerCase(); } + }); + } + + /** + * @param {string=} opt_string The string to encode. + * @param {Object=} options + * @return {!Uint8Array} Encoded bytes, as a Uint8Array. + */ + TextEncoder.prototype.encode = function encode(opt_string, options) { + opt_string = opt_string === undefined ? '' : String(opt_string); + options = ToDictionary(options); + + // NOTE: This option is nonstandard. None of the encodings + // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when + // the input is a USVString so streaming is not necessary. + if (!this._do_not_flush) + this._encoder = encoders[this._encoding.name]({ + fatal: this._fatal === 'fatal'}); + this._do_not_flush = Boolean(options['stream']); + + // 1. Convert input to a stream. + var input = new Stream(stringToCodePoints(opt_string)); + + // 2. Let output be a new stream + var output = []; + + /** @type {?(number|!Array.)} */ + var result; + // 3. While true, run these substeps: + while (true) { + // 1. Let token be the result of reading from input. + var token = input.read(); + if (token === end_of_stream) + break; + // 2. Let result be the result of processing token for encoder, + // input, output. + result = this._encoder.handler(input, token); + if (result === finished) + break; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + // TODO: Align with spec algorithm. + if (!this._do_not_flush) { + while (true) { + result = this._encoder.handler(input, input.read()); + if (result === finished) + break; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + this._encoder = null; + } + // 3. If result is finished, convert output into a byte sequence, + // and then return a Uint8Array object wrapping an ArrayBuffer + // containing output. + return new Uint8Array(output); + }; + + + // + // 9. The encoding + // + + // 9.1 utf-8 + + // 9.1.1 utf-8 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function UTF8Decoder(options) { + var fatal = options.fatal; + + // utf-8's decoder's has an associated utf-8 code point, utf-8 + // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 + // lower boundary (initially 0x80), and a utf-8 upper boundary + // (initially 0xBF). + var /** @type {number} */ utf8_code_point = 0, + /** @type {number} */ utf8_bytes_seen = 0, + /** @type {number} */ utf8_bytes_needed = 0, + /** @type {number} */ utf8_lower_boundary = 0x80, + /** @type {number} */ utf8_upper_boundary = 0xBF; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, + // set utf-8 bytes needed to 0 and return error. + if (bite === end_of_stream && utf8_bytes_needed !== 0) { + utf8_bytes_needed = 0; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 3. If utf-8 bytes needed is 0, based on byte: + if (utf8_bytes_needed === 0) { + + // 0x00 to 0x7F + if (inRange(bite, 0x00, 0x7F)) { + // Return a code point whose value is byte. + return bite; + } + + // 0xC2 to 0xDF + else if (inRange(bite, 0xC2, 0xDF)) { + // 1. Set utf-8 bytes needed to 1. + utf8_bytes_needed = 1; + + // 2. Set UTF-8 code point to byte & 0x1F. + utf8_code_point = bite & 0x1F; + } + + // 0xE0 to 0xEF + else if (inRange(bite, 0xE0, 0xEF)) { + // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. + if (bite === 0xE0) + utf8_lower_boundary = 0xA0; + // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. + if (bite === 0xED) + utf8_upper_boundary = 0x9F; + // 3. Set utf-8 bytes needed to 2. + utf8_bytes_needed = 2; + // 4. Set UTF-8 code point to byte & 0xF. + utf8_code_point = bite & 0xF; + } + + // 0xF0 to 0xF4 + else if (inRange(bite, 0xF0, 0xF4)) { + // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. + if (bite === 0xF0) + utf8_lower_boundary = 0x90; + // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. + if (bite === 0xF4) + utf8_upper_boundary = 0x8F; + // 3. Set utf-8 bytes needed to 3. + utf8_bytes_needed = 3; + // 4. Set UTF-8 code point to byte & 0x7. + utf8_code_point = bite & 0x7; + } + + // Otherwise + else { + // Return error. + return decoderError(fatal); + } + + // Return continue. + return null; + } + + // 4. If byte is not in the range utf-8 lower boundary to utf-8 + // upper boundary, inclusive, run these substeps: + if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { + + // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 + // bytes seen to 0, set utf-8 lower boundary to 0x80, and set + // utf-8 upper boundary to 0xBF. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 2. Prepend byte to stream. + stream.prepend(bite); + + // 3. Return error. + return decoderError(fatal); + } + + // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary + // to 0xBF. + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 6. Set UTF-8 code point to (UTF-8 code point << 6) | (byte & + // 0x3F) + utf8_code_point = (utf8_code_point << 6) | (bite & 0x3F); + + // 7. Increase utf-8 bytes seen by one. + utf8_bytes_seen += 1; + + // 8. If utf-8 bytes seen is not equal to utf-8 bytes needed, + // continue. + if (utf8_bytes_seen !== utf8_bytes_needed) + return null; + + // 9. Let code point be utf-8 code point. + var code_point = utf8_code_point; + + // 10. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes + // seen to 0. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + + // 11. Return a code point whose value is code point. + return code_point; + }; + } + + // 9.1.2 utf-8 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function UTF8Encoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Set count and offset based on the range code point is in: + var count, offset; + // U+0080 to U+07FF, inclusive: + if (inRange(code_point, 0x0080, 0x07FF)) { + // 1 and 0xC0 + count = 1; + offset = 0xC0; + } + // U+0800 to U+FFFF, inclusive: + else if (inRange(code_point, 0x0800, 0xFFFF)) { + // 2 and 0xE0 + count = 2; + offset = 0xE0; + } + // U+10000 to U+10FFFF, inclusive: + else if (inRange(code_point, 0x10000, 0x10FFFF)) { + // 3 and 0xF0 + count = 3; + offset = 0xF0; + } + + // 4. Let bytes be a byte sequence whose first byte is (code + // point >> (6 × count)) + offset. + var bytes = [(code_point >> (6 * count)) + offset]; + + // 5. Run these substeps while count is greater than 0: + while (count > 0) { + + // 1. Set temp to code point >> (6 × (count − 1)). + var temp = code_point >> (6 * (count - 1)); + + // 2. Append to bytes 0x80 | (temp & 0x3F). + bytes.push(0x80 | (temp & 0x3F)); + + // 3. Decrease count by one. + count -= 1; + } + + // 6. Return bytes bytes, in order. + return bytes; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['UTF-8'] = function(options) { + return new UTF8Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['UTF-8'] = function(options) { + return new UTF8Decoder(options); + }; + + // + // 10. Legacy single-byte encodings + // + + // 10.1 single-byte decoder + /** + * @constructor + * @implements {Decoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */ + function SingleByteDecoder(index, options) { + var fatal = options.fatal; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 3. Let code point be the index code point for byte − 0x80 in + // index single-byte. + var code_point = index[bite - 0x80]; + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + }; + } + + // 10.2 single-byte encoder + /** + * @constructor + * @implements {Encoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */ + function SingleByteEncoder(index, options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index pointer for code point in index + // single-byte. + var pointer = indexPointerFor(code_point, index); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + encoderError(code_point); + + // 5. Return a byte whose value is pointer + 0x80. + return pointer + 0x80; + }; + } + + (function() { + if (!('encoding-indexes' in global)) + return; + encodings.forEach(function(category) { + if (category.heading !== 'Legacy single-byte encodings') + return; + category.encodings.forEach(function(encoding) { + var name = encoding.name; + var idx = index(name.toLowerCase()); + /** @param {{fatal: boolean}} options */ + decoders[name] = function(options) { + return new SingleByteDecoder(idx, options); + }; + /** @param {{fatal: boolean}} options */ + encoders[name] = function(options) { + return new SingleByteEncoder(idx, options); + }; + }); + }); + }()); + + // + // 11. Legacy multi-byte Chinese (simplified) encodings + // + + // 11.1 gbk + + // 11.1.1 gbk decoder + // gbk's decoder is gb18030's decoder. + /** @param {{fatal: boolean}} options */ + decoders['GBK'] = function(options) { + return new GB18030Decoder(options); + }; + + // 11.1.2 gbk encoder + // gbk's encoder is gb18030's encoder with its gbk flag set. + /** @param {{fatal: boolean}} options */ + encoders['GBK'] = function(options) { + return new GB18030Encoder(options, true); + }; + + // 11.2 gb18030 + + // 11.2.1 gb18030 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function GB18030Decoder(options) { + var fatal = options.fatal; + // gb18030's decoder has an associated gb18030 first, gb18030 + // second, and gb18030 third (all initially 0x00). + var /** @type {number} */ gb18030_first = 0x00, + /** @type {number} */ gb18030_second = 0x00, + /** @type {number} */ gb18030_third = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and gb18030 first, gb18030 + // second, and gb18030 third are 0x00, return finished. + if (bite === end_of_stream && gb18030_first === 0x00 && + gb18030_second === 0x00 && gb18030_third === 0x00) { + return finished; + } + // 2. If byte is end-of-stream, and gb18030 first, gb18030 + // second, or gb18030 third is not 0x00, set gb18030 first, + // gb18030 second, and gb18030 third to 0x00, and return error. + if (bite === end_of_stream && + (gb18030_first !== 0x00 || gb18030_second !== 0x00 || + gb18030_third !== 0x00)) { + gb18030_first = 0x00; + gb18030_second = 0x00; + gb18030_third = 0x00; + decoderError(fatal); + } + var code_point; + // 3. If gb18030 third is not 0x00, run these substeps: + if (gb18030_third !== 0x00) { + // 1. Let code point be null. + code_point = null; + // 2. If byte is in the range 0x30 to 0x39, inclusive, set + // code point to the index gb18030 ranges code point for + // (((gb18030 first − 0x81) × 10 + gb18030 second − 0x30) × + // 126 + gb18030 third − 0x81) × 10 + byte − 0x30. + if (inRange(bite, 0x30, 0x39)) { + code_point = indexGB18030RangesCodePointFor( + (((gb18030_first - 0x81) * 10 + gb18030_second - 0x30) * 126 + + gb18030_third - 0x81) * 10 + bite - 0x30); + } + + // 3. Let buffer be a byte sequence consisting of gb18030 + // second, gb18030 third, and byte, in order. + var buffer = [gb18030_second, gb18030_third, bite]; + + // 4. Set gb18030 first, gb18030 second, and gb18030 third to + // 0x00. + gb18030_first = 0x00; + gb18030_second = 0x00; + gb18030_third = 0x00; + + // 5. If code point is null, prepend buffer to stream and + // return error. + if (code_point === null) { + stream.prepend(buffer); + return decoderError(fatal); + } + + // 6. Return a code point whose value is code point. + return code_point; + } + + // 4. If gb18030 second is not 0x00, run these substeps: + if (gb18030_second !== 0x00) { + + // 1. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 third to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + gb18030_third = bite; + return null; + } + + // 2. Prepend gb18030 second followed by byte to stream, set + // gb18030 first and gb18030 second to 0x00, and return error. + stream.prepend([gb18030_second, bite]); + gb18030_first = 0x00; + gb18030_second = 0x00; + return decoderError(fatal); + } + + // 5. If gb18030 first is not 0x00, run these substeps: + if (gb18030_first !== 0x00) { + + // 1. If byte is in the range 0x30 to 0x39, inclusive, set + // gb18030 second to byte and return continue. + if (inRange(bite, 0x30, 0x39)) { + gb18030_second = bite; + return null; + } + + // 2. Let lead be gb18030 first, let pointer be null, and set + // gb18030 first to 0x00. + var lead = gb18030_first; + var pointer = null; + gb18030_first = 0x00; + + // 3. Let offset be 0x40 if byte is less than 0x7F and 0x41 + // otherwise. + var offset = bite < 0x7F ? 0x40 : 0x41; + + // 4. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 190 + + // (byte − offset). + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFE)) + pointer = (lead - 0x81) * 190 + (bite - offset); + + // 5. Let code point be null if pointer is null and the index + // code point for pointer in index gb18030 otherwise. + code_point = pointer === null ? null : + indexCodePointFor(pointer, index('gb18030')); + + // 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 7. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 8. Return a code point whose value is code point. + return code_point; + } + + // 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 7. If byte is 0x80, return code point U+20AC. + if (bite === 0x80) + return 0x20AC; + + // 8. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 first to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + gb18030_first = bite; + return null; + } + + // 9. Return error. + return decoderError(fatal); + }; + } + + // 11.2.2 gb18030 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + * @param {boolean=} gbk_flag + */ + function GB18030Encoder(options, gbk_flag) { + options.fatal; + // gb18030's decoder has an associated gbk flag (initially unset). + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is U+E5E5, return error with code point. + if (code_point === 0xE5E5) + return encoderError(code_point); + + // 4. If the gbk flag is set and code point is U+20AC, return + // byte 0x80. + if (gbk_flag && code_point === 0x20AC) + return 0x80; + + // 5. Let pointer be the index pointer for code point in index + // gb18030. + var pointer = indexPointerFor(code_point, index('gb18030')); + + // 6. If pointer is not null, run these substeps: + if (pointer !== null) { + + // 1. Let lead be floor(pointer / 190) + 0x81. + var lead = floor(pointer / 190) + 0x81; + + // 2. Let trail be pointer % 190. + var trail = pointer % 190; + + // 3. Let offset be 0x40 if trail is less than 0x3F and 0x41 otherwise. + var offset = trail < 0x3F ? 0x40 : 0x41; + + // 4. Return two bytes whose values are lead and trail + offset. + return [lead, trail + offset]; + } + + // 7. If gbk flag is set, return error with code point. + if (gbk_flag) + return encoderError(code_point); + + // 8. Set pointer to the index gb18030 ranges pointer for code + // point. + pointer = indexGB18030RangesPointerFor(code_point); + + // 9. Let byte1 be floor(pointer / 10 / 126 / 10). + var byte1 = floor(pointer / 10 / 126 / 10); + + // 10. Set pointer to pointer − byte1 × 10 × 126 × 10. + pointer = pointer - byte1 * 10 * 126 * 10; + + // 11. Let byte2 be floor(pointer / 10 / 126). + var byte2 = floor(pointer / 10 / 126); + + // 12. Set pointer to pointer − byte2 × 10 × 126. + pointer = pointer - byte2 * 10 * 126; + + // 13. Let byte3 be floor(pointer / 10). + var byte3 = floor(pointer / 10); + + // 14. Let byte4 be pointer − byte3 × 10. + var byte4 = pointer - byte3 * 10; + + // 15. Return four bytes whose values are byte1 + 0x81, byte2 + + // 0x30, byte3 + 0x81, byte4 + 0x30. + return [byte1 + 0x81, + byte2 + 0x30, + byte3 + 0x81, + byte4 + 0x30]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['gb18030'] = function(options) { + return new GB18030Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['gb18030'] = function(options) { + return new GB18030Decoder(options); + }; + + + // + // 12. Legacy multi-byte Chinese (traditional) encodings + // + + // 12.1 Big5 + + // 12.1.1 Big5 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function Big5Decoder(options) { + var fatal = options.fatal; + // Big5's decoder has an associated Big5 lead (initially 0x00). + var /** @type {number} */ Big5_lead = 0x00; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and Big5 lead is not 0x00, set + // Big5 lead to 0x00 and return error. + if (bite === end_of_stream && Big5_lead !== 0x00) { + Big5_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and Big5 lead is 0x00, return + // finished. + if (bite === end_of_stream && Big5_lead === 0x00) + return finished; + + // 3. If Big5 lead is not 0x00, let lead be Big5 lead, let + // pointer be null, set Big5 lead to 0x00, and then run these + // substeps: + if (Big5_lead !== 0x00) { + var lead = Big5_lead; + var pointer = null; + Big5_lead = 0x00; + + // 1. Let offset be 0x40 if byte is less than 0x7F and 0x62 + // otherwise. + var offset = bite < 0x7F ? 0x40 : 0x62; + + // 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 + + // (byte − offset). + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0xA1, 0xFE)) + pointer = (lead - 0x81) * 157 + (bite - offset); + + // 3. If there is a row in the table below whose first column + // is pointer, return the two code points listed in its second + // column + // Pointer | Code points + // --------+-------------- + // 1133 | U+00CA U+0304 + // 1135 | U+00CA U+030C + // 1164 | U+00EA U+0304 + // 1166 | U+00EA U+030C + switch (pointer) { + case 1133: return [0x00CA, 0x0304]; + case 1135: return [0x00CA, 0x030C]; + case 1164: return [0x00EA, 0x0304]; + case 1166: return [0x00EA, 0x030C]; + } + + // 4. Let code point be null if pointer is null and the index + // code point for pointer in index Big5 otherwise. + var code_point = (pointer === null) ? null : + indexCodePointFor(pointer, index('big5')); + + // 5. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 6. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 7. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5 + // lead to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + Big5_lead = bite; + return null; + } + + // 6. Return error. + return decoderError(fatal); + }; + } + + // 12.1.2 Big5 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function Big5Encoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index Big5 pointer for code point. + var pointer = indexBig5PointerFor(code_point); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 5. Let lead be floor(pointer / 157) + 0x81. + var lead = floor(pointer / 157) + 0x81; + + // 6. If lead is less than 0xA1, return error with code point. + if (lead < 0xA1) + return encoderError(code_point); + + // 7. Let trail be pointer % 157. + var trail = pointer % 157; + + // 8. Let offset be 0x40 if trail is less than 0x3F and 0x62 + // otherwise. + var offset = trail < 0x3F ? 0x40 : 0x62; + + // Return two bytes whose values are lead and trail + offset. + return [lead, trail + offset]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['Big5'] = function(options) { + return new Big5Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['Big5'] = function(options) { + return new Big5Decoder(options); + }; + + + // + // 13. Legacy multi-byte Japanese encodings + // + + // 13.1 euc-jp + + // 13.1.1 euc-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function EUCJPDecoder(options) { + var fatal = options.fatal; + + // euc-jp's decoder has an associated euc-jp jis0212 flag + // (initially unset) and euc-jp lead (initially 0x00). + var /** @type {boolean} */ eucjp_jis0212_flag = false, + /** @type {number} */ eucjp_lead = 0x00; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and euc-jp lead is not 0x00, set + // euc-jp lead to 0x00, and return error. + if (bite === end_of_stream && eucjp_lead !== 0x00) { + eucjp_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and euc-jp lead is 0x00, return + // finished. + if (bite === end_of_stream && eucjp_lead === 0x00) + return finished; + + // 3. If euc-jp lead is 0x8E and byte is in the range 0xA1 to + // 0xDF, inclusive, set euc-jp lead to 0x00 and return a code + // point whose value is 0xFF61 − 0xA1 + byte. + if (eucjp_lead === 0x8E && inRange(bite, 0xA1, 0xDF)) { + eucjp_lead = 0x00; + return 0xFF61 - 0xA1 + bite; + } + + // 4. If euc-jp lead is 0x8F and byte is in the range 0xA1 to + // 0xFE, inclusive, set the euc-jp jis0212 flag, set euc-jp lead + // to byte, and return continue. + if (eucjp_lead === 0x8F && inRange(bite, 0xA1, 0xFE)) { + eucjp_jis0212_flag = true; + eucjp_lead = bite; + return null; + } + + // 5. If euc-jp lead is not 0x00, let lead be euc-jp lead, set + // euc-jp lead to 0x00, and run these substeps: + if (eucjp_lead !== 0x00) { + var lead = eucjp_lead; + eucjp_lead = 0x00; + + // 1. Let code point be null. + var code_point = null; + + // 2. If lead and byte are both in the range 0xA1 to 0xFE, + // inclusive, set code point to the index code point for (lead + // − 0xA1) × 94 + byte − 0xA1 in index jis0208 if the euc-jp + // jis0212 flag is unset and in index jis0212 otherwise. + if (inRange(lead, 0xA1, 0xFE) && inRange(bite, 0xA1, 0xFE)) { + code_point = indexCodePointFor( + (lead - 0xA1) * 94 + (bite - 0xA1), + index(!eucjp_jis0212_flag ? 'jis0208' : 'jis0212')); + } + + // 3. Unset the euc-jp jis0212 flag. + eucjp_jis0212_flag = false; + + // 4. If byte is not in the range 0xA1 to 0xFE, inclusive, + // prepend byte to stream. + if (!inRange(bite, 0xA1, 0xFE)) + stream.prepend(bite); + + // 5. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 6. Return a code point whose value is code point. + return code_point; + } + + // 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 7. If byte is 0x8E, 0x8F, or in the range 0xA1 to 0xFE, + // inclusive, set euc-jp lead to byte and return continue. + if (bite === 0x8E || bite === 0x8F || inRange(bite, 0xA1, 0xFE)) { + eucjp_lead = bite; + return null; + } + + // 8. Return error. + return decoderError(fatal); + }; + } + + // 13.1.2 euc-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function EUCJPEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 4. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + + // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return two bytes whose values are 0x8E and code point − + // 0xFF61 + 0xA1. + if (inRange(code_point, 0xFF61, 0xFF9F)) + return [0x8E, code_point - 0xFF61 + 0xA1]; + + // 6. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 7. Let pointer be the index pointer for code point in index + // jis0208. + var pointer = indexPointerFor(code_point, index('jis0208')); + + // 8. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 9. Let lead be floor(pointer / 94) + 0xA1. + var lead = floor(pointer / 94) + 0xA1; + + // 10. Let trail be pointer % 94 + 0xA1. + var trail = pointer % 94 + 0xA1; + + // 11. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['EUC-JP'] = function(options) { + return new EUCJPEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['EUC-JP'] = function(options) { + return new EUCJPDecoder(options); + }; + + // 13.2 iso-2022-jp + + // 13.2.1 iso-2022-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function ISO2022JPDecoder(options) { + var fatal = options.fatal; + /** @enum */ + var states = { + ASCII: 0, + Roman: 1, + Katakana: 2, + LeadByte: 3, + TrailByte: 4, + EscapeStart: 5, + Escape: 6 + }; + // iso-2022-jp's decoder has an associated iso-2022-jp decoder + // state (initially ASCII), iso-2022-jp decoder output state + // (initially ASCII), iso-2022-jp lead (initially 0x00), and + // iso-2022-jp output flag (initially unset). + var /** @type {number} */ iso2022jp_decoder_state = states.ASCII, + /** @type {number} */ iso2022jp_decoder_output_state = states.ASCII, + /** @type {number} */ iso2022jp_lead = 0x00, + /** @type {boolean} */ iso2022jp_output_flag = false; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // switching on iso-2022-jp decoder state: + switch (iso2022jp_decoder_state) { + default: + case states.ASCII: + // ASCII + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x00 to 0x7F, excluding 0x0E, 0x0F, and 0x1B + if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E + && bite !== 0x0F && bite !== 0x1B) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag = false; + return bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.Roman: + // Roman + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x5C + if (bite === 0x5C) { + // Unset the iso-2022-jp output flag and return code point + // U+00A5. + iso2022jp_output_flag = false; + return 0x00A5; + } + + // 0x7E + if (bite === 0x7E) { + // Unset the iso-2022-jp output flag and return code point + // U+203E. + iso2022jp_output_flag = false; + return 0x203E; + } + + // 0x00 to 0x7F, excluding 0x0E, 0x0F, 0x1B, 0x5C, and 0x7E + if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E && bite !== 0x0F + && bite !== 0x1B && bite !== 0x5C && bite !== 0x7E) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag = false; + return bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.Katakana: + // Katakana + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x21 to 0x5F + if (inRange(bite, 0x21, 0x5F)) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is 0xFF61 − 0x21 + byte. + iso2022jp_output_flag = false; + return 0xFF61 - 0x21 + bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.LeadByte: + // Lead byte + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x21 to 0x7E + if (inRange(bite, 0x21, 0x7E)) { + // Unset the iso-2022-jp output flag, set iso-2022-jp lead + // to byte, iso-2022-jp decoder state to trail byte, and + // return continue. + iso2022jp_output_flag = false; + iso2022jp_lead = bite; + iso2022jp_decoder_state = states.TrailByte; + return null; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.TrailByte: + // Trail byte + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return decoderError(fatal); + } + + // 0x21 to 0x7E + if (inRange(bite, 0x21, 0x7E)) { + // 1. Set the iso-2022-jp decoder state to lead byte. + iso2022jp_decoder_state = states.LeadByte; + + // 2. Let pointer be (iso-2022-jp lead − 0x21) × 94 + byte − 0x21. + var pointer = (iso2022jp_lead - 0x21) * 94 + bite - 0x21; + + // 3. Let code point be the index code point for pointer in + // index jis0208. + var code_point = indexCodePointFor(pointer, index('jis0208')); + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + } + + // end-of-stream + if (bite === end_of_stream) { + // Set the iso-2022-jp decoder state to lead byte, prepend + // byte to stream, and return error. + iso2022jp_decoder_state = states.LeadByte; + stream.prepend(bite); + return decoderError(fatal); + } + + // Otherwise + // Set iso-2022-jp decoder state to lead byte and return + // error. + iso2022jp_decoder_state = states.LeadByte; + return decoderError(fatal); + + case states.EscapeStart: + // Escape start + + // 1. If byte is either 0x24 or 0x28, set iso-2022-jp lead to + // byte, iso-2022-jp decoder state to escape, and return + // continue. + if (bite === 0x24 || bite === 0x28) { + iso2022jp_lead = bite; + iso2022jp_decoder_state = states.Escape; + return null; + } + + // 2. Prepend byte to stream. + stream.prepend(bite); + + // 3. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state, and + // return error. + iso2022jp_output_flag = false; + iso2022jp_decoder_state = iso2022jp_decoder_output_state; + return decoderError(fatal); + + case states.Escape: + // Escape + + // 1. Let lead be iso-2022-jp lead and set iso-2022-jp lead to + // 0x00. + var lead = iso2022jp_lead; + iso2022jp_lead = 0x00; + + // 2. Let state be null. + var state = null; + + // 3. If lead is 0x28 and byte is 0x42, set state to ASCII. + if (lead === 0x28 && bite === 0x42) + state = states.ASCII; + + // 4. If lead is 0x28 and byte is 0x4A, set state to Roman. + if (lead === 0x28 && bite === 0x4A) + state = states.Roman; + + // 5. If lead is 0x28 and byte is 0x49, set state to Katakana. + if (lead === 0x28 && bite === 0x49) + state = states.Katakana; + + // 6. If lead is 0x24 and byte is either 0x40 or 0x42, set + // state to lead byte. + if (lead === 0x24 && (bite === 0x40 || bite === 0x42)) + state = states.LeadByte; + + // 7. If state is non-null, run these substeps: + if (state !== null) { + // 1. Set iso-2022-jp decoder state and iso-2022-jp decoder + // output state to states. + iso2022jp_decoder_state = iso2022jp_decoder_state = state; + + // 2. Let output flag be the iso-2022-jp output flag. + var output_flag = iso2022jp_output_flag; + + // 3. Set the iso-2022-jp output flag. + iso2022jp_output_flag = true; + + // 4. Return continue, if output flag is unset, and error + // otherwise. + return !output_flag ? null : decoderError(fatal); + } + + // 8. Prepend lead and byte to stream. + stream.prepend([lead, bite]); + + // 9. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state and + // return error. + iso2022jp_output_flag = false; + iso2022jp_decoder_state = iso2022jp_decoder_output_state; + return decoderError(fatal); + } + }; + } + + // 13.2.2 iso-2022-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function ISO2022JPEncoder(options) { + options.fatal; + // iso-2022-jp's encoder has an associated iso-2022-jp encoder + // state which is one of ASCII, Roman, and jis0208 (initially + // ASCII). + /** @enum */ + var states = { + ASCII: 0, + Roman: 1, + jis0208: 2 + }; + var /** @type {number} */ iso2022jp_state = states.ASCII; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream and iso-2022-jp encoder + // state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if (code_point === end_of_stream && + iso2022jp_state !== states.ASCII) { + stream.prepend(code_point); + iso2022jp_state = states.ASCII; + return [0x1B, 0x28, 0x42]; + } + + // 2. If code point is end-of-stream and iso-2022-jp encoder + // state is ASCII, return finished. + if (code_point === end_of_stream && iso2022jp_state === states.ASCII) + return finished; + + // 3. If ISO-2022-JP encoder state is ASCII or Roman, and code + // point is U+000E, U+000F, or U+001B, return error with U+FFFD. + if ((iso2022jp_state === states.ASCII || + iso2022jp_state === states.Roman) && + (code_point === 0x000E || code_point === 0x000F || + code_point === 0x001B)) { + return encoderError(0xFFFD); + } + + // 4. If iso-2022-jp encoder state is ASCII and code point is an + // ASCII code point, return a byte whose value is code point. + if (iso2022jp_state === states.ASCII && + isASCIICodePoint(code_point)) + return code_point; + + // 5. If iso-2022-jp encoder state is Roman and code point is an + // ASCII code point, excluding U+005C and U+007E, or is U+00A5 + // or U+203E, run these substeps: + if (iso2022jp_state === states.Roman && + ((isASCIICodePoint(code_point) && + code_point !== 0x005C && code_point !== 0x007E) || + (code_point == 0x00A5 || code_point == 0x203E))) { + + // 1. If code point is an ASCII code point, return a byte + // whose value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 2. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 3. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + } + + // 6. If code point is an ASCII code point, and iso-2022-jp + // encoder state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if (isASCIICodePoint(code_point) && + iso2022jp_state !== states.ASCII) { + stream.prepend(code_point); + iso2022jp_state = states.ASCII; + return [0x1B, 0x28, 0x42]; + } + + // 7. If code point is either U+00A5 or U+203E, and iso-2022-jp + // encoder state is not Roman, prepend code point to stream, set + // iso-2022-jp encoder state to Roman, and return three bytes + // 0x1B 0x28 0x4A. + if ((code_point === 0x00A5 || code_point === 0x203E) && + iso2022jp_state !== states.Roman) { + stream.prepend(code_point); + iso2022jp_state = states.Roman; + return [0x1B, 0x28, 0x4A]; + } + + // 8. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 9. Let pointer be the index pointer for code point in index + // jis0208. + var pointer = indexPointerFor(code_point, index('jis0208')); + + // 10. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 11. If iso-2022-jp encoder state is not jis0208, prepend code + // point to stream, set iso-2022-jp encoder state to jis0208, + // and return three bytes 0x1B 0x24 0x42. + if (iso2022jp_state !== states.jis0208) { + stream.prepend(code_point); + iso2022jp_state = states.jis0208; + return [0x1B, 0x24, 0x42]; + } + + // 12. Let lead be floor(pointer / 94) + 0x21. + var lead = floor(pointer / 94) + 0x21; + + // 13. Let trail be pointer % 94 + 0x21. + var trail = pointer % 94 + 0x21; + + // 14. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['ISO-2022-JP'] = function(options) { + return new ISO2022JPEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['ISO-2022-JP'] = function(options) { + return new ISO2022JPDecoder(options); + }; + + // 13.3 Shift_JIS + + // 13.3.1 Shift_JIS decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function ShiftJISDecoder(options) { + var fatal = options.fatal; + // Shift_JIS's decoder has an associated Shift_JIS lead (initially + // 0x00). + var /** @type {number} */ Shift_JIS_lead = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and Shift_JIS lead is not 0x00, + // set Shift_JIS lead to 0x00 and return error. + if (bite === end_of_stream && Shift_JIS_lead !== 0x00) { + Shift_JIS_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and Shift_JIS lead is 0x00, + // return finished. + if (bite === end_of_stream && Shift_JIS_lead === 0x00) + return finished; + + // 3. If Shift_JIS lead is not 0x00, let lead be Shift_JIS lead, + // let pointer be null, set Shift_JIS lead to 0x00, and then run + // these substeps: + if (Shift_JIS_lead !== 0x00) { + var lead = Shift_JIS_lead; + var pointer = null; + Shift_JIS_lead = 0x00; + + // 1. Let offset be 0x40, if byte is less than 0x7F, and 0x41 + // otherwise. + var offset = (bite < 0x7F) ? 0x40 : 0x41; + + // 2. Let lead offset be 0x81, if lead is less than 0xA0, and + // 0xC1 otherwise. + var lead_offset = (lead < 0xA0) ? 0x81 : 0xC1; + + // 3. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFC, inclusive, set pointer to (lead − lead offset) × + // 188 + byte − offset. + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFC)) + pointer = (lead - lead_offset) * 188 + bite - offset; + + // 4. If pointer is in the range 8836 to 10715, inclusive, + // return a code point whose value is 0xE000 − 8836 + pointer. + if (inRange(pointer, 8836, 10715)) + return 0xE000 - 8836 + pointer; + + // 5. Let code point be null, if pointer is null, and the + // index code point for pointer in index jis0208 otherwise. + var code_point = (pointer === null) ? null : + indexCodePointFor(pointer, index('jis0208')); + + // 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 7. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 8. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte or 0x80, return a code point + // whose value is byte. + if (isASCIIByte(bite) || bite === 0x80) + return bite; + + // 5. If byte is in the range 0xA1 to 0xDF, inclusive, return a + // code point whose value is 0xFF61 − 0xA1 + byte. + if (inRange(bite, 0xA1, 0xDF)) + return 0xFF61 - 0xA1 + bite; + + // 6. If byte is in the range 0x81 to 0x9F, inclusive, or 0xE0 + // to 0xFC, inclusive, set Shift_JIS lead to byte and return + // continue. + if (inRange(bite, 0x81, 0x9F) || inRange(bite, 0xE0, 0xFC)) { + Shift_JIS_lead = bite; + return null; + } + + // 7. Return error. + return decoderError(fatal); + }; + } + + // 13.3.2 Shift_JIS encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function ShiftJISEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point or U+0080, return a + // byte whose value is code point. + if (isASCIICodePoint(code_point) || code_point === 0x0080) + return code_point; + + // 3. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 4. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + + // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return a byte whose value is code point − 0xFF61 + 0xA1. + if (inRange(code_point, 0xFF61, 0xFF9F)) + return code_point - 0xFF61 + 0xA1; + + // 6. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 7. Let pointer be the index Shift_JIS pointer for code point. + var pointer = indexShiftJISPointerFor(code_point); + + // 8. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 9. Let lead be floor(pointer / 188). + var lead = floor(pointer / 188); + + // 10. Let lead offset be 0x81, if lead is less than 0x1F, and + // 0xC1 otherwise. + var lead_offset = (lead < 0x1F) ? 0x81 : 0xC1; + + // 11. Let trail be pointer % 188. + var trail = pointer % 188; + + // 12. Let offset be 0x40, if trail is less than 0x3F, and 0x41 + // otherwise. + var offset = (trail < 0x3F) ? 0x40 : 0x41; + + // 13. Return two bytes whose values are lead + lead offset and + // trail + offset. + return [lead + lead_offset, trail + offset]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['Shift_JIS'] = function(options) { + return new ShiftJISEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['Shift_JIS'] = function(options) { + return new ShiftJISDecoder(options); + }; + + // + // 14. Legacy multi-byte Korean encodings + // + + // 14.1 euc-kr + + // 14.1.1 euc-kr decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function EUCKRDecoder(options) { + var fatal = options.fatal; + + // euc-kr's decoder has an associated euc-kr lead (initially 0x00). + var /** @type {number} */ euckr_lead = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and euc-kr lead is not 0x00, set + // euc-kr lead to 0x00 and return error. + if (bite === end_of_stream && euckr_lead !== 0) { + euckr_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and euc-kr lead is 0x00, return + // finished. + if (bite === end_of_stream && euckr_lead === 0) + return finished; + + // 3. If euc-kr lead is not 0x00, let lead be euc-kr lead, let + // pointer be null, set euc-kr lead to 0x00, and then run these + // substeps: + if (euckr_lead !== 0x00) { + var lead = euckr_lead; + var pointer = null; + euckr_lead = 0x00; + + // 1. If byte is in the range 0x41 to 0xFE, inclusive, set + // pointer to (lead − 0x81) × 190 + (byte − 0x41). + if (inRange(bite, 0x41, 0xFE)) + pointer = (lead - 0x81) * 190 + (bite - 0x41); + + // 2. Let code point be null, if pointer is null, and the + // index code point for pointer in index euc-kr otherwise. + var code_point = (pointer === null) + ? null : indexCodePointFor(pointer, index('euc-kr')); + + // 3. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (pointer === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 5. If byte is in the range 0x81 to 0xFE, inclusive, set + // euc-kr lead to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + euckr_lead = bite; + return null; + } + + // 6. Return error. + return decoderError(fatal); + }; + } + + // 14.1.2 euc-kr encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function EUCKREncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index pointer for code point in index + // euc-kr. + var pointer = indexPointerFor(code_point, index('euc-kr')); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 5. Let lead be floor(pointer / 190) + 0x81. + var lead = floor(pointer / 190) + 0x81; + + // 6. Let trail be pointer % 190 + 0x41. + var trail = (pointer % 190) + 0x41; + + // 7. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['EUC-KR'] = function(options) { + return new EUCKREncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['EUC-KR'] = function(options) { + return new EUCKRDecoder(options); + }; + + + // + // 15. Legacy miscellaneous encodings + // + + // 15.1 replacement + + // Not needed - API throws RangeError + + // 15.2 Common infrastructure for utf-16be and utf-16le + + /** + * @param {number} code_unit + * @param {boolean} utf16be + * @return {!Array.} bytes + */ + function convertCodeUnitToBytes(code_unit, utf16be) { + // 1. Let byte1 be code unit >> 8. + var byte1 = code_unit >> 8; + + // 2. Let byte2 be code unit & 0x00FF. + var byte2 = code_unit & 0x00FF; + + // 3. Then return the bytes in order: + // utf-16be flag is set: byte1, then byte2. + if (utf16be) + return [byte1, byte2]; + // utf-16be flag is unset: byte2, then byte1. + return [byte2, byte1]; + } + + // 15.2.1 shared utf-16 decoder + /** + * @constructor + * @implements {Decoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */ + function UTF16Decoder(utf16_be, options) { + var fatal = options.fatal; + var /** @type {?number} */ utf16_lead_byte = null, + /** @type {?number} */ utf16_lead_surrogate = null; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and either utf-16 lead byte or + // utf-16 lead surrogate is not null, set utf-16 lead byte and + // utf-16 lead surrogate to null, and return error. + if (bite === end_of_stream && (utf16_lead_byte !== null || + utf16_lead_surrogate !== null)) { + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and utf-16 lead byte and utf-16 + // lead surrogate are null, return finished. + if (bite === end_of_stream && utf16_lead_byte === null && + utf16_lead_surrogate === null) { + return finished; + } + + // 3. If utf-16 lead byte is null, set utf-16 lead byte to byte + // and return continue. + if (utf16_lead_byte === null) { + utf16_lead_byte = bite; + return null; + } + + // 4. Let code unit be the result of: + var code_unit; + if (utf16_be) { + // utf-16be decoder flag is set + // (utf-16 lead byte << 8) + byte. + code_unit = (utf16_lead_byte << 8) + bite; + } else { + // utf-16be decoder flag is unset + // (byte << 8) + utf-16 lead byte. + code_unit = (bite << 8) + utf16_lead_byte; + } + // Then set utf-16 lead byte to null. + utf16_lead_byte = null; + + // 5. If utf-16 lead surrogate is not null, let lead surrogate + // be utf-16 lead surrogate, set utf-16 lead surrogate to null, + // and then run these substeps: + if (utf16_lead_surrogate !== null) { + var lead_surrogate = utf16_lead_surrogate; + utf16_lead_surrogate = null; + + // 1. If code unit is in the range U+DC00 to U+DFFF, + // inclusive, return a code point whose value is 0x10000 + + // ((lead surrogate − 0xD800) << 10) + (code unit − 0xDC00). + if (inRange(code_unit, 0xDC00, 0xDFFF)) { + return 0x10000 + (lead_surrogate - 0xD800) * 0x400 + + (code_unit - 0xDC00); + } + + // 2. Prepend the sequence resulting of converting code unit + // to bytes using utf-16be decoder flag to stream and return + // error. + stream.prepend(convertCodeUnitToBytes(code_unit, utf16_be)); + return decoderError(fatal); + } + + // 6. If code unit is in the range U+D800 to U+DBFF, inclusive, + // set utf-16 lead surrogate to code unit and return continue. + if (inRange(code_unit, 0xD800, 0xDBFF)) { + utf16_lead_surrogate = code_unit; + return null; + } + + // 7. If code unit is in the range U+DC00 to U+DFFF, inclusive, + // return error. + if (inRange(code_unit, 0xDC00, 0xDFFF)) + return decoderError(fatal); + + // 8. Return code point code unit. + return code_unit; + }; + } + + // 15.2.2 shared utf-16 encoder + /** + * @constructor + * @implements {Encoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */ + function UTF16Encoder(utf16_be, options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is in the range U+0000 to U+FFFF, inclusive, + // return the sequence resulting of converting code point to + // bytes using utf-16be encoder flag. + if (inRange(code_point, 0x0000, 0xFFFF)) + return convertCodeUnitToBytes(code_point, utf16_be); + + // 3. Let lead be ((code point − 0x10000) >> 10) + 0xD800, + // converted to bytes using utf-16be encoder flag. + var lead = convertCodeUnitToBytes( + ((code_point - 0x10000) >> 10) + 0xD800, utf16_be); + + // 4. Let trail be ((code point − 0x10000) & 0x3FF) + 0xDC00, + // converted to bytes using utf-16be encoder flag. + var trail = convertCodeUnitToBytes( + ((code_point - 0x10000) & 0x3FF) + 0xDC00, utf16_be); + + // 5. Return a byte sequence of lead followed by trail. + return lead.concat(trail); + }; + } + + // 15.3 utf-16be + // 15.3.1 utf-16be decoder + /** @param {{fatal: boolean}} options */ + encoders['UTF-16BE'] = function(options) { + return new UTF16Encoder(true, options); + }; + // 15.3.2 utf-16be encoder + /** @param {{fatal: boolean}} options */ + decoders['UTF-16BE'] = function(options) { + return new UTF16Decoder(true, options); + }; + + // 15.4 utf-16le + // 15.4.1 utf-16le decoder + /** @param {{fatal: boolean}} options */ + encoders['UTF-16LE'] = function(options) { + return new UTF16Encoder(false, options); + }; + // 15.4.2 utf-16le encoder + /** @param {{fatal: boolean}} options */ + decoders['UTF-16LE'] = function(options) { + return new UTF16Decoder(false, options); + }; + + // 15.5 x-user-defined + + // 15.5.1 x-user-defined decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function XUserDefinedDecoder(options) { + options.fatal; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 3. Return a code point whose value is 0xF780 + byte − 0x80. + return 0xF780 + bite - 0x80; + }; + } + + // 15.5.2 x-user-defined encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function XUserDefinedEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1.If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is in the range U+F780 to U+F7FF, inclusive, + // return a byte whose value is code point − 0xF780 + 0x80. + if (inRange(code_point, 0xF780, 0xF7FF)) + return code_point - 0xF780 + 0x80; + + // 4. Return error with code point. + return encoderError(code_point); + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['x-user-defined'] = function(options) { + return new XUserDefinedEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['x-user-defined'] = function(options) { + return new XUserDefinedDecoder(options); + }; + + if (!global['TextEncoder']) + global['TextEncoder'] = TextEncoder; + if (!global['TextDecoder']) + global['TextDecoder'] = TextDecoder; + + if (typeof module !== "undefined" && module.exports) { + module.exports = { + TextEncoder: global['TextEncoder'], + TextDecoder: global['TextDecoder'], + EncodingIndexes: global["encoding-indexes"] + }; + } + + // For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + }(this || {})); + },{"./encoding-indexes.js":108}],110:[function(require,module,exports){ + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; + } + + },{}],111:[function(require,module,exports){ + module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; + }; + },{}],112:[function(require,module,exports){ + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var formatRegExp = /%[sdj%]/g; + exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; + }; + + + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. + exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(commonjsGlobal$1.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; + }; + + + var debugs = {}; + var debugEnviron; + exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; + }; + + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ + /* legacy: obj, showHidden, depth, colors*/ + function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); + } + exports.inspect = inspect; + + + // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] + }; + + // Don't use 'blue' not visible on cmd.exe + inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' + }; + + + function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } + } + + + function stylizeNoColor(str, styleType) { + return str; + } + + + function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; + } + + + function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); + } + + + function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; + } + + + function reduceToSingleString(output, base, braces) { + var length = output.reduce(function(prev, cur) { + if (cur.indexOf('\n') >= 0) ; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { + return Array.isArray(ar); + } + exports.isArray = isArray; + + function isBoolean(arg) { + return typeof arg === 'boolean'; + } + exports.isBoolean = isBoolean; + + function isNull(arg) { + return arg === null; + } + exports.isNull = isNull; + + function isNullOrUndefined(arg) { + return arg == null; + } + exports.isNullOrUndefined = isNullOrUndefined; + + function isNumber(arg) { + return typeof arg === 'number'; + } + exports.isNumber = isNumber; + + function isString(arg) { + return typeof arg === 'string'; + } + exports.isString = isString; + + function isSymbol(arg) { + return typeof arg === 'symbol'; + } + exports.isSymbol = isSymbol; + + function isUndefined(arg) { + return arg === void 0; + } + exports.isUndefined = isUndefined; + + function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; + } + exports.isRegExp = isRegExp; + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + exports.isObject = isObject; + + function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; + } + exports.isDate = isDate; + + function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); + } + exports.isError = isError; + + function isFunction(arg) { + return typeof arg === 'function'; + } + exports.isFunction = isFunction; + + function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; + } + exports.isPrimitive = isPrimitive; + + exports.isBuffer = require('./support/isBuffer'); + + function objectToString(o) { + return Object.prototype.toString.call(o); + } + + + function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); + } + + + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + + // 26 Feb 16:19:34 + function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); + } + + + // log is just a thin wrapper to console.log that prepends a timestamp + exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); + }; + + + /** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ + exports.inherits = require('inherits'); + + exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; + }; + + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + },{"./support/isBuffer":111,"inherits":110}],113:[function(require,module,exports){ + /*! + + diff v5.1.0 + + Software License Agreement (BSD License) + + Copyright (c) 2009-2015, Kevin Decker + + All rights reserved. + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + @license + */ + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + (global = global || self, factory(global.Diff = {})); + }(this, (function (exports) { + function Diff() {} + Diff.prototype = { + diff: function diff(oldString, newString) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var callback = options.callback; + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + this.options = options; + var self = this; + + function done(value) { + if (callback) { + setTimeout(function () { + callback(undefined, value); + }, 0); + return true; + } else { + return value; + } + } // Allow subclasses to massage the input prior to running + + + oldString = this.castInput(oldString); + newString = this.castInput(newString); + oldString = this.removeEmpty(this.tokenize(oldString)); + newString = this.removeEmpty(this.tokenize(newString)); + var newLen = newString.length, + oldLen = oldString.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + + if (options.maxEditLength) { + maxEditLength = Math.min(maxEditLength, options.maxEditLength); + } + + var bestPath = [{ + newPos: -1, + components: [] + }]; // Seed editLength = 0, i.e. the content starts with the same values + + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + // Identity per the equality and tokenizer + return done([{ + value: this.join(newString), + count: newString.length + }]); + } // Main worker method. checks all permutations of a given edit length for acceptance. + + + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath = void 0; + + var addPath = bestPath[diagonalPath - 1], + removePath = bestPath[diagonalPath + 1], + _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } + + var canAdd = addPath && addPath.newPos + 1 < newLen, + canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen; + + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + + + if (!canAdd || canRemove && addPath.newPos < removePath.newPos) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); + } else { + basePath = addPath; // No need to clone, we've pulled it from the list + + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); + } + + _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done + + if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) { + return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken)); + } else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; + } + } + + editLength++; + } // Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced, or until the edit length exceeds options.maxEditLength (if given), + // in which case it will return undefined. + + + if (callback) { + (function exec() { + setTimeout(function () { + if (editLength > maxEditLength) { + return callback(); + } + + if (!execEditLength()) { + exec(); + } + }, 0); + })(); + } else { + while (editLength <= maxEditLength) { + var ret = execEditLength(); + + if (ret) { + return ret; + } + } + } + }, + pushComponent: function pushComponent(components, added, removed) { + var last = components[components.length - 1]; + + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = { + count: last.count + 1, + added: added, + removed: removed + }; + } else { + components.push({ + count: 1, + added: added, + removed: removed + }); + } + }, + extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath, + commonCount = 0; + + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + + if (commonCount) { + basePath.components.push({ + count: commonCount + }); + } + + basePath.newPos = newPos; + return oldPos; + }, + equals: function equals(left, right) { + if (this.options.comparator) { + return this.options.comparator(left, right); + } else { + return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase(); + } + }, + removeEmpty: function removeEmpty(array) { + var ret = []; + + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + + return ret; + }, + castInput: function castInput(value) { + return value; + }, + tokenize: function tokenize(value) { + return value.split(''); + }, + join: function join(chars) { + return chars.join(''); + } + }; + + function buildValues(diff, components, newString, oldString, useLongestToken) { + var componentPos = 0, + componentLen = components.length, + newPos = 0, + oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + + if (!component.removed) { + if (!component.added && useLongestToken) { + var value = newString.slice(newPos, newPos + component.count); + value = value.map(function (value, i) { + var oldValue = oldString[oldPos + i]; + return oldValue.length > value.length ? oldValue : value; + }); + component.value = diff.join(value); + } else { + component.value = diff.join(newString.slice(newPos, newPos + component.count)); + } + + newPos += component.count; // Common case + + if (!component.added) { + oldPos += component.count; + } + } else { + component.value = diff.join(oldString.slice(oldPos, oldPos + component.count)); + oldPos += component.count; // Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + + if (componentPos && components[componentPos - 1].added) { + var tmp = components[componentPos - 1]; + components[componentPos - 1] = components[componentPos]; + components[componentPos] = tmp; + } + } + } // Special case handle for when one terminal is ignored (i.e. whitespace). + // For this case we merge the terminal into the prior string and drop the change. + // This is only available for string mode. + + + var lastComponent = components[componentLen - 1]; + + if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { + components[componentLen - 2].value += lastComponent.value; + components.pop(); + } + + return components; + } + + function clonePath(path) { + return { + newPos: path.newPos, + components: path.components.slice(0) + }; + } + + var characterDiff = new Diff(); + function diffChars(oldStr, newStr, options) { + return characterDiff.diff(oldStr, newStr, options); + } + + function generateOptions(options, defaults) { + if (typeof options === 'function') { + defaults.callback = options; + } else if (options) { + for (var name in options) { + /* istanbul ignore else */ + if (options.hasOwnProperty(name)) { + defaults[name] = options[name]; + } + } + } + + return defaults; + } + + // + // Ranges and exceptions: + // Latin-1 Supplement, 0080–00FF + // - U+00D7 × Multiplication sign + // - U+00F7 ÷ Division sign + // Latin Extended-A, 0100–017F + // Latin Extended-B, 0180–024F + // IPA Extensions, 0250–02AF + // Spacing Modifier Letters, 02B0–02FF + // - U+02C7 ˇ ˇ Caron + // - U+02D8 ˘ ˘ Breve + // - U+02D9 ˙ ˙ Dot Above + // - U+02DA ˚ ˚ Ring Above + // - U+02DB ˛ ˛ Ogonek + // - U+02DC ˜ ˜ Small Tilde + // - U+02DD ˝ ˝ Double Acute Accent + // Latin Extended Additional, 1E00–1EFF + + var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/; + var reWhitespace = /\S/; + var wordDiff = new Diff(); + + wordDiff.equals = function (left, right) { + if (this.options.ignoreCase) { + left = left.toLowerCase(); + right = right.toLowerCase(); + } + + return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right); + }; + + wordDiff.tokenize = function (value) { + // All whitespace symbols except newline group into one token, each newline - in separate token + var tokens = value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + + for (var i = 0; i < tokens.length - 1; i++) { + // If we have an empty string in the next field and we have only word chars before and after, merge + if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) { + tokens[i] += tokens[i + 2]; + tokens.splice(i + 1, 2); + i--; + } + } + + return tokens; + }; + + function diffWords(oldStr, newStr, options) { + options = generateOptions(options, { + ignoreWhitespace: true + }); + return wordDiff.diff(oldStr, newStr, options); + } + function diffWordsWithSpace(oldStr, newStr, options) { + return wordDiff.diff(oldStr, newStr, options); + } + + var lineDiff = new Diff(); + + lineDiff.tokenize = function (value) { + var retLines = [], + linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line + + if (!linesAndNewlines[linesAndNewlines.length - 1]) { + linesAndNewlines.pop(); + } // Merge the content and line separators into single tokens + + + for (var i = 0; i < linesAndNewlines.length; i++) { + var line = linesAndNewlines[i]; + + if (i % 2 && !this.options.newlineIsToken) { + retLines[retLines.length - 1] += line; + } else { + if (this.options.ignoreWhitespace) { + line = line.trim(); + } + + retLines.push(line); + } + } + + return retLines; + }; + + function diffLines(oldStr, newStr, callback) { + return lineDiff.diff(oldStr, newStr, callback); + } + function diffTrimmedLines(oldStr, newStr, callback) { + var options = generateOptions(callback, { + ignoreWhitespace: true + }); + return lineDiff.diff(oldStr, newStr, options); + } + + var sentenceDiff = new Diff(); + + sentenceDiff.tokenize = function (value) { + return value.split(/(\S.+?[.!?])(?=\s+|$)/); + }; + + function diffSentences(oldStr, newStr, callback) { + return sentenceDiff.diff(oldStr, newStr, callback); + } + + var cssDiff = new Diff(); + + cssDiff.tokenize = function (value) { + return value.split(/([{}:;,]|\s+)/); + }; + + function diffCss(oldStr, newStr, callback) { + return cssDiff.diff(oldStr, newStr, callback); + } + + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var objectPrototypeToString = Object.prototype.toString; + var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a + // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: + + jsonDiff.useLongestToken = true; + jsonDiff.tokenize = lineDiff.tokenize; + + jsonDiff.castInput = function (value) { + var _this$options = this.options, + undefinedReplacement = _this$options.undefinedReplacement, + _this$options$stringi = _this$options.stringifyReplacer, + stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) { + return typeof v === 'undefined' ? undefinedReplacement : v; + } : _this$options$stringi; + return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); + }; + + jsonDiff.equals = function (left, right) { + return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); + }; + + function diffJson(oldObj, newObj, options) { + return jsonDiff.diff(oldObj, newObj, options); + } // This function handles the presence of circular references by bailing out when encountering an + // object that is already on the "stack" of items being processed. Accepts an optional replacer + + function canonicalize(obj, stack, replacementStack, replacer, key) { + stack = stack || []; + replacementStack = replacementStack || []; + + if (replacer) { + obj = replacer(key, obj); + } + + var i; + + for (i = 0; i < stack.length; i += 1) { + if (stack[i] === obj) { + return replacementStack[i]; + } + } - if (failed) { - failAssertion( - this, - (fake.printf || fake.proxy.printf).apply( - fake, - concat([msg], args) - ) - ); - } else { - assert.pass(name); - } - }; - } + var canonicalizedObj; + + if ('[object Array]' === objectPrototypeToString.call(obj)) { + stack.push(obj); + canonicalizedObj = new Array(obj.length); + replacementStack.push(canonicalizedObj); + + for (i = 0; i < obj.length; i += 1) { + canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key); + } + + stack.pop(); + replacementStack.pop(); + return canonicalizedObj; + } + + if (obj && obj.toJSON) { + obj = obj.toJSON(); + } + + if (_typeof(obj) === 'object' && obj !== null) { + stack.push(obj); + canonicalizedObj = {}; + replacementStack.push(canonicalizedObj); + + var sortedKeys = [], + _key; + + for (_key in obj) { + /* istanbul ignore else */ + if (obj.hasOwnProperty(_key)) { + sortedKeys.push(_key); + } + } + + sortedKeys.sort(); + + for (i = 0; i < sortedKeys.length; i += 1) { + _key = sortedKeys[i]; + canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key); + } + + stack.pop(); + replacementStack.pop(); + } else { + canonicalizedObj = obj; + } + + return canonicalizedObj; + } + + var arrayDiff = new Diff(); + + arrayDiff.tokenize = function (value) { + return value.slice(); + }; + + arrayDiff.join = arrayDiff.removeEmpty = function (value) { + return value; + }; + + function diffArrays(oldArr, newArr, callback) { + return arrayDiff.diff(oldArr, newArr, callback); + } + + function parsePatch(uniDiff) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [], + list = [], + i = 0; + + function parseIndex() { + var index = {}; + list.push(index); // Parse diff metadata + + while (i < diffstr.length) { + var line = diffstr[i]; // File header found, end parsing diff metadata + + if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) { + break; + } // Diff index + + + var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line); + + if (header) { + index.index = header[1]; + } + + i++; + } // Parse file headers if they are defined. Unified diff requires them, but + // there's no technical issues to have an isolated hunk without file header + + + parseFileHeader(index); + parseFileHeader(index); // Parse hunks + + index.hunks = []; + + while (i < diffstr.length) { + var _line = diffstr[i]; + + if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) { + break; + } else if (/^@@/.test(_line)) { + index.hunks.push(parseHunk()); + } else if (_line && options.strict) { + // Ignore unexpected content unless in strict mode + throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line)); + } else { + i++; + } + } + } // Parses the --- and +++ headers, if none are found, no lines + // are consumed. + + + function parseFileHeader(index) { + var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]); + + if (fileHeader) { + var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; + var data = fileHeader[2].split('\t', 2); + var fileName = data[0].replace(/\\\\/g, '\\'); + + if (/^".*"$/.test(fileName)) { + fileName = fileName.substr(1, fileName.length - 2); + } + + index[keyPrefix + 'FileName'] = fileName; + index[keyPrefix + 'Header'] = (data[1] || '').trim(); + i++; + } + } // Parses a hunk + // This assumes that we are at the start of a hunk. + + + function parseHunk() { + var chunkHeaderIndex = i, + chunkHeaderLine = diffstr[i++], + chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/); + var hunk = { + oldStart: +chunkHeader[1], + oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2], + newStart: +chunkHeader[3], + newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4], + lines: [], + linedelimiters: [] + }; // Unified Diff Format quirk: If the chunk size is 0, + // the first number is one lower than one would expect. + // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + + if (hunk.oldLines === 0) { + hunk.oldStart += 1; + } + + if (hunk.newLines === 0) { + hunk.newStart += 1; + } + + var addCount = 0, + removeCount = 0; + + for (; i < diffstr.length; i++) { + // Lines starting with '---' could be mistaken for the "remove line" operation + // But they could be the header for the next file. Therefore prune such cases out. + if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) { + break; + } + + var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0]; + + if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { + hunk.lines.push(diffstr[i]); + hunk.linedelimiters.push(delimiters[i] || '\n'); + + if (operation === '+') { + addCount++; + } else if (operation === '-') { + removeCount++; + } else if (operation === ' ') { + addCount++; + removeCount++; + } + } else { + break; + } + } // Handle the empty block count case + + + if (!addCount && hunk.newLines === 1) { + hunk.newLines = 0; + } + + if (!removeCount && hunk.oldLines === 1) { + hunk.oldLines = 0; + } // Perform optional sanity checking + + + if (options.strict) { + if (addCount !== hunk.newLines) { + throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + + if (removeCount !== hunk.oldLines) { + throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + } + + return hunk; + } + + while (i < diffstr.length) { + parseIndex(); + } + + return list; + } + + // Iterator that traverses in the range of [min, max], stepping + // by distance from a given start position. I.e. for [0, 4], with + // start of 2, this will iterate 2, 3, 1, 4, 0. + function distanceIterator (start, minLine, maxLine) { + var wantForward = true, + backwardExhausted = false, + forwardExhausted = false, + localOffset = 1; + return function iterator() { + if (wantForward && !forwardExhausted) { + if (backwardExhausted) { + localOffset++; + } else { + wantForward = false; + } // Check if trying to fit beyond text length, and if not, check it fits + // after offset location (or desired location on first iteration) + + + if (start + localOffset <= maxLine) { + return localOffset; + } + + forwardExhausted = true; + } + + if (!backwardExhausted) { + if (!forwardExhausted) { + wantForward = true; + } // Check if trying to fit before text beginning, and if not, check it fits + // before offset location + + + if (minLine <= start - localOffset) { + return -localOffset++; + } + + backwardExhausted = true; + return iterator(); + } // We tried to fit hunk before text beginning and beyond text length, then + // hunk can't fit on the text. Return undefined + + }; + } + + function applyPatch(source, uniDiff) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (typeof uniDiff === 'string') { + uniDiff = parsePatch(uniDiff); + } + + if (Array.isArray(uniDiff)) { + if (uniDiff.length > 1) { + throw new Error('applyPatch only works with a single input.'); + } + + uniDiff = uniDiff[0]; + } // Apply the diff to the input + + + var lines = source.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [], + hunks = uniDiff.hunks, + compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) { + return line === patchContent; + }, + errorCount = 0, + fuzzFactor = options.fuzzFactor || 0, + minLine = 0, + offset = 0, + removeEOFNL, + addEOFNL; + /** + * Checks if the hunk exactly fits on the provided location + */ + + + function hunkFits(hunk, toPos) { + for (var j = 0; j < hunk.lines.length; j++) { + var line = hunk.lines[j], + operation = line.length > 0 ? line[0] : ' ', + content = line.length > 0 ? line.substr(1) : line; + + if (operation === ' ' || operation === '-') { + // Context sanity check + if (!compareLine(toPos + 1, lines[toPos], operation, content)) { + errorCount++; + + if (errorCount > fuzzFactor) { + return false; + } + } + + toPos++; + } + } + + return true; + } // Search best fit offsets for each hunk based on the previous ones + + + for (var i = 0; i < hunks.length; i++) { + var hunk = hunks[i], + maxLine = lines.length - hunk.oldLines, + localOffset = 0, + toPos = offset + hunk.oldStart - 1; + var iterator = distanceIterator(toPos, minLine, maxLine); + + for (; localOffset !== undefined; localOffset = iterator()) { + if (hunkFits(hunk, toPos + localOffset)) { + hunk.offset = offset += localOffset; + break; + } + } + + if (localOffset === undefined) { + return false; + } // Set lower text limit to end of the current hunk, so next ones don't try + // to fit over already patched text + + + minLine = hunk.offset + hunk.oldStart + hunk.oldLines; + } // Apply patch hunks + + + var diffOffset = 0; + + for (var _i = 0; _i < hunks.length; _i++) { + var _hunk = hunks[_i], + _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1; + + diffOffset += _hunk.newLines - _hunk.oldLines; + + for (var j = 0; j < _hunk.lines.length; j++) { + var line = _hunk.lines[j], + operation = line.length > 0 ? line[0] : ' ', + content = line.length > 0 ? line.substr(1) : line, + delimiter = _hunk.linedelimiters[j]; + + if (operation === ' ') { + _toPos++; + } else if (operation === '-') { + lines.splice(_toPos, 1); + delimiters.splice(_toPos, 1); + /* istanbul ignore else */ + } else if (operation === '+') { + lines.splice(_toPos, 0, content); + delimiters.splice(_toPos, 0, delimiter); + _toPos++; + } else if (operation === '\\') { + var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; + + if (previousOperation === '+') { + removeEOFNL = true; + } else if (previousOperation === '-') { + addEOFNL = true; + } + } + } + } // Handle EOFNL insertion/removal + + + if (removeEOFNL) { + while (!lines[lines.length - 1]) { + lines.pop(); + delimiters.pop(); + } + } else if (addEOFNL) { + lines.push(''); + delimiters.push('\n'); + } + + for (var _k = 0; _k < lines.length - 1; _k++) { + lines[_k] = lines[_k] + delimiters[_k]; + } + + return lines.join(''); + } // Wrapper that supports multiple file patches via callbacks. + + function applyPatches(uniDiff, options) { + if (typeof uniDiff === 'string') { + uniDiff = parsePatch(uniDiff); + } + + var currentIndex = 0; + + function processIndex() { + var index = uniDiff[currentIndex++]; + + if (!index) { + return options.complete(); + } + + options.loadFile(index, function (err, data) { + if (err) { + return options.complete(err); + } + + var updatedContent = applyPatch(data, index, options); + options.patched(index, updatedContent, function (err) { + if (err) { + return options.complete(err); + } + + processIndex(); + }); + }); + } + + processIndex(); + } + + function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + if (!options) { + options = {}; + } + + if (typeof options.context === 'undefined') { + options.context = 4; + } + + var diff = diffLines(oldStr, newStr, options); + + if (!diff) { + return; + } + + diff.push({ + value: '', + lines: [] + }); // Append an empty value to make cleanup easier + + function contextLines(lines) { + return lines.map(function (entry) { + return ' ' + entry; + }); + } + + var hunks = []; + var oldRangeStart = 0, + newRangeStart = 0, + curRange = [], + oldLine = 1, + newLine = 1; + + var _loop = function _loop(i) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, '').split('\n'); + current.lines = lines; + + if (current.added || current.removed) { + var _curRange; + + // If we have previous context, start with that + if (!oldRangeStart) { + var prev = diff[i - 1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } // Output our changes + + + (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) { + return (current.added ? '+' : '-') + entry; + }))); // Track the updated file position + + + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + // Identical context lines. Track line changes + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= options.context * 2 && i < diff.length - 2) { + var _curRange2; + + // Overlapping + (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines))); + } else { + var _curRange3; + + // end the range and output + var contextSize = Math.min(lines.length, options.context); + + (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize)))); + + var hunk = { + oldStart: oldRangeStart, + oldLines: oldLine - oldRangeStart + contextSize, + newStart: newRangeStart, + newLines: newLine - newRangeStart + contextSize, + lines: curRange + }; + + if (i >= diff.length - 2 && lines.length <= options.context) { + // EOF is inside this hunk + var oldEOFNewline = /\n$/.test(oldStr); + var newEOFNewline = /\n$/.test(newStr); + var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines; + + if (!oldEOFNewline && noNlBeforeAdds && oldStr.length > 0) { + // special case: old has no eol and no trailing context; no-nl can end up before adds + // however, if the old file is empty, do not output the no-nl line + curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file'); + } + + if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) { + curRange.push('\\ No newline at end of file'); + } + } + + hunks.push(hunk); + oldRangeStart = 0; + newRangeStart = 0; + curRange = []; + } + } + + oldLine += lines.length; + newLine += lines.length; + } + }; + + for (var i = 0; i < diff.length; i++) { + _loop(i); + } + + return { + oldFileName: oldFileName, + newFileName: newFileName, + oldHeader: oldHeader, + newHeader: newHeader, + hunks: hunks + }; + } + function formatPatch(diff) { + var ret = []; + + if (diff.oldFileName == diff.newFileName) { + ret.push('Index: ' + diff.oldFileName); + } + + ret.push('==================================================================='); + ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); + ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); + + for (var i = 0; i < diff.hunks.length; i++) { + var hunk = diff.hunks[i]; // Unified Diff Format quirk: If the chunk size is 0, + // the first number is one lower than one would expect. + // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + + if (hunk.oldLines === 0) { + hunk.oldStart -= 1; + } + + if (hunk.newLines === 0) { + hunk.newStart -= 1; + } + + ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@'); + ret.push.apply(ret, hunk.lines); + } + + return ret.join('\n') + '\n'; + } + function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + return formatPatch(structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)); + } + function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { + return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); + } + + function arrayEqual(a, b) { + if (a.length !== b.length) { + return false; + } + + return arrayStartsWith(a, b); + } + function arrayStartsWith(array, start) { + if (start.length > array.length) { + return false; + } + + for (var i = 0; i < start.length; i++) { + if (start[i] !== array[i]) { + return false; + } + } + + return true; + } + + function calcLineCount(hunk) { + var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines), + oldLines = _calcOldNewLineCount.oldLines, + newLines = _calcOldNewLineCount.newLines; + + if (oldLines !== undefined) { + hunk.oldLines = oldLines; + } else { + delete hunk.oldLines; + } + + if (newLines !== undefined) { + hunk.newLines = newLines; + } else { + delete hunk.newLines; + } + } + function merge(mine, theirs, base) { + mine = loadPatch(mine, base); + theirs = loadPatch(theirs, base); + var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning. + // Leaving sanity checks on this to the API consumer that may know more about the + // meaning in their own context. + + if (mine.index || theirs.index) { + ret.index = mine.index || theirs.index; + } + + if (mine.newFileName || theirs.newFileName) { + if (!fileNameChanged(mine)) { + // No header or no change in ours, use theirs (and ours if theirs does not exist) + ret.oldFileName = theirs.oldFileName || mine.oldFileName; + ret.newFileName = theirs.newFileName || mine.newFileName; + ret.oldHeader = theirs.oldHeader || mine.oldHeader; + ret.newHeader = theirs.newHeader || mine.newHeader; + } else if (!fileNameChanged(theirs)) { + // No header or no change in theirs, use ours + ret.oldFileName = mine.oldFileName; + ret.newFileName = mine.newFileName; + ret.oldHeader = mine.oldHeader; + ret.newHeader = mine.newHeader; + } else { + // Both changed... figure it out + ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName); + ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName); + ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader); + ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader); + } + } + + ret.hunks = []; + var mineIndex = 0, + theirsIndex = 0, + mineOffset = 0, + theirsOffset = 0; + + while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) { + var mineCurrent = mine.hunks[mineIndex] || { + oldStart: Infinity + }, + theirsCurrent = theirs.hunks[theirsIndex] || { + oldStart: Infinity + }; + + if (hunkBefore(mineCurrent, theirsCurrent)) { + // This patch does not overlap with any of the others, yay. + ret.hunks.push(cloneHunk(mineCurrent, mineOffset)); + mineIndex++; + theirsOffset += mineCurrent.newLines - mineCurrent.oldLines; + } else if (hunkBefore(theirsCurrent, mineCurrent)) { + // This patch does not overlap with any of the others, yay. + ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset)); + theirsIndex++; + mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines; + } else { + // Overlap, merge as best we can + var mergedHunk = { + oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart), + oldLines: 0, + newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset), + newLines: 0, + lines: [] + }; + mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines); + theirsIndex++; + mineIndex++; + ret.hunks.push(mergedHunk); + } + } + + return ret; + } + + function loadPatch(param, base) { + if (typeof param === 'string') { + if (/^@@/m.test(param) || /^Index:/m.test(param)) { + return parsePatch(param)[0]; + } + + if (!base) { + throw new Error('Must provide a base reference or pass in a patch'); + } + + return structuredPatch(undefined, undefined, base, param); + } + + return param; + } + + function fileNameChanged(patch) { + return patch.newFileName && patch.newFileName !== patch.oldFileName; + } + + function selectField(index, mine, theirs) { + if (mine === theirs) { + return mine; + } else { + index.conflict = true; + return { + mine: mine, + theirs: theirs + }; + } + } + + function hunkBefore(test, check) { + return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart; + } + + function cloneHunk(hunk, offset) { + return { + oldStart: hunk.oldStart, + oldLines: hunk.oldLines, + newStart: hunk.newStart + offset, + newLines: hunk.newLines, + lines: hunk.lines + }; + } + + function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) { + // This will generally result in a conflicted hunk, but there are cases where the context + // is the only overlap where we can successfully merge the content here. + var mine = { + offset: mineOffset, + lines: mineLines, + index: 0 + }, + their = { + offset: theirOffset, + lines: theirLines, + index: 0 + }; // Handle any leading content + + insertLeading(hunk, mine, their); + insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each. + + while (mine.index < mine.lines.length && their.index < their.lines.length) { + var mineCurrent = mine.lines[mine.index], + theirCurrent = their.lines[their.index]; + + if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) { + // Both modified ... + mutualChange(hunk, mine, their); + } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') { + var _hunk$lines; + + // Mine inserted + (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine))); + } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') { + var _hunk$lines2; + + // Theirs inserted + (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their))); + } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') { + // Mine removed or edited + removal(hunk, mine, their); + } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') { + // Their removed or edited + removal(hunk, their, mine, true); + } else if (mineCurrent === theirCurrent) { + // Context identity + hunk.lines.push(mineCurrent); + mine.index++; + their.index++; + } else { + // Context mismatch + conflict(hunk, collectChange(mine), collectChange(their)); + } + } // Now push anything that may be remaining + + + insertTrailing(hunk, mine); + insertTrailing(hunk, their); + calcLineCount(hunk); + } + + function mutualChange(hunk, mine, their) { + var myChanges = collectChange(mine), + theirChanges = collectChange(their); + + if (allRemoves(myChanges) && allRemoves(theirChanges)) { + // Special case for remove changes that are supersets of one another + if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) { + var _hunk$lines3; + + (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges)); + + return; + } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) { + var _hunk$lines4; + + (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges)); + + return; + } + } else if (arrayEqual(myChanges, theirChanges)) { + var _hunk$lines5; + + (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges)); + + return; + } + + conflict(hunk, myChanges, theirChanges); + } + + function removal(hunk, mine, their, swap) { + var myChanges = collectChange(mine), + theirChanges = collectContext(their, myChanges); + + if (theirChanges.merged) { + var _hunk$lines6; + + (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged)); + } else { + conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges); + } + } + + function conflict(hunk, mine, their) { + hunk.conflict = true; + hunk.lines.push({ + conflict: true, + mine: mine, + theirs: their + }); + } + + function insertLeading(hunk, insert, their) { + while (insert.offset < their.offset && insert.index < insert.lines.length) { + var line = insert.lines[insert.index++]; + hunk.lines.push(line); + insert.offset++; + } + } + + function insertTrailing(hunk, insert) { + while (insert.index < insert.lines.length) { + var line = insert.lines[insert.index++]; + hunk.lines.push(line); + } + } + + function collectChange(state) { + var ret = [], + operation = state.lines[state.index][0]; + + while (state.index < state.lines.length) { + var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change. + + if (operation === '-' && line[0] === '+') { + operation = '+'; + } + + if (operation === line[0]) { + ret.push(line); + state.index++; + } else { + break; + } + } + + return ret; + } + + function collectContext(state, matchChanges) { + var changes = [], + merged = [], + matchIndex = 0, + contextChanges = false, + conflicted = false; + + while (matchIndex < matchChanges.length && state.index < state.lines.length) { + var change = state.lines[state.index], + match = matchChanges[matchIndex]; // Once we've hit our add, then we are done + + if (match[0] === '+') { + break; + } + + contextChanges = contextChanges || change[0] !== ' '; + merged.push(match); + matchIndex++; // Consume any additions in the other block as a conflict to attempt + // to pull in the remaining context after this + + if (change[0] === '+') { + conflicted = true; + + while (change[0] === '+') { + changes.push(change); + change = state.lines[++state.index]; + } + } + + if (match.substr(1) === change.substr(1)) { + changes.push(change); + state.index++; + } else { + conflicted = true; + } + } + + if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) { + conflicted = true; + } + + if (conflicted) { + return changes; + } + + while (matchIndex < matchChanges.length) { + merged.push(matchChanges[matchIndex++]); + } + + return { + merged: merged, + changes: changes + }; + } + + function allRemoves(changes) { + return changes.reduce(function (prev, change) { + return prev && change[0] === '-'; + }, true); + } + + function skipRemoveSuperset(state, removeChanges, delta) { + for (var i = 0; i < delta; i++) { + var changeContent = removeChanges[removeChanges.length - delta + i].substr(1); + + if (state.lines[state.index + i] !== ' ' + changeContent) { + return false; + } + } + + state.index += delta; + return true; + } + + function calcOldNewLineCount(lines) { + var oldLines = 0; + var newLines = 0; + lines.forEach(function (line) { + if (typeof line !== 'string') { + var myCount = calcOldNewLineCount(line.mine); + var theirCount = calcOldNewLineCount(line.theirs); + + if (oldLines !== undefined) { + if (myCount.oldLines === theirCount.oldLines) { + oldLines += myCount.oldLines; + } else { + oldLines = undefined; + } + } + + if (newLines !== undefined) { + if (myCount.newLines === theirCount.newLines) { + newLines += myCount.newLines; + } else { + newLines = undefined; + } + } + } else { + if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) { + newLines++; + } + + if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) { + oldLines++; + } + } + }); + return { + oldLines: oldLines, + newLines: newLines + }; + } + + // See: http://code.google.com/p/google-diff-match-patch/wiki/API + function convertChangesToDMP(changes) { + var ret = [], + change, + operation; + + for (var i = 0; i < changes.length; i++) { + change = changes[i]; + + if (change.added) { + operation = 1; + } else if (change.removed) { + operation = -1; + } else { + operation = 0; + } + + ret.push([operation, change.value]); + } + + return ret; + } + + function convertChangesToXML(changes) { + var ret = []; + + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + } + + return ret.join(''); + } + + function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, '&'); + n = n.replace(//g, '>'); + n = n.replace(/"/g, '"'); + return n; + } + + exports.Diff = Diff; + exports.applyPatch = applyPatch; + exports.applyPatches = applyPatches; + exports.canonicalize = canonicalize; + exports.convertChangesToDMP = convertChangesToDMP; + exports.convertChangesToXML = convertChangesToXML; + exports.createPatch = createPatch; + exports.createTwoFilesPatch = createTwoFilesPatch; + exports.diffArrays = diffArrays; + exports.diffChars = diffChars; + exports.diffCss = diffCss; + exports.diffJson = diffJson; + exports.diffLines = diffLines; + exports.diffSentences = diffSentences; + exports.diffTrimmedLines = diffTrimmedLines; + exports.diffWords = diffWords; + exports.diffWordsWithSpace = diffWordsWithSpace; + exports.merge = merge; + exports.parsePatch = parsePatch; + exports.structuredPatch = structuredPatch; + + Object.defineProperty(exports, '__esModule', { value: true }); + + }))); + + },{}],114:[function(require,module,exports){ + module.exports = extend; + + /* + var obj = {a: 3, b: 5}; + extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 4, b: 5, c: 8} + + var obj = {a: 3, b: 5}; + extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 3, b: 5} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3]} + + extend({a: 4, b: 5}); // {a: 4, b: 5} + extend({a: 4, b: 5}, 3); {a: 4, b: 5} + extend({a: 4, b: 5}, true); {a: 4, b: 5} + extend('hello', {a: 4, b: 5}); // throws + extend(3, {a: 4, b: 5}); // throws + */ + + function extend(/* [deep], obj1, obj2, [objn] */) { + var args = [].slice.call(arguments); + var deep = false; + if (typeof args[0] == 'boolean') { + deep = args.shift(); + } + var result = args[0]; + if (isUnextendable(result)) { + throw new Error('extendee must be an object'); + } + var extenders = args.slice(1); + var len = extenders.length; + for (var i = 0; i < len; i++) { + var extender = extenders[i]; + for (var key in extender) { + if (Object.prototype.hasOwnProperty.call(extender, key)) { + var value = extender[key]; + if (deep && isCloneable(value)) { + var base = Array.isArray(value) ? [] : {}; + result[key] = extend( + true, + Object.prototype.hasOwnProperty.call(result, key) && !isUnextendable(result[key]) + ? result[key] + : base, + value + ); + } else { + result[key] = value; + } + } + } + } + return result; + } + + function isCloneable(obj) { + return Array.isArray(obj) || {}.toString.call(obj) == '[object Object]'; + } + + function isUnextendable(val) { + return !val || (typeof val != 'object' && typeof val != 'function'); + } + + },{}],115:[function(require,module,exports){ + /** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0; + + /** `Object#toString` result references. */ + var funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof commonjsGlobal$1 == 'object' && commonjsGlobal$1 && commonjsGlobal$1.Object === Object && commonjsGlobal$1; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ + function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) {} + } + return result; + } + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = root['__core-js_shared__']; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Symbol = root.Symbol, + splice = arrayProto.splice; + + /* Built-in method references that are verified to be native. */ + var Map = getNative(root, 'Map'), + nativeCreate = getNative(Object, 'create'); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + return getMapData(this, key)['delete'](key); + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + getMapData(this, key).set(key, value); + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value) { + return isArray(value) ? value : stringToPath(value); + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoize(function(string) { + string = toString(string); + + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Assign cache to `_.memoize`. + memoize.Cache = MapCache; + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return !!value && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + module.exports = get; + + },{}],116:[function(require,module,exports){ + + // cache a reference to setTimeout, so that our reference won't be stubbed out + // when using fake timers and errors will still get logged + // https://github.com/cjohansen/Sinon.JS/issues/381 + var realSetTimeout = setTimeout; + + function configureLogger(config) { + // eslint-disable-next-line no-param-reassign + config = config || {}; + // Function which prints errors. + if (!config.hasOwnProperty("logger")) { + // eslint-disable-next-line no-empty-function + config.logger = function() {}; + } + // When set to true, any errors logged will be thrown immediately; + // If set to false, the errors will be thrown in separate execution frame. + if (!config.hasOwnProperty("useImmediateExceptions")) { + config.useImmediateExceptions = true; + } + // wrap realSetTimeout with something we can stub in tests + if (!config.hasOwnProperty("setTimeout")) { + config.setTimeout = realSetTimeout; + } + + return function logError(label, e) { + var msg = `${label} threw exception: `; + var err = { + name: e.name || label, + message: e.message || e.toString(), + stack: e.stack + }; + + function throwLoggedError() { + err.message = msg + err.message; + throw err; + } + + config.logger(`${msg}[${err.name}] ${err.message}`); + + if (err.stack) { + config.logger(err.stack); + } + + if (config.useImmediateExceptions) { + throwLoggedError(); + } else { + config.setTimeout(throwLoggedError, 0); + } + }; + } + + module.exports = configureLogger; + + },{}],117:[function(require,module,exports){ + + var Event = require("./event"); + + function CustomEvent(type, customData, target) { + this.initEvent(type, false, false, target); + this.detail = customData.detail || null; + } + + CustomEvent.prototype = new Event(); + + CustomEvent.prototype.constructor = CustomEvent; + + module.exports = CustomEvent; + + },{"./event":119}],118:[function(require,module,exports){ + + function flattenOptions(options) { + if (options !== Object(options)) { + return { + capture: Boolean(options), + once: false, + passive: false + }; + } + return { + capture: Boolean(options.capture), + once: Boolean(options.once), + passive: Boolean(options.passive) + }; + } + function not(fn) { + return function() { + return !fn.apply(this, arguments); + }; + } + function hasListenerFilter(listener, capture) { + return function(listenerSpec) { + return ( + listenerSpec.capture === capture && + listenerSpec.listener === listener + ); + }; + } + + var EventTarget = { + // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener + addEventListener: function addEventListener( + event, + listener, + providedOptions + ) { + // 3. Let capture, passive, and once be the result of flattening more options. + // Flatten property before executing step 2, + // feture detection is usually based on registering handler with options object, + // that has getter defined + // addEventListener("load", () => {}, { + // get once() { supportsOnce = true; } + // }); + var options = flattenOptions(providedOptions); + + // 2. If callback is null, then return. + if (listener === null || listener === undefined) { + return; + } + + this.eventListeners = this.eventListeners || {}; + this.eventListeners[event] = this.eventListeners[event] || []; + + // 4. If context object’s associated list of event listener + // does not contain an event listener whose type is type, + // callback is callback, and capture is capture, then append + // a new event listener to it, whose type is type, callback is + // callback, capture is capture, passive is passive, and once is once. + if ( + !this.eventListeners[event].some( + hasListenerFilter(listener, options.capture) + ) + ) { + this.eventListeners[event].push({ + listener: listener, + capture: options.capture, + once: options.once + }); + } + }, + + // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener + removeEventListener: function removeEventListener( + event, + listener, + providedOptions + ) { + if (!this.eventListeners || !this.eventListeners[event]) { + return; + } + + // 2. Let capture be the result of flattening options. + var options = flattenOptions(providedOptions); + + // 3. If there is an event listener in the associated list of + // event listeners whose type is type, callback is callback, + // and capture is capture, then set that event listener’s + // removed to true and remove it from the associated list of event listeners. + this.eventListeners[event] = this.eventListeners[event].filter( + not(hasListenerFilter(listener, options.capture)) + ); + }, + + dispatchEvent: function dispatchEvent(event) { + if (!this.eventListeners || !this.eventListeners[event.type]) { + return Boolean(event.defaultPrevented); + } + + var self = this; + var type = event.type; + var listeners = self.eventListeners[type]; + + // Remove listeners, that should be dispatched once + // before running dispatch loop to avoid nested dispatch issues + self.eventListeners[type] = listeners.filter(function(listenerSpec) { + return !listenerSpec.once; + }); + listeners.forEach(function(listenerSpec) { + var listener = listenerSpec.listener; + if (typeof listener === "function") { + listener.call(self, event); + } else { + listener.handleEvent(event); + } + }); + + return Boolean(event.defaultPrevented); + } + }; + + module.exports = EventTarget; + + },{}],119:[function(require,module,exports){ + + function Event(type, bubbles, cancelable, target) { + this.initEvent(type, bubbles, cancelable, target); + } + + Event.prototype = { + initEvent: function(type, bubbles, cancelable, target) { + this.type = type; + this.bubbles = bubbles; + this.cancelable = cancelable; + this.target = target; + this.currentTarget = target; + }, + + // eslint-disable-next-line no-empty-function + stopPropagation: function() {}, + + preventDefault: function() { + this.defaultPrevented = true; + } + }; + + module.exports = Event; + + },{}],120:[function(require,module,exports){ + + module.exports = { + Event: require("./event"), + ProgressEvent: require("./progress-event"), + CustomEvent: require("./custom-event"), + EventTarget: require("./event-target") + }; + + },{"./custom-event":117,"./event":119,"./event-target":118,"./progress-event":121}],121:[function(require,module,exports){ + + var Event = require("./event"); + + function ProgressEvent(type, progressEventRaw, target) { + this.initEvent(type, false, false, target); + this.loaded = + typeof progressEventRaw.loaded === "number" + ? progressEventRaw.loaded + : null; + this.total = + typeof progressEventRaw.total === "number" + ? progressEventRaw.total + : null; + this.lengthComputable = Boolean(progressEventRaw.total); + } + + ProgressEvent.prototype = new Event(); + + ProgressEvent.prototype.constructor = ProgressEvent; + + module.exports = ProgressEvent; + + },{"./event":119}],122:[function(require,module,exports){ + + var FakeTimers = require("@sinonjs/fake-timers"); + var fakeServer = require("./index"); + + // eslint-disable-next-line no-empty-function + function Server() {} + Server.prototype = fakeServer; + + var fakeServerWithClock = new Server(); + + fakeServerWithClock.addRequest = function addRequest(xhr) { + if (xhr.async) { + if (typeof setTimeout.clock === "object") { + this.clock = setTimeout.clock; + } else { + this.clock = FakeTimers.install(); + this.resetClock = true; + } + + if (!this.longestTimeout) { + var clockSetTimeout = this.clock.setTimeout; + var clockSetInterval = this.clock.setInterval; + var server = this; + + this.clock.setTimeout = function(fn, timeout) { + server.longestTimeout = Math.max( + timeout, + server.longestTimeout || 0 + ); + + return clockSetTimeout.apply(this, arguments); + }; + + this.clock.setInterval = function(fn, timeout) { + server.longestTimeout = Math.max( + timeout, + server.longestTimeout || 0 + ); + + return clockSetInterval.apply(this, arguments); + }; + } + } + + return fakeServer.addRequest.call(this, xhr); + }; + + fakeServerWithClock.respond = function respond() { + var returnVal = fakeServer.respond.apply(this, arguments); + + if (this.clock) { + this.clock.tick(this.longestTimeout || 0); + this.longestTimeout = 0; + + if (this.resetClock) { + this.clock.uninstall(); + this.resetClock = false; + } + } + + return returnVal; + }; + + fakeServerWithClock.restore = function restore() { + if (this.clock) { + this.clock.uninstall(); + } + + return fakeServer.restore.apply(this, arguments); + }; + + module.exports = fakeServerWithClock; + + },{"./index":123,"@sinonjs/fake-timers":60}],123:[function(require,module,exports){ + + var fakeXhr = require("../fake-xhr"); + var push = [].push; + var log = require("./log"); + var configureLogError = require("../configure-logger"); + var pathToRegexp = require("path-to-regexp"); + + var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + + function responseArray(handler) { + var response = handler; + + if (Object.prototype.toString.call(handler) !== "[object Array]") { + response = [200, {}, handler]; + } + + if (typeof response[2] !== "string") { + if (!supportsArrayBuffer) { + throw new TypeError( + `Fake server response body should be a string, but was ${typeof response[2]}` + ); + } else if (!(response[2] instanceof ArrayBuffer)) { + throw new TypeError( + `Fake server response body should be a string or ArrayBuffer, but was ${typeof response[2]}` + ); + } + } + + return response; + } + + function getDefaultWindowLocation() { + var winloc = { + hostname: "localhost", + port: process.env.PORT || 80, + protocol: "http:" + }; + winloc.host = + winloc.hostname + + (String(winloc.port) === "80" ? "" : `:${winloc.port}`); + return winloc; + } + + function getWindowLocation() { + if (typeof window === "undefined") { + // Fallback + return getDefaultWindowLocation(); + } + + if (typeof window.location !== "undefined") { + // Browsers place location on window + return window.location; + } + + if ( + typeof window.window !== "undefined" && + typeof window.window.location !== "undefined" + ) { + // React Native on Android places location on window.window + return window.window.location; + } + + return getDefaultWindowLocation(); + } + + function matchOne(response, reqMethod, reqUrl) { + var rmeth = response.method; + var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase(); + var url = response.url; + var matchUrl = + !url || + url === reqUrl || + (typeof url.test === "function" && url.test(reqUrl)) || + (typeof url === "function" && url(reqUrl) === true); + + return matchMethod && matchUrl; + } + + function match(response, request) { + var wloc = getWindowLocation(); + + var rCurrLoc = new RegExp(`^${wloc.protocol}//${wloc.host}/`); + + var requestUrl = request.url; + + if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) { + requestUrl = requestUrl.replace(rCurrLoc, "/"); + } + + if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { + if (typeof response.response === "function") { + var ru = response.url; + var args = [request].concat( + ru && typeof ru.exec === "function" + ? ru.exec(requestUrl).slice(1) + : [] + ); + return response.response.apply(response, args); + } + + return true; + } + + return false; + } + + function incrementRequestCount() { + var count = ++this.requestCount; + + this.requested = true; + + this.requestedOnce = count === 1; + this.requestedTwice = count === 2; + this.requestedThrice = count === 3; + + this.firstRequest = this.getRequest(0); + this.secondRequest = this.getRequest(1); + this.thirdRequest = this.getRequest(2); + + this.lastRequest = this.getRequest(count - 1); + } + + var fakeServer = { + create: function(config) { + var server = Object.create(this); + server.configure(config); + this.xhr = fakeXhr.useFakeXMLHttpRequest(); + server.requests = []; + server.requestCount = 0; + server.queue = []; + server.responses = []; + + this.xhr.onCreate = function(xhrObj) { + xhrObj.unsafeHeadersEnabled = function() { + return !(server.unsafeHeadersEnabled === false); + }; + server.addRequest(xhrObj); + }; + + return server; + }, + + configure: function(config) { + var self = this; + var allowlist = { + autoRespond: true, + autoRespondAfter: true, + respondImmediately: true, + fakeHTTPMethods: true, + logger: true, + unsafeHeadersEnabled: true + }; + + // eslint-disable-next-line no-param-reassign + config = config || {}; + + Object.keys(config).forEach(function(setting) { + if (setting in allowlist) { + self[setting] = config[setting]; + } + }); + + self.logError = configureLogError(config); + }, + + addRequest: function addRequest(xhrObj) { + var server = this; + push.call(this.requests, xhrObj); + + incrementRequestCount.call(this); + + xhrObj.onSend = function() { + server.handleRequest(this); + + if (server.respondImmediately) { + server.respond(); + } else if (server.autoRespond && !server.responding) { + setTimeout(function() { + server.responding = false; + server.respond(); + }, server.autoRespondAfter || 10); + + server.responding = true; + } + }; + }, + + getHTTPMethod: function getHTTPMethod(request) { + if (this.fakeHTTPMethods && /post/i.test(request.method)) { + var matches = (request.requestBody || "").match( + /_method=([^\b;]+)/ + ); + return matches ? matches[1] : request.method; + } + + return request.method; + }, + + handleRequest: function handleRequest(xhr) { + if (xhr.async) { + push.call(this.queue, xhr); + } else { + this.processRequest(xhr); + } + }, + + logger: function() { + // no-op; override via configure() + }, + + logError: configureLogError({}), + + log: log, + + respondWith: function respondWith(method, url, body) { + if (arguments.length === 1 && typeof method !== "function") { + this.response = responseArray(method); + return; + } + + if (arguments.length === 1) { + // eslint-disable-next-line no-param-reassign + body = method; + // eslint-disable-next-line no-param-reassign + url = method = null; + } + + if (arguments.length === 2) { + // eslint-disable-next-line no-param-reassign + body = url; + // eslint-disable-next-line no-param-reassign + url = method; + // eslint-disable-next-line no-param-reassign + method = null; + } + + // Escape port number to prevent "named" parameters in 'path-to-regexp' module + if (typeof url === "string" && url !== "" && /:[0-9]+\//.test(url)) { + var m = url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/); + // eslint-disable-next-line no-param-reassign + url = `${m[1]}\\:${m[2]}`; + } + + push.call(this.responses, { + method: method, + url: + typeof url === "string" && url !== "" ? pathToRegexp(url) : url, + response: typeof body === "function" ? body : responseArray(body) + }); + }, + + respond: function respond() { + if (arguments.length > 0) { + this.respondWith.apply(this, arguments); + } + + var queue = this.queue || []; + var requests = queue.splice(0, queue.length); + var self = this; + + requests.forEach(function(request) { + self.processRequest(request); + }); + }, + + respondAll: function respondAll() { + if (this.respondImmediately) { + return; + } + + this.queue = this.requests.slice(0); + + var request; + while ((request = this.queue.shift())) { + this.processRequest(request); + } + }, + + processRequest: function processRequest(request) { + try { + if (request.aborted) { + return; + } + + var response = this.response || [404, {}, ""]; + + if (this.responses) { + for (var l = this.responses.length, i = l - 1; i >= 0; i--) { + if (match.call(this, this.responses[i], request)) { + response = this.responses[i].response; + break; + } + } + } + + if (request.readyState !== 4) { + this.log(response, request); + + request.respond(response[0], response[1], response[2]); + } + } catch (e) { + this.logError("Fake server request processing", e); + } + }, + + restore: function restore() { + return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments); + }, + + getRequest: function getRequest(index) { + return this.requests[index] || null; + }, + + reset: function reset() { + this.resetBehavior(); + this.resetHistory(); + }, + + resetBehavior: function resetBehavior() { + this.responses.length = this.queue.length = 0; + }, + + resetHistory: function resetHistory() { + this.requests.length = this.requestCount = 0; + + this.requestedOnce = this.requestedTwice = this.requestedThrice = this.requested = false; + + this.firstRequest = this.secondRequest = this.thirdRequest = this.lastRequest = null; + } + }; + + module.exports = fakeServer; + + },{"../configure-logger":116,"../fake-xhr":126,"./log":124,"path-to-regexp":147}],124:[function(require,module,exports){ + var inspect = require("util").inspect; + + function log(response, request) { + var str; + + str = `Request:\n${inspect(request)}\n\n`; + str += `Response:\n${inspect(response)}\n\n`; + + /* istanbul ignore else: when this.logger is not a function, it can't be called */ + if (typeof this.logger === "function") { + this.logger(str); + } + } + + module.exports = log; + + },{"util":112}],125:[function(require,module,exports){ + + exports.isSupported = (function() { + try { + return Boolean(new Blob()); + } catch (e) { + return false; + } + })(); + + },{}],126:[function(require,module,exports){ + + var GlobalTextEncoder = + typeof TextEncoder !== "undefined" + ? TextEncoder + : require("@sinonjs/text-encoding").TextEncoder; + var globalObject = require("@sinonjs/commons").global; + var configureLogError = require("../configure-logger"); + var sinonEvent = require("../event"); + var extend = require("just-extend"); + + var supportsProgress = typeof ProgressEvent !== "undefined"; + var supportsCustomEvent = typeof CustomEvent !== "undefined"; + var supportsFormData = typeof FormData !== "undefined"; + var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + var supportsBlob = require("./blob").isSupported; + + function getWorkingXHR(globalScope) { + var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined"; + if (supportsXHR) { + return globalScope.XMLHttpRequest; + } + + var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined"; + if (supportsActiveX) { + return function() { + return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0"); + }; + } + + return false; + } + + // Ref: https://fetch.spec.whatwg.org/#forbidden-header-name + var unsafeHeaders = { + "Accept-Charset": true, + "Access-Control-Request-Headers": true, + "Access-Control-Request-Method": true, + "Accept-Encoding": true, + Connection: true, + "Content-Length": true, + Cookie: true, + Cookie2: true, + "Content-Transfer-Encoding": true, + Date: true, + DNT: true, + Expect: true, + Host: true, + "Keep-Alive": true, + Origin: true, + Referer: true, + TE: true, + Trailer: true, + "Transfer-Encoding": true, + Upgrade: true, + "User-Agent": true, + Via: true + }; + + function EventTargetHandler() { + var self = this; + var events = [ + "loadstart", + "progress", + "abort", + "error", + "load", + "timeout", + "loadend" + ]; + + function addEventListener(eventName) { + self.addEventListener(eventName, function(event) { + var listener = self[`on${eventName}`]; + + if (listener && typeof listener === "function") { + listener.call(this, event); + } + }); + } + + events.forEach(addEventListener); + } + + EventTargetHandler.prototype = sinonEvent.EventTarget; + + function normalizeHeaderValue(value) { + // Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes + /*eslint no-control-regex: "off"*/ + return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g, ""); + } + + function getHeader(headers, header) { + var foundHeader = Object.keys(headers).filter(function(h) { + return h.toLowerCase() === header.toLowerCase(); + }); + + return foundHeader[0] || null; + } + + function excludeSetCookie2Header(header) { + return !/^Set-Cookie2?$/i.test(header); + } + + function verifyResponseBodyType(body, responseType) { + var error = null; + var isString = typeof body === "string"; + + if (responseType === "arraybuffer") { + if (!isString && !(body instanceof ArrayBuffer)) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string or ArrayBuffer.` + ); + error.name = "InvalidBodyException"; + } + } else if (responseType === "blob") { + if ( + !isString && + !(body instanceof ArrayBuffer) && + supportsBlob && + !(body instanceof Blob) + ) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string, ArrayBuffer, or Blob.` + ); + error.name = "InvalidBodyException"; + } + } else if (!isString) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string.` + ); + error.name = "InvalidBodyException"; + } + + if (error) { + throw error; + } + } + + function convertToArrayBuffer(body, encoding) { + if (body instanceof ArrayBuffer) { + return body; + } + + return new GlobalTextEncoder(encoding || "utf-8").encode(body).buffer; + } + + function isXmlContentType(contentType) { + return ( + !contentType || + /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType) + ); + } + + function clearResponse(xhr) { + if (xhr.responseType === "" || xhr.responseType === "text") { + xhr.response = xhr.responseText = ""; + } else { + xhr.response = xhr.responseText = null; + } + xhr.responseXML = null; + } + + function fakeXMLHttpRequestFor(globalScope) { + var isReactNative = + globalScope.navigator && + globalScope.navigator.product === "ReactNative"; + var sinonXhr = { XMLHttpRequest: globalScope.XMLHttpRequest }; + sinonXhr.GlobalXMLHttpRequest = globalScope.XMLHttpRequest; + sinonXhr.GlobalActiveXObject = globalScope.ActiveXObject; + sinonXhr.supportsActiveX = + typeof sinonXhr.GlobalActiveXObject !== "undefined"; + sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined"; + sinonXhr.workingXHR = getWorkingXHR(globalScope); + sinonXhr.supportsTimeout = + sinonXhr.supportsXHR && + "timeout" in new sinonXhr.GlobalXMLHttpRequest(); + sinonXhr.supportsCORS = + isReactNative || + (sinonXhr.supportsXHR && + "withCredentials" in new sinonXhr.GlobalXMLHttpRequest()); + + // Note that for FakeXMLHttpRequest to work pre ES5 + // we lose some of the alignment with the spec. + // To ensure as close a match as possible, + // set responseType before calling open, send or respond; + function FakeXMLHttpRequest(config) { + EventTargetHandler.call(this); + this.readyState = FakeXMLHttpRequest.UNSENT; + this.requestHeaders = {}; + this.requestBody = null; + this.status = 0; + this.statusText = ""; + this.upload = new EventTargetHandler(); + this.responseType = ""; + this.response = ""; + this.logError = configureLogError(config); + + if (sinonXhr.supportsTimeout) { + this.timeout = 0; + } + + if (sinonXhr.supportsCORS) { + this.withCredentials = false; + } + + if (typeof FakeXMLHttpRequest.onCreate === "function") { + FakeXMLHttpRequest.onCreate(this); + } + } + + function verifyState(xhr) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { + throw new Error("INVALID_STATE_ERR"); + } + + if (xhr.sendFlag) { + throw new Error("INVALID_STATE_ERR"); + } + } + + // largest arity in XHR is 5 - XHR#open + var apply = function(obj, method, args) { + switch (args.length) { + case 0: + return obj[method](); + case 1: + return obj[method](args[0]); + case 2: + return obj[method](args[0], args[1]); + case 3: + return obj[method](args[0], args[1], args[2]); + case 4: + return obj[method](args[0], args[1], args[2], args[3]); + case 5: + return obj[method](args[0], args[1], args[2], args[3], args[4]); + default: + throw new Error("Unhandled case"); + } + }; + + FakeXMLHttpRequest.filters = []; + FakeXMLHttpRequest.addFilter = function addFilter(fn) { + this.filters.push(fn); + }; + FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) { + var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap + + [ + "open", + "setRequestHeader", + "abort", + "getResponseHeader", + "getAllResponseHeaders", + "addEventListener", + "overrideMimeType", + "removeEventListener" + ].forEach(function(method) { + fakeXhr[method] = function() { + return apply(xhr, method, arguments); + }; + }); + + fakeXhr.send = function() { + // Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute + if (xhr.responseType !== fakeXhr.responseType) { + xhr.responseType = fakeXhr.responseType; + } + return apply(xhr, "send", arguments); + }; + + var copyAttrs = function(args) { + args.forEach(function(attr) { + fakeXhr[attr] = xhr[attr]; + }); + }; + + var stateChangeStart = function() { + fakeXhr.readyState = xhr.readyState; + if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) { + copyAttrs(["status", "statusText"]); + } + if (xhr.readyState >= FakeXMLHttpRequest.LOADING) { + copyAttrs(["response"]); + if (xhr.responseType === "" || xhr.responseType === "text") { + copyAttrs(["responseText"]); + } + } + if ( + xhr.readyState === FakeXMLHttpRequest.DONE && + (xhr.responseType === "" || xhr.responseType === "document") + ) { + copyAttrs(["responseXML"]); + } + }; + + var stateChangeEnd = function() { + if (fakeXhr.onreadystatechange) { + // eslint-disable-next-line no-useless-call + fakeXhr.onreadystatechange.call(fakeXhr, { + target: fakeXhr, + currentTarget: fakeXhr + }); + } + }; + + var stateChange = function stateChange() { + stateChangeStart(); + stateChangeEnd(); + }; + + if (xhr.addEventListener) { + xhr.addEventListener("readystatechange", stateChangeStart); + + Object.keys(fakeXhr.eventListeners).forEach(function(event) { + /*eslint-disable no-loop-func*/ + fakeXhr.eventListeners[event].forEach(function(handler) { + xhr.addEventListener(event, handler.listener, { + capture: handler.capture, + once: handler.once + }); + }); + /*eslint-enable no-loop-func*/ + }); + + xhr.addEventListener("readystatechange", stateChangeEnd); + } else { + xhr.onreadystatechange = stateChange; + } + apply(xhr, "open", xhrArgs); + }; + FakeXMLHttpRequest.useFilters = false; + + function verifyRequestOpened(xhr) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { + const errorMessage = + xhr.readyState === FakeXMLHttpRequest.UNSENT + ? "INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first..." + : `INVALID_STATE_ERR - ${xhr.readyState}`; + throw new Error(errorMessage); + } + } + + function verifyRequestSent(xhr) { + if (xhr.readyState === FakeXMLHttpRequest.DONE) { + throw new Error("Request done"); + } + } + + function verifyHeadersReceived(xhr) { + if ( + xhr.async && + xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED + ) { + throw new Error("No headers received"); + } + } + + function convertResponseBody(responseType, contentType, body) { + if (responseType === "" || responseType === "text") { + return body; + } else if (supportsArrayBuffer && responseType === "arraybuffer") { + return convertToArrayBuffer(body); + } else if (responseType === "json") { + try { + return JSON.parse(body); + } catch (e) { + // Return parsing failure as null + return null; + } + } else if (supportsBlob && responseType === "blob") { + if (body instanceof Blob) { + return body; + } + + var blobOptions = {}; + if (contentType) { + blobOptions.type = contentType; + } + return new Blob([convertToArrayBuffer(body)], blobOptions); + } else if (responseType === "document") { + if (isXmlContentType(contentType)) { + return FakeXMLHttpRequest.parseXML(body); + } + return null; + } + throw new Error(`Invalid responseType ${responseType}`); + } + + /** + * Steps to follow when there is an error, according to: + * https://xhr.spec.whatwg.org/#request-error-steps + */ + function requestErrorSteps(xhr) { + clearResponse(xhr); + xhr.errorFlag = true; + xhr.requestHeaders = {}; + xhr.responseHeaders = {}; + + if ( + xhr.readyState !== FakeXMLHttpRequest.UNSENT && + xhr.sendFlag && + xhr.readyState !== FakeXMLHttpRequest.DONE + ) { + xhr.readyStateChange(FakeXMLHttpRequest.DONE); + xhr.sendFlag = false; + } + } + + FakeXMLHttpRequest.parseXML = function parseXML(text) { + // Treat empty string as parsing failure + if (text !== "") { + try { + if (typeof DOMParser !== "undefined") { + var parser = new DOMParser(); + var parsererrorNS = ""; + + try { + var parsererrors = parser + .parseFromString("INVALID", "text/xml") + .getElementsByTagName("parsererror"); + if (parsererrors.length) { + parsererrorNS = parsererrors[0].namespaceURI; + } + } catch (e) { + // passing invalid XML makes IE11 throw + // so no namespace needs to be determined + } + + var result; + try { + result = parser.parseFromString(text, "text/xml"); + } catch (err) { + return null; + } + + return result.getElementsByTagNameNS( + parsererrorNS, + "parsererror" + ).length + ? null + : result; + } + var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(text); + return xmlDoc.parseError.errorCode !== 0 ? null : xmlDoc; + } catch (e) { + // Unable to parse XML - no biggie + } + } + + return null; + }; + + FakeXMLHttpRequest.statusCodes = { + 100: "Continue", + 101: "Switching Protocols", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 300: "Multiple Choice", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 307: "Temporary Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported" + }; + + extend(FakeXMLHttpRequest.prototype, sinonEvent.EventTarget, { + async: true, + + open: function open(method, url, async, username, password) { + this.method = method; + this.url = url; + this.async = typeof async === "boolean" ? async : true; + this.username = username; + this.password = password; + clearResponse(this); + this.requestHeaders = {}; + this.sendFlag = false; + + if (FakeXMLHttpRequest.useFilters === true) { + var xhrArgs = arguments; + var defake = FakeXMLHttpRequest.filters.some(function(filter) { + return filter.apply(this, xhrArgs); + }); + if (defake) { + FakeXMLHttpRequest.defake(this, arguments); + return; + } + } + this.readyStateChange(FakeXMLHttpRequest.OPENED); + }, + + readyStateChange: function readyStateChange(state) { + this.readyState = state; + + var readyStateChangeEvent = new sinonEvent.Event( + "readystatechange", + false, + false, + this + ); + if (typeof this.onreadystatechange === "function") { + try { + this.onreadystatechange(readyStateChangeEvent); + } catch (e) { + this.logError("Fake XHR onreadystatechange handler", e); + } + } + + if (this.readyState !== FakeXMLHttpRequest.DONE) { + this.dispatchEvent(readyStateChangeEvent); + } else { + var event, progress; + + if (this.timedOut || this.aborted || this.status === 0) { + progress = { loaded: 0, total: 0 }; + event = + (this.timedOut && "timeout") || + (this.aborted && "abort") || + "error"; + } else { + progress = { loaded: 100, total: 100 }; + event = "load"; + } + + if (supportsProgress) { + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent("progress", progress, this) + ); + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent(event, progress, this) + ); + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent("loadend", progress, this) + ); + } + + this.dispatchEvent( + new sinonEvent.ProgressEvent("progress", progress, this) + ); + this.dispatchEvent( + new sinonEvent.ProgressEvent(event, progress, this) + ); + this.dispatchEvent(readyStateChangeEvent); + this.dispatchEvent( + new sinonEvent.ProgressEvent("loadend", progress, this) + ); + } + }, + + // Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method + setRequestHeader: function setRequestHeader(header, value) { + if (typeof value !== "string") { + throw new TypeError( + `By RFC7230, section 3.2.4, header values should be strings. Got ${typeof value}` + ); + } + verifyState(this); + + var checkUnsafeHeaders = true; + if (typeof this.unsafeHeadersEnabled === "function") { + checkUnsafeHeaders = this.unsafeHeadersEnabled(); + } + + if ( + checkUnsafeHeaders && + (getHeader(unsafeHeaders, header) !== null || + /^(Sec-|Proxy-)/i.test(header)) + ) { + throw new Error( + // eslint-disable-next-line quotes + `Refused to set unsafe header "${header}"` + ); + } + + // eslint-disable-next-line no-param-reassign + value = normalizeHeaderValue(value); + + var existingHeader = getHeader(this.requestHeaders, header); + if (existingHeader) { + this.requestHeaders[existingHeader] += `, ${value}`; + } else { + this.requestHeaders[header] = value; + } + }, + + setStatus: function setStatus(status) { + var sanitizedStatus = typeof status === "number" ? status : 200; + + verifyRequestOpened(this); + this.status = sanitizedStatus; + this.statusText = FakeXMLHttpRequest.statusCodes[sanitizedStatus]; + }, + + // Helps testing + setResponseHeaders: function setResponseHeaders(headers) { + verifyRequestOpened(this); + + var responseHeaders = (this.responseHeaders = {}); + + Object.keys(headers).forEach(function(header) { + responseHeaders[header] = headers[header]; + }); + + if (this.async) { + this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); + } else { + this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; + } + }, + + // Currently treats ALL data as a DOMString (i.e. no Document) + send: function send(data) { + verifyState(this); + + if (!/^(head)$/i.test(this.method)) { + var contentType = getHeader( + this.requestHeaders, + "Content-Type" + ); + if (this.requestHeaders[contentType]) { + var value = this.requestHeaders[contentType].split(";"); + this.requestHeaders[ + contentType + ] = `${value[0]};charset=utf-8`; + } else if (supportsFormData && !(data instanceof FormData)) { + this.requestHeaders["Content-Type"] = + "text/plain;charset=utf-8"; + } + + this.requestBody = data; + } + + this.errorFlag = false; + this.sendFlag = this.async; + clearResponse(this); + + if (typeof this.onSend === "function") { + this.onSend(this); + } + + // Only listen if setInterval and Date are a stubbed. + if ( + sinonXhr.supportsTimeout && + typeof setInterval.clock === "object" && + typeof Date.clock === "object" + ) { + var initiatedTime = Date.now(); + var self = this; + + // Listen to any possible tick by fake timers and check to see if timeout has + // been exceeded. It's important to note that timeout can be changed while a request + // is in flight, so we must check anytime the end user forces a clock tick to make + // sure timeout hasn't changed. + // https://xhr.spec.whatwg.org/#dfnReturnLink-2 + var clearIntervalId = setInterval(function() { + // Check if the readyState has been reset or is done. If this is the case, there + // should be no timeout. This will also prevent aborted requests and + // fakeServerWithClock from triggering unnecessary responses. + if ( + self.readyState === FakeXMLHttpRequest.UNSENT || + self.readyState === FakeXMLHttpRequest.DONE + ) { + clearInterval(clearIntervalId); + } else if ( + typeof self.timeout === "number" && + self.timeout > 0 + ) { + if (Date.now() >= initiatedTime + self.timeout) { + self.triggerTimeout(); + clearInterval(clearIntervalId); + } + } + }, 1); + } + + this.dispatchEvent( + new sinonEvent.Event("loadstart", false, false, this) + ); + }, + + abort: function abort() { + this.aborted = true; + requestErrorSteps(this); + this.readyState = FakeXMLHttpRequest.UNSENT; + }, + + error: function() { + clearResponse(this); + this.errorFlag = true; + this.requestHeaders = {}; + this.responseHeaders = {}; + + this.readyStateChange(FakeXMLHttpRequest.DONE); + }, + + triggerTimeout: function triggerTimeout() { + if (sinonXhr.supportsTimeout) { + this.timedOut = true; + requestErrorSteps(this); + } + }, + + getResponseHeader: function getResponseHeader(header) { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return null; + } + + if (/^Set-Cookie2?$/i.test(header)) { + return null; + } + + // eslint-disable-next-line no-param-reassign + header = getHeader(this.responseHeaders, header); + + return this.responseHeaders[header] || null; + }, + + getAllResponseHeaders: function getAllResponseHeaders() { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return ""; + } + + var responseHeaders = this.responseHeaders; + var headers = Object.keys(responseHeaders) + .filter(excludeSetCookie2Header) + .reduce(function(prev, header) { + var value = responseHeaders[header]; + + return `${prev}${header}: ${value}\r\n`; + }, ""); + + return headers; + }, + + setResponseBody: function setResponseBody(body) { + verifyRequestSent(this); + verifyHeadersReceived(this); + verifyResponseBodyType(body, this.responseType); + var contentType = + this.overriddenMimeType || + this.getResponseHeader("Content-Type"); + + var isTextResponse = + this.responseType === "" || this.responseType === "text"; + clearResponse(this); + if (this.async) { + var chunkSize = this.chunkSize || 10; + var index = 0; + + do { + this.readyStateChange(FakeXMLHttpRequest.LOADING); + + if (isTextResponse) { + this.responseText = this.response += body.substring( + index, + index + chunkSize + ); + } + index += chunkSize; + } while (index < body.length); + } + + this.response = convertResponseBody( + this.responseType, + contentType, + body + ); + if (isTextResponse) { + this.responseText = this.response; + } + + if (this.responseType === "document") { + this.responseXML = this.response; + } else if ( + this.responseType === "" && + isXmlContentType(contentType) + ) { + this.responseXML = FakeXMLHttpRequest.parseXML( + this.responseText + ); + } + this.readyStateChange(FakeXMLHttpRequest.DONE); + }, + + respond: function respond(status, headers, body) { + this.responseURL = this.url; + + this.setStatus(status); + this.setResponseHeaders(headers || {}); + this.setResponseBody(body || ""); + }, + + uploadProgress: function uploadProgress(progressEventRaw) { + if (supportsProgress) { + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent( + "progress", + progressEventRaw, + this.upload + ) + ); + } + }, + + downloadProgress: function downloadProgress(progressEventRaw) { + if (supportsProgress) { + this.dispatchEvent( + new sinonEvent.ProgressEvent( + "progress", + progressEventRaw, + this + ) + ); + } + }, + + uploadError: function uploadError(error) { + if (supportsCustomEvent) { + this.upload.dispatchEvent( + new sinonEvent.CustomEvent("error", { detail: error }) + ); + } + }, + + overrideMimeType: function overrideMimeType(type) { + if (this.readyState >= FakeXMLHttpRequest.LOADING) { + throw new Error("INVALID_STATE_ERR"); + } + this.overriddenMimeType = type; + } + }); + + var states = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4 + }; + + extend(FakeXMLHttpRequest, states); + extend(FakeXMLHttpRequest.prototype, states); + + function useFakeXMLHttpRequest() { + FakeXMLHttpRequest.restore = function restore(keepOnCreate) { + if (sinonXhr.supportsXHR) { + globalScope.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest; + } + + if (sinonXhr.supportsActiveX) { + globalScope.ActiveXObject = sinonXhr.GlobalActiveXObject; + } + + delete FakeXMLHttpRequest.restore; + + if (keepOnCreate !== true) { + delete FakeXMLHttpRequest.onCreate; + } + }; + if (sinonXhr.supportsXHR) { + globalScope.XMLHttpRequest = FakeXMLHttpRequest; + } + + if (sinonXhr.supportsActiveX) { + globalScope.ActiveXObject = function ActiveXObject(objId) { + if ( + objId === "Microsoft.XMLHTTP" || + /^Msxml2\.XMLHTTP/i.test(objId) + ) { + return new FakeXMLHttpRequest(); + } + + return new sinonXhr.GlobalActiveXObject(objId); + }; + } + + return FakeXMLHttpRequest; + } + + return { + xhr: sinonXhr, + FakeXMLHttpRequest: FakeXMLHttpRequest, + useFakeXMLHttpRequest: useFakeXMLHttpRequest + }; + } + + module.exports = extend(fakeXMLHttpRequestFor(globalObject), { + fakeXMLHttpRequestFor: fakeXMLHttpRequestFor + }); + + },{"../configure-logger":116,"../event":120,"./blob":125,"@sinonjs/commons":134,"@sinonjs/text-encoding":107,"just-extend":114}],127:[function(require,module,exports){ + + module.exports = { + fakeServer: require("./fake-server"), + fakeServerWithClock: require("./fake-server/fake-server-with-clock"), + fakeXhr: require("./fake-xhr") + }; + + },{"./fake-server":123,"./fake-server/fake-server-with-clock":122,"./fake-xhr":126}],128:[function(require,module,exports){ + arguments[4][41][0].apply(exports,arguments); + },{"./prototypes/array":136,"dup":41}],129:[function(require,module,exports){ + arguments[4][42][0].apply(exports,arguments); + },{"./function-name":132,"dup":42}],130:[function(require,module,exports){ + arguments[4][43][0].apply(exports,arguments); + },{"dup":43}],131:[function(require,module,exports){ + arguments[4][44][0].apply(exports,arguments); + },{"dup":44}],132:[function(require,module,exports){ + arguments[4][45][0].apply(exports,arguments); + },{"dup":45}],133:[function(require,module,exports){ + arguments[4][46][0].apply(exports,arguments); + },{"dup":46}],134:[function(require,module,exports){ + arguments[4][47][0].apply(exports,arguments); + },{"./called-in-order":128,"./class-name":129,"./deprecated":130,"./every":131,"./function-name":132,"./global":133,"./order-by-first-call":135,"./prototypes":139,"./type-of":145,"./value-to-string":146,"dup":47}],135:[function(require,module,exports){ + arguments[4][48][0].apply(exports,arguments); + },{"./prototypes/array":136,"dup":48}],136:[function(require,module,exports){ + arguments[4][49][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":49}],137:[function(require,module,exports){ + arguments[4][50][0].apply(exports,arguments); + },{"./throws-on-proto":144,"dup":50}],138:[function(require,module,exports){ + arguments[4][51][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":51}],139:[function(require,module,exports){ + arguments[4][52][0].apply(exports,arguments); + },{"./array":136,"./function":138,"./map":140,"./object":141,"./set":142,"./string":143,"dup":52}],140:[function(require,module,exports){ + arguments[4][53][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":53}],141:[function(require,module,exports){ + arguments[4][54][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":54}],142:[function(require,module,exports){ + arguments[4][55][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":55}],143:[function(require,module,exports){ + arguments[4][56][0].apply(exports,arguments); + },{"./copy-prototype-methods":137,"dup":56}],144:[function(require,module,exports){ + arguments[4][57][0].apply(exports,arguments); + },{"dup":57}],145:[function(require,module,exports){ + arguments[4][58][0].apply(exports,arguments); + },{"dup":58,"type-detect":150}],146:[function(require,module,exports){ + arguments[4][59][0].apply(exports,arguments); + },{"dup":59}],147:[function(require,module,exports){ + var isarray = require('isarray'); + + /** + * Expose `pathToRegexp`. + */ + module.exports = pathToRegexp; + module.exports.parse = parse; + module.exports.compile = compile; + module.exports.tokensToFunction = tokensToFunction; + module.exports.tokensToRegExp = tokensToRegExp; + + /** + * The main path matching regexp utility. + * + * @type {RegExp} + */ + var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' + ].join('|'), 'g'); + + /** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */ + function parse (str, options) { + var tokens = []; + var key = 0; + var index = 0; + var path = ''; + var defaultDelimiter = options && options.delimiter || '/'; + var res; + + while ((res = PATH_REGEXP.exec(str)) != null) { + var m = res[0]; + var escaped = res[1]; + var offset = res.index; + path += str.slice(index, offset); + index = offset + m.length; + + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1]; + continue + } + + var next = str[index]; + var prefix = res[2]; + var name = res[3]; + var capture = res[4]; + var group = res[5]; + var modifier = res[6]; + var asterisk = res[7]; + + // Push the current path onto the tokens. + if (path) { + tokens.push(path); + path = ''; + } + + var partial = prefix != null && next != null && next !== prefix; + var repeat = modifier === '+' || modifier === '*'; + var optional = modifier === '?' || modifier === '*'; + var delimiter = res[2] || defaultDelimiter; + var pattern = capture || group; + + tokens.push({ + name: name || key++, + prefix: prefix || '', + delimiter: delimiter, + optional: optional, + repeat: repeat, + partial: partial, + asterisk: !!asterisk, + pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') + }); + } + + // Match any characters still remaining. + if (index < str.length) { + path += str.substr(index); + } + + // If the path exists, push it onto the end. + if (path) { + tokens.push(path); + } + + return tokens + } + + /** + * Compile a string to a template function for the path. + * + * @param {string} str + * @param {Object=} options + * @return {!function(Object=, Object=)} + */ + function compile (str, options) { + return tokensToFunction(parse(str, options), options) + } + + /** + * Prettier encoding of URI path segments. + * + * @param {string} + * @return {string} + */ + function encodeURIComponentPretty (str) { + return encodeURI(str).replace(/[\/?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } + + /** + * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. + * + * @param {string} + * @return {string} + */ + function encodeAsterisk (str) { + return encodeURI(str).replace(/[?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } + + /** + * Expose a method for transforming tokens into the path function. + */ + function tokensToFunction (tokens, options) { + // Compile all the tokens into regexps. + var matches = new Array(tokens.length); + + // Compile all the patterns before compilation. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] === 'object') { + matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options)); + } + } + + return function (obj, opts) { + var path = ''; + var data = obj || {}; + var options = opts || {}; + var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (typeof token === 'string') { + path += token; + + continue + } + + var value = data[token.name]; + var segment; + + if (value == null) { + if (token.optional) { + // Prepend partial segment prefixes. + if (token.partial) { + path += token.prefix; + } + + continue + } else { + throw new TypeError('Expected "' + token.name + '" to be defined') + } + } + + if (isarray(value)) { + if (!token.repeat) { + throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') + } + + if (value.length === 0) { + if (token.optional) { + continue + } else { + throw new TypeError('Expected "' + token.name + '" to not be empty') + } + } + + for (var j = 0; j < value.length; j++) { + segment = encode(value[j]); + + if (!matches[i].test(segment)) { + throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') + } + + path += (j === 0 ? token.prefix : token.delimiter) + segment; + } + + continue + } + + segment = token.asterisk ? encodeAsterisk(value) : encode(value); + + if (!matches[i].test(segment)) { + throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') + } + + path += token.prefix + segment; + } + + return path + } + } + + /** + * Escape a regular expression string. + * + * @param {string} str + * @return {string} + */ + function escapeString (str) { + return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') + } + + /** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {string} group + * @return {string} + */ + function escapeGroup (group) { + return group.replace(/([=!:$\/()])/g, '\\$1') + } + + /** + * Attach the keys as a property of the regexp. + * + * @param {!RegExp} re + * @param {Array} keys + * @return {!RegExp} + */ + function attachKeys (re, keys) { + re.keys = keys; + return re + } + + /** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {string} + */ + function flags (options) { + return options && options.sensitive ? '' : 'i' + } + + /** + * Pull out keys from a regexp. + * + * @param {!RegExp} path + * @param {!Array} keys + * @return {!RegExp} + */ + function regexpToRegexp (path, keys) { + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g); + + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + prefix: null, + delimiter: null, + optional: false, + repeat: false, + partial: false, + asterisk: false, + pattern: null + }); + } + } + + return attachKeys(path, keys) + } + + /** + * Transform an array into a regexp. + * + * @param {!Array} path + * @param {Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function arrayToRegexp (path, keys, options) { + var parts = []; + + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source); + } + + var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); + + return attachKeys(regexp, keys) + } + + /** + * Create a path regexp from string input. + * + * @param {string} path + * @param {!Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function stringToRegexp (path, keys, options) { + return tokensToRegExp(parse(path, options), keys, options) + } + + /** + * Expose a function for taking tokens and returning a RegExp. + * + * @param {!Array} tokens + * @param {(Array|Object)=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function tokensToRegExp (tokens, keys, options) { + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys || options); + keys = []; + } + + options = options || {}; + + var strict = options.strict; + var end = options.end !== false; + var route = ''; + + // Iterate over the tokens and create our regexp string. + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (typeof token === 'string') { + route += escapeString(token); + } else { + var prefix = escapeString(token.prefix); + var capture = '(?:' + token.pattern + ')'; + + keys.push(token); + + if (token.repeat) { + capture += '(?:' + prefix + capture + ')*'; + } + + if (token.optional) { + if (!token.partial) { + capture = '(?:' + prefix + '(' + capture + '))?'; + } else { + capture = prefix + '(' + capture + ')?'; + } + } else { + capture = prefix + '(' + capture + ')'; + } + + route += capture; + } + } + + var delimiter = escapeString(options.delimiter || '/'); + var endsWithDelimiter = route.slice(-delimiter.length) === delimiter; + + // In non-strict mode we allow a slash at the end of match. If the path to + // match already ends with a slash, we remove it for consistency. The slash + // is valid at the end of a path match, not in the middle. This is important + // in non-ending mode, where "/test/" shouldn't match "/test//route". + if (!strict) { + route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?'; + } + + if (end) { + route += '$'; + } else { + // In non-ending mode, we need the capturing groups to match as much as + // possible by using a positive lookahead to the end or next path segment. + route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)'; + } + + return attachKeys(new RegExp('^' + route, flags(options)), keys) + } + + /** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(string|RegExp|Array)} path + * @param {(Array|Object)=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function pathToRegexp (path, keys, options) { + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys || options); + keys = []; + } + + options = options || {}; + + if (path instanceof RegExp) { + return regexpToRegexp(path, /** @type {!Array} */ (keys)) + } + + if (isarray(path)) { + return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options) + } + + return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options) + } + + },{"isarray":148}],148:[function(require,module,exports){ + module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; + }; + + },{}],149:[function(require,module,exports){ + module.exports = { + stdout: false, + stderr: false + }; + + },{}],150:[function(require,module,exports){ + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + (global.typeDetect = factory()); + }(this, (function () { + /* ! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + var promiseExists = typeof Promise === 'function'; + + /* eslint-disable no-undef */ + var globalObject = typeof self === 'object' ? self : commonjsGlobal$1; // eslint-disable-line id-blacklist + + var symbolExists = typeof Symbol !== 'undefined'; + var mapExists = typeof Map !== 'undefined'; + var setExists = typeof Set !== 'undefined'; + var weakMapExists = typeof WeakMap !== 'undefined'; + var weakSetExists = typeof WeakSet !== 'undefined'; + var dataViewExists = typeof DataView !== 'undefined'; + var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; + var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; + var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; + var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; + var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); + var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); + var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; + var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); + var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; + var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); + var toStringLeftSliceLength = 8; + var toStringRightSliceLength = -1; + /** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ + function typeDetect(obj) { + /* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */ + var typeofObj = typeof obj; + if (typeofObj !== 'object') { + return typeofObj; + } + + /* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */ + if (obj === null) { + return 'null'; + } + + /* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */ + if (obj === globalObject) { + return 'global'; + } + + /* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) + */ + if ( + Array.isArray(obj) && + (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) + ) { + return 'Array'; + } + + // Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if (typeof window === 'object' && window !== null) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" + */ + if (typeof window.location === 'object' && obj === window.location) { + return 'Location'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */ + if (typeof window.document === 'object' && obj === window.document) { + return 'Document'; + } + + if (typeof window.navigator === 'object') { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */ + if (typeof window.navigator.mimeTypes === 'object' && + obj === window.navigator.mimeTypes) { + return 'MimeTypeArray'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */ + if (typeof window.navigator.plugins === 'object' && + obj === window.navigator.plugins) { + return 'PluginArray'; + } + } + + if ((typeof window.HTMLElement === 'function' || + typeof window.HTMLElement === 'object') && + obj instanceof window.HTMLElement) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */ + if (obj.tagName === 'BLOCKQUOTE') { + return 'HTMLQuoteElement'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TD') { + return 'HTMLTableDataCellElement'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TH') { + return 'HTMLTableHeaderCellElement'; + } + } + } + + /* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */ + var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); + if (typeof stringTag === 'string') { + return stringTag; + } + + var objPrototype = Object.getPrototypeOf(obj); + /* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */ + if (objPrototype === RegExp.prototype) { + return 'RegExp'; + } + + /* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */ + if (objPrototype === Date.prototype) { + return 'Date'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */ + if (promiseExists && objPrototype === Promise.prototype) { + return 'Promise'; + } + + /* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */ + if (setExists && objPrototype === Set.prototype) { + return 'Set'; + } + + /* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */ + if (mapExists && objPrototype === Map.prototype) { + return 'Map'; + } + + /* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */ + if (weakSetExists && objPrototype === WeakSet.prototype) { + return 'WeakSet'; + } + + /* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */ + if (weakMapExists && objPrototype === WeakMap.prototype) { + return 'WeakMap'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */ + if (dataViewExists && objPrototype === DataView.prototype) { + return 'DataView'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */ + if (mapExists && objPrototype === mapIteratorPrototype) { + return 'Map Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" + */ + if (setExists && objPrototype === setIteratorPrototype) { + return 'Set Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { + return 'Array Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (stringIteratorExists && objPrototype === stringIteratorPrototype) { + return 'String Iterator'; + } + + /* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */ + if (objPrototype === null) { + return 'Object'; + } + + return Object + .prototype + .toString + .call(obj) + .slice(toStringLeftSliceLength, toStringRightSliceLength); + } + + return typeDetect; + + }))); + + },{}]},{},[1])(1) + }); + + + } (sinon$3, sinon$3.exports)); + + var sinonExports = sinon$3.exports; + var sinon$2 = /*@__PURE__*/getDefaultExportFromCjs(sinonExports); + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } - function exposedName(prefix, prop) { - return !prefix || /^fail/.test(prop) - ? prop - : prefix + - stringSlice(prop, 0, 1).toUpperCase() + - stringSlice(prop, 1); - } + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } - mirrorPropAsAssertion( - "called", - "expected %n to have been called at least once but was never called" - ); - mirrorPropAsAssertion( - "notCalled", - function (spy) { - return !spy.called; - }, - "expected %n to not have been called but was called %c%C" - ); - mirrorPropAsAssertion( - "calledOnce", - "expected %n to be called once but was called %c%C" - ); - mirrorPropAsAssertion( - "calledTwice", - "expected %n to be called twice but was called %c%C" - ); - mirrorPropAsAssertion( - "calledThrice", - "expected %n to be called thrice but was called %c%C" - ); - mirrorPropAsAssertion( - "calledOn", - "expected %n to be called with %1 as this but was called with %t" - ); - mirrorPropAsAssertion( - "alwaysCalledOn", - "expected %n to always be called with %1 as this but was called with %t" - ); - mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new"); - mirrorPropAsAssertion( - "alwaysCalledWithNew", - "expected %n to always be called with new" - ); - mirrorPropAsAssertion( - "calledWith", - "expected %n to be called with arguments %D" - ); - mirrorPropAsAssertion( - "calledWithMatch", - "expected %n to be called with match %D" - ); - mirrorPropAsAssertion( - "alwaysCalledWith", - "expected %n to always be called with arguments %D" - ); - mirrorPropAsAssertion( - "alwaysCalledWithMatch", - "expected %n to always be called with match %D" - ); - mirrorPropAsAssertion( - "calledWithExactly", - "expected %n to be called with exact arguments %D" - ); - mirrorPropAsAssertion( - "calledOnceWithExactly", - "expected %n to be called once and with exact arguments %D" - ); - mirrorPropAsAssertion( - "calledOnceWithMatch", - "expected %n to be called once and with match %D" - ); - mirrorPropAsAssertion( - "alwaysCalledWithExactly", - "expected %n to always be called with exact arguments %D" - ); - mirrorPropAsAssertion( - "neverCalledWith", - "expected %n to never be called with arguments %*%C" - ); - mirrorPropAsAssertion( - "neverCalledWithMatch", - "expected %n to never be called with match %*%C" - ); - mirrorPropAsAssertion("threw", "%n did not throw exception%C"); - mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C"); + /** + * Helpers. + */ - return assert; + var s = 1000; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var w = d * 7; + var y = d * 365.25; + + /** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + + var ms = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); + }; + + /** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + + function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } } - module.exports = createAssertObject(); - module.exports.createAssertObject = createAssertObject; + /** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ - },{"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],4:[function(require,module,exports){ + function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; + } - const arrayProto = require("@sinonjs/commons").prototypes.array; - const extend = require("./util/core/extend"); - const functionName = require("@sinonjs/commons").functionName; - const nextTick = require("./util/core/next-tick"); - const valueToString = require("@sinonjs/commons").valueToString; - const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); + /** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ - const concat = arrayProto.concat; - const join = arrayProto.join; - const reverse = arrayProto.reverse; - const slice = arrayProto.slice; + function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; + } - const useLeftMostCallback = -1; - const useRightMostCallback = -2; + /** + * Pluralization helper. + */ - function getCallback(behavior, args) { - const callArgAt = behavior.callArgAt; + function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); + } - if (callArgAt >= 0) { - return args[callArgAt]; - } + /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ - let argumentList; + function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = ms; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * Active `debug` instances. + */ + createDebug.instances = []; + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; + // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + + // env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + createDebug.instances.push(debug); + + return debug; + } + + function destroy() { + const index = createDebug.instances.indexOf(this); + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } + return false; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < createDebug.instances.length; i++) { + const instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + createDebug.enable(createDebug.load()); + + return createDebug; + } - if (callArgAt === useLeftMostCallback) { - argumentList = args; - } + var common = setup; - if (callArgAt === useRightMostCallback) { - argumentList = reverse(slice(args)); - } + var browser = createCommonjsModule(function (module, exports) { + /* eslint-env browser */ - const callArgProp = behavior.callArgProp; + /** + * This is the web browser implementation of `debug()`. + */ - for (let i = 0, l = argumentList.length; i < l; ++i) { - if (!callArgProp && typeof argumentList[i] === "function") { - return argumentList[i]; - } + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + exports.storage = localstorage(); - if ( - callArgProp && - argumentList[i] && - typeof argumentList[i][callArgProp] === "function" - ) { - return argumentList[i][callArgProp]; - } - } + /** + * Colors. + */ - return null; + exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' + ]; + + /** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + + // eslint-disable-next-line complexity + function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } - function getCallbackError(behavior, func, args) { - if (behavior.callArgAt < 0) { - let msg; + /** + * Colorize log arguments if enabled. + * + * @api public + */ - if (behavior.callArgProp) { - msg = `${functionName( - behavior.stub - )} expected to yield to '${valueToString( - behavior.callArgProp - )}', but no object with such a property was passed.`; - } else { - msg = `${functionName( - behavior.stub - )} expected to yield, but no callback was passed.`; - } + function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + } - if (args.length > 0) { - msg += ` Received [${join(args, ", ")}]`; - } + /** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + function log(...args) { + // This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return typeof console === 'object' && + console.log && + console.log(...args); + } - return msg; - } + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + } - return `argument at index ${behavior.callArgAt} is not a function: ${func}`; + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; } - function ensureArgs(name, behavior, args) { - // map function name to internal property - // callsArg => callArgAt - const property = name.replace(/sArg/, "ArgAt"); - const index = behavior[property]; + /** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ - if (index >= args.length) { - throw new TypeError( - `${name} failed: ${index + 1} arguments required but only ${ - args.length - } present` - ); - } + function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } } - function callCallback(behavior, args) { - if (typeof behavior.callArgAt === "number") { - ensureArgs("callsArg", behavior, args); - const func = getCallback(behavior, args); + module.exports = common(exports); - if (typeof func !== "function") { - throw new TypeError(getCallbackError(behavior, func, args)); - } + const {formatters} = module.exports; - if (behavior.callbackAsync) { - nextTick(function () { - func.apply( - behavior.callbackContext, - behavior.callbackArguments - ); - }); + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + + formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } + }; + }); + browser.log; + browser.formatArgs; + browser.save; + browser.load; + browser.useColors; + browser.storage; + browser.colors; + + let debugFunc; + let phase = 'default'; + let namespace = ''; + const newDebug = () => { + debugFunc = namespace + ? browser(`fetch-mock:${phase}:${namespace}`) + : browser(`fetch-mock:${phase}`); + }; + + const newDebugSandbox = ns => browser(`fetch-mock:${phase}:${ns}`); + + newDebug(); + + var debug_1 = { + debug: (...args) => { + debugFunc(...args); + }, + setDebugNamespace: str => { + namespace = str; + newDebug(); + }, + setDebugPhase: str => { + phase = str || 'default'; + newDebug(); + }, + getDebug: namespace => newDebugSandbox(namespace) + }; + + var globToRegexp = function (glob, opts) { + if (typeof glob !== 'string') { + throw new TypeError('Expected a string'); + } + + var str = String(glob); + + // The regexp we are building, as a string. + var reStr = ""; + + // Whether we are matching so called "extended" globs (like bash) and should + // support single character matching, matching ranges of characters, group + // matching, etc. + var extended = opts ? !!opts.extended : false; + + // When globstar is _false_ (default), '/foo/*' is translated a regexp like + // '^\/foo\/.*$' which will match any string beginning with '/foo/' + // When globstar is _true_, '/foo/*' is translated to regexp like + // '^\/foo\/[^/]*$' which will match any string beginning with '/foo/' BUT + // which does not have a '/' to the right of it. + // E.g. with '/foo/*' these will match: '/foo/bar', '/foo/bar.txt' but + // these will not '/foo/bar/baz', '/foo/bar/baz.txt' + // Lastely, when globstar is _true_, '/foo/**' is equivelant to '/foo/*' when + // globstar is _false_ + var globstar = opts ? !!opts.globstar : false; + + // If we are doing extended matching, this boolean is true when we are inside + // a group (eg {*.html,*.js}), and false otherwise. + var inGroup = false; + + // RegExp flags (eg "i" ) to pass in to RegExp constructor. + var flags = opts && typeof( opts.flags ) === "string" ? opts.flags : ""; + + var c; + for (var i = 0, len = str.length; i < len; i++) { + c = str[i]; + + switch (c) { + case "/": + case "$": + case "^": + case "+": + case ".": + case "(": + case ")": + case "=": + case "!": + case "|": + reStr += "\\" + c; + break; + + case "?": + if (extended) { + reStr += "."; + break; + } + + case "[": + case "]": + if (extended) { + reStr += c; + break; + } + + case "{": + if (extended) { + inGroup = true; + reStr += "("; + break; + } + + case "}": + if (extended) { + inGroup = false; + reStr += ")"; + break; + } + + case ",": + if (inGroup) { + reStr += "|"; + break; + } + reStr += "\\" + c; + break; + + case "*": + // Move over all consecutive "*"'s. + // Also store the previous and next characters + var prevChar = str[i - 1]; + var starCount = 1; + while(str[i + 1] === "*") { + starCount++; + i++; + } + var nextChar = str[i + 1]; + + if (!globstar) { + // globstar is disabled, so treat any number of "*" as one + reStr += ".*"; + } else { + // globstar is enabled, so determine if this is a globstar segment + var isGlobstar = starCount > 1 // multiple "*"'s + && (prevChar === "/" || prevChar === undefined) // from the start of the segment + && (nextChar === "/" || nextChar === undefined); // to the end of the segment + + if (isGlobstar) { + // it's a globstar, so match zero or more path segments + reStr += "((?:[^/]*(?:\/|$))*)"; + i++; // move over the "/" } else { - return func.apply( - behavior.callbackContext, - behavior.callbackArguments - ); + // it's not a globstar, so only match one path segment + reStr += "([^/]*)"; } + } + break; + + default: + reStr += c; } + } - return undefined; - } + // When regexp 'g' flag is specified don't + // constrain the regular expression with ^ & $ + if (!flags || !~flags.indexOf('g')) { + reStr = "^" + reStr + "$"; + } - const proto = { - create: function create(stub) { - const behavior = extend({}, proto); - delete behavior.create; - delete behavior.addBehavior; - delete behavior.createBehavior; - behavior.stub = stub; + return new RegExp(reStr, flags); + }; - if (stub.defaultBehavior && stub.defaultBehavior.promiseLibrary) { - behavior.promiseLibrary = stub.defaultBehavior.promiseLibrary; - } + /** + * Expose `pathToRegexp`. + */ + var pathToRegexp_1 = pathToRegexp; + var parse_1 = parse$1; + var compile_1 = compile; + var tokensToFunction_1 = tokensToFunction; + var tokensToRegExp_1 = tokensToRegExp; - return behavior; - }, + /** + * Default configs. + */ + var DEFAULT_DELIMITER = '/'; + var DEFAULT_DELIMITERS = './'; - isPresent: function isPresent() { - return ( - typeof this.callArgAt === "number" || - this.exception || - this.exceptionCreator || - typeof this.returnArgAt === "number" || - this.returnThis || - typeof this.resolveArgAt === "number" || - this.resolveThis || - typeof this.throwArgAt === "number" || - this.fakeFn || - this.returnValueDefined - ); - }, + /** + * The main path matching regexp utility. + * + * @type {RegExp} + */ + var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // ":test(\\d+)?" => ["test", "\d+", undefined, "?"] + // "(\\d+)" => [undefined, undefined, "\d+", undefined] + '(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?' + ].join('|'), 'g'); - /*eslint complexity: ["error", 20]*/ - invoke: function invoke(context, args) { - /* - * callCallback (conditionally) calls ensureArgs - * - * Note: callCallback intentionally happens before - * everything else and cannot be moved lower - */ - const returnValue = callCallback(this, args); + /** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */ + function parse$1 (str, options) { + var tokens = []; + var key = 0; + var index = 0; + var path = ''; + var defaultDelimiter = (options && options.delimiter) || DEFAULT_DELIMITER; + var delimiters = (options && options.delimiters) || DEFAULT_DELIMITERS; + var pathEscaped = false; + var res; - if (this.exception) { - throw this.exception; - } else if (this.exceptionCreator) { - this.exception = this.exceptionCreator(); - this.exceptionCreator = undefined; - throw this.exception; - } else if (typeof this.returnArgAt === "number") { - ensureArgs("returnsArg", this, args); - return args[this.returnArgAt]; - } else if (this.returnThis) { - return context; - } else if (typeof this.throwArgAt === "number") { - ensureArgs("throwsArg", this, args); - throw args[this.throwArgAt]; - } else if (this.fakeFn) { - return this.fakeFn.apply(context, args); - } else if (typeof this.resolveArgAt === "number") { - ensureArgs("resolvesArg", this, args); - return (this.promiseLibrary || Promise).resolve( - args[this.resolveArgAt] - ); - } else if (this.resolveThis) { - return (this.promiseLibrary || Promise).resolve(context); - } else if (this.resolve) { - return (this.promiseLibrary || Promise).resolve(this.returnValue); - } else if (this.reject) { - return (this.promiseLibrary || Promise).reject(this.returnValue); - } else if (this.callsThrough) { - const wrappedMethod = this.effectiveWrappedMethod(); + while ((res = PATH_REGEXP.exec(str)) !== null) { + var m = res[0]; + var escaped = res[1]; + var offset = res.index; + path += str.slice(index, offset); + index = offset + m.length; - return wrappedMethod.apply(context, args); - } else if (this.callsThroughWithNew) { - // Get the original method (assumed to be a constructor in this case) - const WrappedClass = this.effectiveWrappedMethod(); - // Turn the arguments object into a normal array - const argsArray = slice(args); - // Call the constructor - const F = WrappedClass.bind.apply( - WrappedClass, - concat([null], argsArray) - ); - return new F(); - } else if (typeof this.returnValue !== "undefined") { - return this.returnValue; - } else if (typeof this.callArgAt === "number") { - return returnValue; - } + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1]; + pathEscaped = true; + continue + } - return this.returnValue; - }, + var prev = ''; + var next = str[index]; + var name = res[2]; + var capture = res[3]; + var group = res[4]; + var modifier = res[5]; - effectiveWrappedMethod: function effectiveWrappedMethod() { - for (let stubb = this.stub; stubb; stubb = stubb.parent) { - if (stubb.wrappedMethod) { - return stubb.wrappedMethod; - } - } - throw new Error("Unable to find wrapped method"); - }, + if (!pathEscaped && path.length) { + var k = path.length - 1; - onCall: function onCall(index) { - return this.stub.onCall(index); - }, + if (delimiters.indexOf(path[k]) > -1) { + prev = path[k]; + path = path.slice(0, k); + } + } - onFirstCall: function onFirstCall() { - return this.stub.onFirstCall(); - }, + // Push the current path onto the tokens. + if (path) { + tokens.push(path); + path = ''; + pathEscaped = false; + } - onSecondCall: function onSecondCall() { - return this.stub.onSecondCall(); - }, + var partial = prev !== '' && next !== undefined && next !== prev; + var repeat = modifier === '+' || modifier === '*'; + var optional = modifier === '?' || modifier === '*'; + var delimiter = prev || defaultDelimiter; + var pattern = capture || group; - onThirdCall: function onThirdCall() { - return this.stub.onThirdCall(); - }, + tokens.push({ + name: name || key++, + prefix: prev, + delimiter: delimiter, + optional: optional, + repeat: repeat, + partial: partial, + pattern: pattern ? escapeGroup(pattern) : '[^' + escapeString(delimiter) + ']+?' + }); + } - withArgs: function withArgs(/* arguments */) { - throw new Error( - 'Defining a stub by invoking "stub.onCall(...).withArgs(...)" ' + - 'is not supported. Use "stub.withArgs(...).onCall(...)" ' + - "to define sequential behavior for calls with certain arguments." - ); - }, - }; + // Push any remaining characters. + if (path || index < str.length) { + tokens.push(path + str.substr(index)); + } - function createBehavior(behaviorMethod) { - return function () { - this.defaultBehavior = this.defaultBehavior || proto.create(this); - this.defaultBehavior[behaviorMethod].apply( - this.defaultBehavior, - arguments - ); - return this; - }; + return tokens } - function addBehavior(stub, name, fn) { - proto[name] = function () { - fn.apply(this, concat([this], slice(arguments))); - return this.stub || this; - }; - - stub[name] = createBehavior(name); + /** + * Compile a string to a template function for the path. + * + * @param {string} str + * @param {Object=} options + * @return {!function(Object=, Object=)} + */ + function compile (str, options) { + return tokensToFunction(parse$1(str, options)) } - proto.addBehavior = addBehavior; - proto.createBehavior = createBehavior; + /** + * Expose a method for transforming tokens into the path function. + */ + function tokensToFunction (tokens) { + // Compile all the tokens into regexps. + var matches = new Array(tokens.length); - const asyncBehaviors = exportAsyncBehaviors(proto); + // Compile all the patterns before compilation. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] === 'object') { + matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$'); + } + } - module.exports = extend.nonEnum({}, proto, asyncBehaviors); + return function (data, options) { + var path = ''; + var encode = (options && options.encode) || encodeURIComponent; - },{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/next-tick":34,"@sinonjs/commons":48}],5:[function(require,module,exports){ + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; - const walk = require("./util/core/walk"); - const getPropertyDescriptor = require("./util/core/get-property-descriptor"); - const hasOwnProperty = - require("@sinonjs/commons").prototypes.object.hasOwnProperty; - const push = require("@sinonjs/commons").prototypes.array.push; + if (typeof token === 'string') { + path += token; + continue + } - function collectMethod(methods, object, prop, propOwner) { - if ( - typeof getPropertyDescriptor(propOwner, prop).value === "function" && - hasOwnProperty(object, prop) - ) { - push(methods, object[prop]); - } - } + var value = data ? data[token.name] : undefined; + var segment; - // This function returns an array of all the own methods on the passed object - function collectOwnMethods(object) { - const methods = []; + if (Array.isArray(value)) { + if (!token.repeat) { + throw new TypeError('Expected "' + token.name + '" to not repeat, but got array') + } - walk(object, collectMethod.bind(null, methods, object)); + if (value.length === 0) { + if (token.optional) continue - return methods; - } + throw new TypeError('Expected "' + token.name + '" to not be empty') + } - module.exports = collectOwnMethods; + for (var j = 0; j < value.length; j++) { + segment = encode(value[j], token); - },{"./util/core/get-property-descriptor":29,"./util/core/walk":39,"@sinonjs/commons":48}],6:[function(require,module,exports){ + if (!matches[i].test(segment)) { + throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '"') + } - const supportsColor = require("supports-color"); + path += (j === 0 ? token.prefix : token.delimiter) + segment; + } - function colorize(str, color) { - if (supportsColor.stdout === false) { - return str; - } + continue + } - return `\x1b[${color}m${str}\x1b[0m`; - } + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + segment = encode(String(value), token); - exports.red = function (str) { - return colorize(str, 31); - }; + if (!matches[i].test(segment)) { + throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but got "' + segment + '"') + } - exports.green = function (str) { - return colorize(str, 32); - }; + path += token.prefix + segment; + continue + } - exports.cyan = function (str) { - return colorize(str, 96); - }; + if (token.optional) { + // Prepend partial segment prefixes. + if (token.partial) path += token.prefix; - exports.white = function (str) { - return colorize(str, 39); - }; + continue + } - exports.bold = function (str) { - return colorize(str, 1); - }; + throw new TypeError('Expected "' + token.name + '" to be ' + (token.repeat ? 'an array' : 'a string')) + } - },{"supports-color":150}],7:[function(require,module,exports){ + return path + } + } - const arrayProto = require("@sinonjs/commons").prototypes.array; - const Sandbox = require("./sandbox"); + /** + * Escape a regular expression string. + * + * @param {string} str + * @return {string} + */ + function escapeString (str) { + return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1') + } - const forEach = arrayProto.forEach; - const push = arrayProto.push; + /** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {string} group + * @return {string} + */ + function escapeGroup (group) { + return group.replace(/([=!:$/()])/g, '\\$1') + } - function prepareSandboxFromConfig(config) { - const sandbox = new Sandbox(); + /** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {string} + */ + function flags (options) { + return options && options.sensitive ? '' : 'i' + } - if (config.useFakeServer) { - if (typeof config.useFakeServer === "object") { - sandbox.serverPrototype = config.useFakeServer; - } + /** + * Pull out keys from a regexp. + * + * @param {!RegExp} path + * @param {Array=} keys + * @return {!RegExp} + */ + function regexpToRegexp (path, keys) { + if (!keys) return path - sandbox.useFakeServer(); - } + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g); - if (config.useFakeTimers) { - if (typeof config.useFakeTimers === "object") { - sandbox.useFakeTimers(config.useFakeTimers); - } else { - sandbox.useFakeTimers(); - } + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + prefix: null, + delimiter: null, + optional: false, + repeat: false, + partial: false, + pattern: null + }); } + } - return sandbox; + return path } - function exposeValue(sandbox, config, key, value) { - if (!value) { - return; - } + /** + * Transform an array into a regexp. + * + * @param {!Array} path + * @param {Array=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function arrayToRegexp (path, keys, options) { + var parts = []; - if (config.injectInto && !(key in config.injectInto)) { - config.injectInto[key] = value; - push(sandbox.injectedKeys, key); - } else { - push(sandbox.args, value); - } + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source); + } + + return new RegExp('(?:' + parts.join('|') + ')', flags(options)) } - function createSandbox(config) { - if (!config) { - return new Sandbox(); - } + /** + * Create a path regexp from string input. + * + * @param {string} path + * @param {Array=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function stringToRegexp (path, keys, options) { + return tokensToRegExp(parse$1(path, options), keys, options) + } - const configuredSandbox = prepareSandboxFromConfig(config); - configuredSandbox.args = configuredSandbox.args || []; - configuredSandbox.injectedKeys = []; - configuredSandbox.injectInto = config.injectInto; - const exposed = configuredSandbox.inject({}); + /** + * Expose a function for taking tokens and returning a RegExp. + * + * @param {!Array} tokens + * @param {Array=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function tokensToRegExp (tokens, keys, options) { + options = options || {}; - if (config.properties) { - forEach(config.properties, function (prop) { - const value = - exposed[prop] || (prop === "sandbox" && configuredSandbox); - exposeValue(configuredSandbox, config, prop, value); - }); + var strict = options.strict; + var start = options.start !== false; + var end = options.end !== false; + var delimiter = escapeString(options.delimiter || DEFAULT_DELIMITER); + var delimiters = options.delimiters || DEFAULT_DELIMITERS; + var endsWith = [].concat(options.endsWith || []).map(escapeString).concat('$').join('|'); + var route = start ? '^' : ''; + var isEndDelimited = tokens.length === 0; + + // Iterate over the tokens and create our regexp string. + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (typeof token === 'string') { + route += escapeString(token); + isEndDelimited = i === tokens.length - 1 && delimiters.indexOf(token[token.length - 1]) > -1; } else { - exposeValue(configuredSandbox, config, "sandbox"); + var capture = token.repeat + ? '(?:' + token.pattern + ')(?:' + escapeString(token.delimiter) + '(?:' + token.pattern + '))*' + : token.pattern; + + if (keys) keys.push(token); + + if (token.optional) { + if (token.partial) { + route += escapeString(token.prefix) + '(' + capture + ')?'; + } else { + route += '(?:' + escapeString(token.prefix) + '(' + capture + '))?'; + } + } else { + route += escapeString(token.prefix) + '(' + capture + ')'; + } } + } - return configuredSandbox; + if (end) { + if (!strict) route += '(?:' + delimiter + ')?'; + + route += endsWith === '$' ? '$' : '(?=' + endsWith + ')'; + } else { + if (!strict) route += '(?:' + delimiter + '(?=' + endsWith + '))?'; + if (!isEndDelimited) route += '(?=' + delimiter + '|' + endsWith + ')'; + } + + return new RegExp(route, flags(options)) } - module.exports = createSandbox; + /** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(string|RegExp|Array)} path + * @param {Array=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function pathToRegexp (path, keys, options) { + if (path instanceof RegExp) { + return regexpToRegexp(path, keys) + } - },{"./sandbox":19,"@sinonjs/commons":48}],8:[function(require,module,exports){ + if (Array.isArray(path)) { + return arrayToRegexp(/** @type {!Array} */ (path), keys, options) + } - const stub = require("./stub"); - const sinonType = require("./util/core/sinon-type"); - const forEach = require("@sinonjs/commons").prototypes.array.forEach; + return stringToRegexp(/** @type {string} */ (path), keys, options) + } + pathToRegexp_1.parse = parse_1; + pathToRegexp_1.compile = compile_1; + pathToRegexp_1.tokensToFunction = tokensToFunction_1; + pathToRegexp_1.tokensToRegExp = tokensToRegExp_1; - function isStub(value) { - return sinonType.get(value) === "stub"; + // Copyright Joyent, Inc. and other Node contributors. + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); } - module.exports = function createStubInstance(constructor, overrides) { - if (typeof constructor !== "function") { - throw new TypeError("The constructor should be a function."); - } + var decode = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; - const stubInstance = Object.create(constructor.prototype); - sinonType.set(stubInstance, "stub-instance"); + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } - const stubbedObject = stub(stubInstance); + var regexp = /\+/g; + qs = qs.split(sep); - forEach(Object.keys(overrides || {}), function (propertyName) { - if (propertyName in stubbedObject) { - const value = overrides[propertyName]; - if (isStub(value)) { - stubbedObject[propertyName] = value; - } else { - stubbedObject[propertyName].returns(value); - } - } else { - throw new Error( - `Cannot stub ${propertyName}. Property does not exist!` - ); - } - }); - return stubbedObject; - }; + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } - },{"./stub":22,"./util/core/sinon-type":35,"@sinonjs/commons":48}],9:[function(require,module,exports){ + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } - const arrayProto = require("@sinonjs/commons").prototypes.array; - const isPropertyConfigurable = require("./util/core/is-property-configurable"); - const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); - const extend = require("./util/core/extend"); + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; - const slice = arrayProto.slice; + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } - const useLeftMostCallback = -1; - const useRightMostCallback = -2; + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); - function throwsException(fake, error, message) { - if (typeof error === "function") { - fake.exceptionCreator = error; - } else if (typeof error === "string") { - fake.exceptionCreator = function () { - const newException = new Error( - message || `Sinon-provided ${error}` - ); - newException.name = error; - return newException; - }; - } else if (!error) { - fake.exceptionCreator = function () { - return new Error("Error"); - }; + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (Array.isArray(obj[k])) { + obj[k].push(v); } else { - fake.exception = error; + obj[k] = [obj[k], v]; } - } + } - const defaultBehaviors = { - callsFake: function callsFake(fake, fn) { - fake.fakeFn = fn; - fake.exception = undefined; - fake.exceptionCreator = undefined; - }, + return obj; + }; - callsArg: function callsArg(fake, index) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + // Copyright Joyent, Inc. and other Node contributors. - fake.callArgAt = index; - fake.callbackArguments = []; - fake.callbackContext = undefined; - fake.callArgProp = undefined; - fake.callbackAsync = false; - }, + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; - callsArgOn: function callsArgOn(fake, index, context) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + case 'boolean': + return v ? 'true' : 'false'; - fake.callArgAt = index; - fake.callbackArguments = []; - fake.callbackContext = context; - fake.callArgProp = undefined; - fake.callbackAsync = false; - }, - - callsArgWith: function callsArgWith(fake, index) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + case 'number': + return isFinite(v) ? v : ''; - fake.callArgAt = index; - fake.callbackArguments = slice(arguments, 2); - fake.callbackContext = undefined; - fake.callArgProp = undefined; - fake.callbackAsync = false; - }, - - callsArgOnWith: function callsArgWith(fake, index, context) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + default: + return ''; + } + }; - fake.callArgAt = index; - fake.callbackArguments = slice(arguments, 3); - fake.callbackContext = context; - fake.callArgProp = undefined; - fake.callbackAsync = false; - }, + var encode = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } - usingPromise: function usingPromise(fake, promiseLibrary) { - fake.promiseLibrary = promiseLibrary; - }, + if (typeof obj === 'object') { + return Object.keys(obj).map(function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (Array.isArray(obj[k])) { + return obj[k].map(function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); - yields: function (fake) { - fake.callArgAt = useLeftMostCallback; - fake.callbackArguments = slice(arguments, 1); - fake.callbackContext = undefined; - fake.callArgProp = undefined; - fake.callbackAsync = false; - fake.fakeFn = undefined; - }, + } - yieldsRight: function (fake) { - fake.callArgAt = useRightMostCallback; - fake.callbackArguments = slice(arguments, 1); - fake.callbackContext = undefined; - fake.callArgProp = undefined; - fake.callbackAsync = false; - fake.fakeFn = undefined; - }, + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; - yieldsOn: function (fake, context) { - fake.callArgAt = useLeftMostCallback; - fake.callbackArguments = slice(arguments, 2); - fake.callbackContext = context; - fake.callArgProp = undefined; - fake.callbackAsync = false; - fake.fakeFn = undefined; - }, + var querystring = createCommonjsModule(function (module, exports) { - yieldsTo: function (fake, prop) { - fake.callArgAt = useLeftMostCallback; - fake.callbackArguments = slice(arguments, 2); - fake.callbackContext = undefined; - fake.callArgProp = prop; - fake.callbackAsync = false; - fake.fakeFn = undefined; - }, + exports.decode = exports.parse = decode; + exports.encode = exports.stringify = encode; + }); + querystring.decode; + querystring.parse; + querystring.encode; + querystring.stringify; - yieldsToOn: function (fake, prop, context) { - fake.callArgAt = useLeftMostCallback; - fake.callbackArguments = slice(arguments, 3); - fake.callbackContext = context; - fake.callArgProp = prop; - fake.callbackAsync = false; - fake.fakeFn = undefined; - }, + var isSubset_1 = createCommonjsModule(function (module, exports) { - throws: throwsException, - throwsException: throwsException, + Object.defineProperty(exports, '__esModule', { + value: true + }); + /** + * Check if an object is contained within another object. + * + * Returns `true` if: + * - all enumerable keys of *subset* are also enumerable in *superset*, and + * - every value assigned to an enumerable key of *subset* strictly equals + * the value assigned to the same key of *superset* – or is a subset of it. + * + * @param {Object} superset + * @param {Object} subset + * + * @returns {Boolean} + * + * @module is-subset + * @function default + * @alias isSubset + */ + var isSubset = (function (_isSubset) { + function isSubset(_x, _x2) { + return _isSubset.apply(this, arguments); + } - returns: function returns(fake, value) { - fake.returnValue = value; - fake.resolve = false; - fake.reject = false; - fake.returnValueDefined = true; - fake.exception = undefined; - fake.exceptionCreator = undefined; - fake.fakeFn = undefined; - }, + isSubset.toString = function () { + return _isSubset.toString(); + }; - returnsArg: function returnsArg(fake, index) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + return isSubset; + })(function (superset, subset) { + if (typeof superset !== 'object' || superset === null || (typeof subset !== 'object' || subset === null)) return false; - fake.returnArgAt = index; - }, + return Object.keys(subset).every(function (key) { + if (!superset.propertyIsEnumerable(key)) return false; - throwsArg: function throwsArg(fake, index) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } + var subsetItem = subset[key]; + var supersetItem = superset[key]; + if (typeof subsetItem === 'object' && subsetItem !== null ? !isSubset(supersetItem, subsetItem) : supersetItem !== subsetItem) return false; - fake.throwArgAt = index; - }, + return true; + }); + }); - returnsThis: function returnsThis(fake) { - fake.returnThis = true; - }, + exports['default'] = isSubset; + module.exports = exports['default']; + }); - resolves: function resolves(fake, value) { - fake.returnValue = value; - fake.resolve = true; - fake.resolveThis = false; - fake.reject = false; - fake.returnValueDefined = true; - fake.exception = undefined; - fake.exceptionCreator = undefined; - fake.fakeFn = undefined; - }, + unwrapExports(isSubset_1); + + let URL; + // https://stackoverflow.com/a/19709846/308237 + const absoluteUrlRX = new RegExp('^(?:[a-z]+:)?//', 'i'); + + const headersToArray = headers => { + // node-fetch 1 Headers + if (typeof headers.raw === 'function') { + return Object.entries(headers.raw()); + } else if (headers[Symbol.iterator]) { + return [...headers]; + } else { + return Object.entries(headers); + } + }; - resolvesArg: function resolvesArg(fake, index) { - if (typeof index !== "number") { - throw new TypeError("argument index is not number"); - } - fake.resolveArgAt = index; - fake.returnValue = undefined; - fake.resolve = true; - fake.resolveThis = false; - fake.reject = false; - fake.returnValueDefined = false; - fake.exception = undefined; - fake.exceptionCreator = undefined; - fake.fakeFn = undefined; - }, + const zipObject = entries => + entries.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {}); + + const normalizeUrl = url => { + if ( + typeof url === 'function' || + url instanceof RegExp || + /^(begin|end|glob|express|path)\:/.test(url) + ) { + return url; + } + if (absoluteUrlRX.test(url)) { + const u = new URL(url); + return u.href; + } else { + const u = new URL(url, 'http://dummy'); + return u.pathname + u.search; + } + }; - rejects: function rejects(fake, error, message) { - let reason; - if (typeof error === "string") { - reason = new Error(message || ""); - reason.name = error; - } else if (!error) { - reason = new Error("Error"); - } else { - reason = error; - } - fake.returnValue = reason; - fake.resolve = false; - fake.resolveThis = false; - fake.reject = true; - fake.returnValueDefined = true; - fake.exception = undefined; - fake.exceptionCreator = undefined; - fake.fakeFn = undefined; + const extractBody = async request => { + try { + // node-fetch + if ('body' in request) { + return request.body.toString(); + } + // fetch + return request.clone().text(); + } catch (err) { + return; + } + }; - return fake; - }, + var requestUtils = { + setUrlImplementation: it => { + URL = it; + }, + normalizeRequest: (url, options, Request) => { + if (Request.prototype.isPrototypeOf(url)) { + const derivedOptions = { + method: url.method + }; + + const body = extractBody(url); + + if (typeof body !== 'undefined') { + derivedOptions.body = body; + } + + const normalizedRequestObject = { + url: normalizeUrl(url.url), + options: Object.assign(derivedOptions, options), + request: url, + signal: (options && options.signal) || url.signal + }; + + const headers = headersToArray(url.headers); + + if (headers.length) { + normalizedRequestObject.options.headers = zipObject(headers); + } + return normalizedRequestObject; + } else if ( + typeof url === 'string' || + // horrible URL object duck-typing + (typeof url === 'object' && 'href' in url) + ) { + return { + url: normalizeUrl(url), + options: options, + signal: options && options.signal + }; + } else if (typeof url === 'object') { + throw new TypeError( + 'fetch-mock: Unrecognised Request object. Read the Config and Installation sections of the docs' + ); + } else { + throw new TypeError('fetch-mock: Invalid arguments passed to fetch'); + } + }, + normalizeUrl, + getPath: url => { + const u = absoluteUrlRX.test(url) + ? new URL(url) + : new URL(url, 'http://dummy'); + return u.pathname; + }, + + getQuery: url => { + const u = absoluteUrlRX.test(url) + ? new URL(url) + : new URL(url, 'http://dummy'); + return u.search ? u.search.substr(1) : ''; + }, + headers: { + normalize: headers => zipObject(headersToArray(headers)), + toLowerCase: headers => + Object.keys(headers).reduce((obj, k) => { + obj[k.toLowerCase()] = headers[k]; + return obj; + }, {}), + equal: (actualHeader, expectedHeader) => { + actualHeader = Array.isArray(actualHeader) + ? actualHeader + : [actualHeader]; + expectedHeader = Array.isArray(expectedHeader) + ? expectedHeader + : [expectedHeader]; + + if (actualHeader.length !== expectedHeader.length) { + return false; + } + + return actualHeader.every((val, i) => val === expectedHeader[i]); + } + } + }; - resolvesThis: function resolvesThis(fake) { - fake.returnValue = undefined; - fake.resolve = false; - fake.resolveThis = true; - fake.reject = false; - fake.returnValueDefined = false; - fake.exception = undefined; - fake.exceptionCreator = undefined; - fake.fakeFn = undefined; - }, + var lodash_isequal = createCommonjsModule(function (module, exports) { + /** + * Lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright JS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ - callThrough: function callThrough(fake) { - fake.callsThrough = true; - }, + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; - callThroughWithNew: function callThroughWithNew(fake) { - fake.callsThroughWithNew = true; - }, + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; - get: function get(fake, getterFunction) { - const rootStub = fake.stub || fake; + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; - Object.defineProperty(rootStub.rootObj, rootStub.propName, { - get: getterFunction, - configurable: isPropertyConfigurable( - rootStub.rootObj, - rootStub.propName - ), - }); + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; - return fake; - }, + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; - set: function set(fake, setterFunction) { - const rootStub = fake.stub || fake; + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - Object.defineProperty( - rootStub.rootObj, - rootStub.propName, - // eslint-disable-next-line accessor-pairs - { - set: setterFunction, - configurable: isPropertyConfigurable( - rootStub.rootObj, - rootStub.propName - ), - } - ); + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; - return fake; - }, + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; - value: function value(fake, newVal) { - const rootStub = fake.stub || fake; + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; - Object.defineProperty(rootStub.rootObj, rootStub.propName, { - value: newVal, - enumerable: true, - writable: true, - configurable: - rootStub.shadowsPropOnPrototype || - isPropertyConfigurable(rootStub.rootObj, rootStub.propName), - }); + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - return fake; - }, - }; + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); - const asyncBehaviors = exportAsyncBehaviors(defaultBehaviors); + /** Detect free variable `exports`. */ + var freeExports = exports && !exports.nodeType && exports; - module.exports = extend({}, defaultBehaviors, asyncBehaviors); + /** Detect free variable `module`. */ + var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module; - },{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/is-property-configurable":32,"@sinonjs/commons":48}],10:[function(require,module,exports){ + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; - const arrayProto = require("@sinonjs/commons").prototypes.array; - const createProxy = require("./proxy"); - const nextTick = require("./util/core/next-tick"); + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; - const slice = arrayProto.slice; - let promiseLib = Promise; + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); - module.exports = fake; + /* Node.js helper references. */ + var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; /** - * Returns a `fake` that records all calls, arguments and return values. - * - * When an `f` argument is supplied, this implementation will be used. + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. * - * @example - * // create an empty fake - * var f1 = sinon.fake(); - * - * f1(); - * - * f1.calledOnce() - * // true - * - * @example - * function greet(greeting) { - * console.log(`Hello ${greeting}`); - * } - * - * // create a fake with implementation - * var f2 = sinon.fake(greet); - * - * // Hello world - * f2("world"); - * - * f2.calledWith("world"); - * // true - * - * @param {Function|undefined} f - * @returns {Function} - * @namespace + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. */ - function fake(f) { - if (arguments.length > 0 && typeof f !== "function") { - throw new TypeError("Expected f argument to be a Function"); - } + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; - return wrapFunc(f); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; } /** - * Creates a `fake` that returns the provided `value`, as well as recording all - * calls, arguments and return values. - * - * @example - * var f1 = sinon.fake.returns(42); - * - * f1(); - * // 42 + * Appends the elements of `values` to `array`. * - * @memberof fake - * @param {*} value - * @returns {Function} + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. */ - fake.returns = function returns(value) { - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - return value; - } + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; - return wrapFunc(f); - }; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } /** - * Creates a `fake` that throws an Error. - * If the `value` argument does not have Error in its prototype chain, it will - * be used for creating a new error. - * - * @example - * var f1 = sinon.fake.throws("hello"); - * - * f1(); - * // Uncaught Error: hello - * - * @example - * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. * - * f2(); - * // Uncaught TypeError: Invalid argument - * - * @memberof fake - * @param {*|Error} value - * @returns {Function} + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. */ - fake.throws = function throws(value) { - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - throw getError(value); - } + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; - return wrapFunc(f); - }; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } /** - * Creates a `fake` that returns a promise that resolves to the passed `value` - * argument. - * - * @example - * var f1 = sinon.fake.resolves("apple pie"); - * - * await f1(); - * // "apple pie" + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. * - * @memberof fake - * @param {*} value - * @returns {Function} + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. */ - fake.resolves = function resolves(value) { - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - return promiseLib.resolve(value); - } + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); - return wrapFunc(f); - }; + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } /** - * Creates a `fake` that returns a promise that rejects to the passed `value` - * argument. When `value` does not have Error in its prototype chain, it will be - * wrapped in an Error. - * - * @example - * var f1 = sinon.fake.rejects(":("); - * - * try { - * await ft(); - * } catch (error) { - * console.log(error); - * // ":(" - * } + * The base implementation of `_.unary` without support for storing metadata. * - * @memberof fake - * @param {*} value - * @returns {Function} + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. */ - fake.rejects = function rejects(value) { - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - return promiseLib.reject(getError(value)); - } - - return wrapFunc(f); - }; + function baseUnary(func) { + return function(value) { + return func(value); + }; + } /** - * Causes `fake` to use a custom Promise implementation, instead of the native - * Promise implementation. - * - * @example - * const bluebird = require("bluebird"); - * sinon.fake.usingPromise(bluebird); + * Checks if a `cache` value for `key` exists. * - * @memberof fake - * @param {*} promiseLibrary - * @returns {Function} + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ - fake.usingPromise = function usingPromise(promiseLibrary) { - promiseLib = promiseLibrary; - return fake; - }; + function cacheHas(cache, key) { + return cache.has(key); + } /** - * Returns a `fake` that calls the callback with the defined arguments. - * - * @example - * function callback() { - * console.log(arguments.join("*")); - * } - * - * const f1 = sinon.fake.yields("apple", "pie"); - * - * f1(callback); - * // "apple*pie" + * Gets the value at `key` of `object`. * - * @memberof fake - * @returns {Function} + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. */ - fake.yields = function yields() { - const values = slice(arguments); - - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - const callback = arguments[arguments.length - 1]; - if (typeof callback !== "function") { - throw new TypeError("Expected last argument to be a function"); - } - - callback.apply(null, values); - } - - return wrapFunc(f); - }; + function getValue(object, key) { + return object == null ? undefined : object[key]; + } /** - * Returns a `fake` that calls the callback **asynchronously** with the - * defined arguments. - * - * @example - * function callback() { - * console.log(arguments.join("*")); - * } - * - * const f1 = sinon.fake.yields("apple", "pie"); - * - * f1(callback); - * - * setTimeout(() => { - * // "apple*pie" - * }); + * Converts `map` to its key-value pairs. * - * @memberof fake - * @returns {Function} + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. */ - fake.yieldsAsync = function yieldsAsync() { - const values = slice(arguments); - - // eslint-disable-next-line jsdoc/require-jsdoc - function f() { - const callback = arguments[arguments.length - 1]; - if (typeof callback !== "function") { - throw new TypeError("Expected last argument to be a function"); - } - nextTick(function () { - callback.apply(null, values); - }); - } + function mapToArray(map) { + var index = -1, + result = Array(map.size); - return wrapFunc(f); - }; + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } - let uuid = 0; /** - * Creates a proxy (sinon concept) from the passed function. + * Creates a unary function that invokes `func` with its argument transformed. * * @private - * @param {Function} f - * @returns {Function} + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. */ - function wrapFunc(f) { - const fakeInstance = function () { - let firstArg, lastArg; + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } - if (arguments.length > 0) { - firstArg = arguments[0]; - lastArg = arguments[arguments.length - 1]; - } + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); - const callback = - lastArg && typeof lastArg === "function" ? lastArg : undefined; + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } - /* eslint-disable no-use-before-define */ - proxy.firstArg = firstArg; - proxy.lastArg = lastArg; - proxy.callback = callback; + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; - return f && f.apply(this, arguments); - }; - const proxy = createProxy(fakeInstance, f || fakeInstance); + /** Used to detect overreaching core-js shims. */ + var coreJsData = root['__core-js_shared__']; - proxy.displayName = "fake"; - proxy.id = `fake#${uuid++}`; + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; - return proxy; - } + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); /** - * Returns an Error instance from the passed value, if the value is not - * already an Error instance. - * - * @private - * @param {*} value [description] - * @returns {Error} [description] + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. */ - function getError(value) { - return value instanceof Error ? value : new Error(value); - } + var nativeObjectToString = objectProto.toString; - },{"./proxy":17,"./util/core/next-tick":34,"@sinonjs/commons":48}],11:[function(require,module,exports){ + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); - const arrayProto = require("@sinonjs/commons").prototypes.array; - const proxyInvoke = require("./proxy-invoke"); - const proxyCallToString = require("./proxy-call").toString; - const timesInWords = require("./util/core/times-in-words"); - const extend = require("./util/core/extend"); - const match = require("@sinonjs/samsam").createMatcher; - const stub = require("./stub"); - const assert = require("./assert"); - const deepEqual = require("@sinonjs/samsam").deepEqual; - const inspect = require("util").inspect; - const valueToString = require("@sinonjs/commons").valueToString; + /** Built-in value references. */ + var Buffer = moduleExports ? root.Buffer : undefined, + Symbol = root.Symbol, + Uint8Array = root.Uint8Array, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeKeys = overArg(Object.keys, Object); - const every = arrayProto.every; - const forEach = arrayProto.forEach; - const push = arrayProto.push; - const slice = arrayProto.slice; + /* Built-in method references that are verified to be native. */ + var DataView = getNative(root, 'DataView'), + Map = getNative(root, 'Map'), + Promise = getNative(root, 'Promise'), + Set = getNative(root, 'Set'), + WeakMap = getNative(root, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); - function callCountInWords(callCount) { - if (callCount === 0) { - return "never called"; - } + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); - return `called ${timesInWords(callCount)}`; - } + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; - function expectedCallCountInWords(expectation) { - const min = expectation.minCalls; - const max = expectation.maxCalls; + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; - if (typeof min === "number" && typeof max === "number") { - let str = timesInWords(min); + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } - if (min !== max) { - str = `at least ${str} and at most ${timesInWords(max)}`; - } + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } - return str; - } + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } - if (typeof min === "number") { - return `at least ${timesInWords(min)}`; - } + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } - return `at most ${timesInWords(max)}`; + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); } - function receivedMinCalls(expectation) { - const hasMinLimit = typeof expectation.minCalls === "number"; - return !hasMinLimit || expectation.callCount >= expectation.minCalls; + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; } - function receivedMaxCalls(expectation) { - if (typeof expectation.maxCalls !== "number") { - return false; - } + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; - return expectation.callCount === expectation.maxCalls; - } + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; - function verifyMatcher(possibleMatcher, arg) { - const isMatcher = match.isMatcher(possibleMatcher); + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } - return (isMatcher && possibleMatcher.test(arg)) || true; + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; } - const mockExpectation = { - minCalls: 1, - maxCalls: 1, + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); - create: function create(methodName) { - const expectation = extend.nonEnum(stub(), mockExpectation); - delete expectation.create; - expectation.method = methodName; + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } - return expectation; - }, + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); - invoke: function invoke(func, thisValue, args) { - this.verifyCallAllowed(thisValue, args); + return index < 0 ? undefined : data[index][1]; + } - return proxyInvoke.apply(this, arguments); - }, - - atLeast: function atLeast(num) { - if (typeof num !== "number") { - throw new TypeError(`'${valueToString(num)}' is not number`); - } + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } - if (!this.limitsSet) { - this.maxCalls = null; - this.limitsSet = true; - } + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); - this.minCalls = num; + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } - return this; - }, + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; - atMost: function atMost(num) { - if (typeof num !== "number") { - throw new TypeError(`'${valueToString(num)}' is not number`); - } + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; - if (!this.limitsSet) { - this.minCalls = null; - this.limitsSet = true; - } + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } - this.maxCalls = num; + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } - return this; - }, + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } - never: function never() { - return this.exactly(0); - }, + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } - once: function once() { - return this.exactly(1); - }, + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } - twice: function twice() { - return this.exactly(2); - }, + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; - thrice: function thrice() { - return this.exactly(3); - }, + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } - exactly: function exactly(num) { - if (typeof num !== "number") { - throw new TypeError(`'${valueToString(num)}' is not a number`); - } + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; - this.atLeast(num); - return this.atMost(num); - }, + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; - met: function met() { - return !this.failed && receivedMinCalls(this); - }, + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } - verifyCallAllowed: function verifyCallAllowed(thisValue, args) { - const expectedArguments = this.expectedArguments; + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } - if (receivedMaxCalls(this)) { - this.failed = true; - mockExpectation.fail( - `${this.method} already called ${timesInWords(this.maxCalls)}` - ); - } + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } - if ("expectedThis" in this && this.expectedThis !== thisValue) { - mockExpectation.fail( - `${this.method} called with ${valueToString( - thisValue - )} as thisValue, expected ${valueToString(this.expectedThis)}` - ); - } + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; - if (!("expectedArguments" in this)) { - return; - } + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } - if (!args) { - mockExpectation.fail( - `${this.method} received no arguments, expected ${inspect( - expectedArguments - )}` - ); - } + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } - if (args.length < expectedArguments.length) { - mockExpectation.fail( - `${this.method} received too few arguments (${inspect( - args - )}), expected ${inspect(expectedArguments)}` - ); - } + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); - if ( - this.expectsExactArgCount && - args.length !== expectedArguments.length - ) { - mockExpectation.fail( - `${this.method} received too many arguments (${inspect( - args - )}), expected ${inspect(expectedArguments)}` - ); - } + this.size = data.size; + return result; + } - forEach( - expectedArguments, - function (expectedArgument, i) { - if (!verifyMatcher(expectedArgument, args[i])) { - mockExpectation.fail( - `${this.method} received wrong arguments ${inspect( - args - )}, didn't match ${String(expectedArguments)}` - ); - } + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } - if (!deepEqual(args[i], expectedArgument)) { - mockExpectation.fail( - `${this.method} received wrong arguments ${inspect( - args - )}, expected ${inspect(expectedArguments)}` - ); - } - }, - this - ); - }, + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } - allowsCall: function allowsCall(thisValue, args) { - const expectedArguments = this.expectedArguments; + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } - if (this.met() && receivedMaxCalls(this)) { - return false; - } + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; - if ("expectedThis" in this && this.expectedThis !== thisValue) { - return false; - } + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } - if (!("expectedArguments" in this)) { - return true; - } + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } - // eslint-disable-next-line no-underscore-dangle - const _args = args || []; + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } - if (_args.length < expectedArguments.length) { - return false; - } + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } - if ( - this.expectsExactArgCount && - _args.length !== expectedArguments.length - ) { - return false; - } + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } - return every(expectedArguments, function (expectedArgument, i) { - if (!verifyMatcher(expectedArgument, _args[i])) { - return false; - } + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } - if (!deepEqual(_args[i], expectedArgument)) { - return false; - } + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); - return true; - }); - }, + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; - withArgs: function withArgs() { - this.expectedArguments = slice(arguments); - return this; - }, + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; - withExactArgs: function withExactArgs() { - this.withArgs.apply(this, arguments); - this.expectsExactArgCount = true; - return this; - }, + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - on: function on(thisValue) { - this.expectedThis = thisValue; - return this; - }, + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; - toString: function () { - const args = slice(this.expectedArguments || []); + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } - if (!this.expectsExactArgCount) { - push(args, "[...]"); - } + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } - const callStr = proxyCallToString.call({ - proxy: this.method || "anonymous mock expectation", - args: args, - }); + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } - const message = `${callStr.replace( - ", [...", - "[, ..." - )} ${expectedCallCountInWords(this)}`; + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } - if (this.met()) { - return `Expectation met: ${message}`; - } + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; - return `Expected ${message} (${callCountInWords(this.callCount)})`; - }, + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; - verify: function verify() { - if (!this.met()) { - mockExpectation.fail(String(this)); - } else { - mockExpectation.pass(String(this)); - } + stack.set(array, other); + stack.set(other, array); - return true; - }, + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; - pass: function pass(message) { - assert.pass(message); - }, + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } - fail: function fail(message) { - const exception = new Error(message); - exception.name = "ExpectationError"; + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; - throw exception; - }, - }; + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; - module.exports = mockExpectation; + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); - },{"./assert":3,"./proxy-call":15,"./proxy-invoke":16,"./stub":22,"./util/core/extend":26,"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],12:[function(require,module,exports){ + case errorTag: + return object.name == other.name && object.message == other.message; - const arrayProto = require("@sinonjs/commons").prototypes.array; - const mockExpectation = require("./mock-expectation"); - const proxyCallToString = require("./proxy-call").toString; - const extend = require("./util/core/extend"); - const deepEqual = require("@sinonjs/samsam").deepEqual; - const wrapMethod = require("./util/core/wrap-method"); - const usePromiseLibrary = require("./util/core/use-promise-library"); + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); - const concat = arrayProto.concat; - const filter = arrayProto.filter; - const forEach = arrayProto.forEach; - const every = arrayProto.every; - const join = arrayProto.join; - const push = arrayProto.push; - const slice = arrayProto.slice; - const unshift = arrayProto.unshift; + case mapTag: + var convert = mapToArray; - function mock(object) { - if (!object || typeof object === "string") { - return mockExpectation.create(object ? object : "Anonymous mock"); - } + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); - return mock.create(object); - } + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; - function each(collection, callback) { - const col = collection || []; + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; - forEach(col, callback); + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; } - function arrayEquals(arr1, arr2, compareLength) { - if (compareLength && arr1.length !== arr2.length) { - return false; + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; } - - return every(arr1, function (element, i) { - return deepEqual(arr2[i], element); - }); + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; } - extend(mock, { - create: function create(object) { - if (!object) { - throw new TypeError("object is null"); - } - - const mockObject = extend.nonEnum({}, mock, { object: object }); - delete mockObject.create; + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } - return mockObject; - }, + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } - expects: function expects(method) { - if (!method) { - throw new TypeError("method is falsy"); - } + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } - if (!this.expectations) { - this.expectations = {}; - this.proxies = []; - this.failures = []; - } + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } - if (!this.expectations[method]) { - this.expectations[method] = []; - const mockObject = this; + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; - wrapMethod(this.object, method, function () { - return mockObject.invokeMethod(method, this, arguments); - }); + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } - push(this.proxies, method); - } + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } - const expectation = mockExpectation.create(method); - expectation.wrappedMethod = this.object[method].wrappedMethod; - push(this.expectations[method], expectation); - usePromiseLibrary(this.promiseLibrary, expectation); + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } - return expectation; - }, + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } - restore: function restore() { - const object = this.object; + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; - each(this.proxies, function (proxy) { - if (typeof object[proxy].restore === "function") { - object[proxy].restore(); - } - }); - }, + return value === proto; + } - verify: function verify() { - const expectations = this.expectations || {}; - const messages = this.failures ? slice(this.failures) : []; - const met = []; + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } - each(this.proxies, function (proxy) { - each(expectations[proxy], function (expectation) { - if (!expectation.met()) { - push(messages, String(expectation)); - } else { - push(met, String(expectation)); - } - }); - }); + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } - this.restore(); + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } - if (messages.length > 0) { - mockExpectation.fail(join(concat(messages, met), "\n")); - } else if (met.length > 0) { - mockExpectation.pass(join(concat(messages, met), "\n")); - } - - return true; - }, - - usingPromise: function usingPromise(promiseLibrary) { - this.promiseLibrary = promiseLibrary; - - return this; - }, - - invokeMethod: function invokeMethod(method, thisValue, args) { - /* if we cannot find any matching files we will explicitly call mockExpection#fail with error messages */ - /* eslint consistent-return: "off" */ - const expectations = - this.expectations && this.expectations[method] - ? this.expectations[method] - : []; - const currentArgs = args || []; - let available; - - const expectationsWithMatchingArgs = filter( - expectations, - function (expectation) { - const expectedArgs = expectation.expectedArguments || []; - - return arrayEquals( - expectedArgs, - currentArgs, - expectation.expectsExactArgCount - ); - } - ); - - const expectationsToApply = filter( - expectationsWithMatchingArgs, - function (expectation) { - return ( - !expectation.met() && - expectation.allowsCall(thisValue, args) - ); - } - ); - - if (expectationsToApply.length > 0) { - return expectationsToApply[0].apply(thisValue, args); - } - - const messages = []; - let exhausted = 0; - - forEach(expectationsWithMatchingArgs, function (expectation) { - if (expectation.allowsCall(thisValue, args)) { - available = available || expectation; - } else { - exhausted += 1; - } - }); - - if (available && exhausted === 0) { - return available.apply(thisValue, args); - } - - forEach(expectations, function (expectation) { - push(messages, ` ${String(expectation)}`); - }); - - unshift( - messages, - `Unexpected call: ${proxyCallToString.call({ - proxy: method, - args: args, - })}` - ); - - const err = new Error(); - if (!err.stack) { - // PhantomJS does not serialize the stack trace until the error has been thrown - try { - throw err; - } catch (e) { - /* empty */ - } - } - push( - this.failures, - `Unexpected call: ${proxyCallToString.call({ - proxy: method, - args: args, - stack: err.stack, - })}` - ); - - mockExpectation.fail(join(messages, "\n")); - }, - }); + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; - module.exports = mock; + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; - },{"./mock-expectation":11,"./proxy-call":15,"./util/core/extend":26,"./util/core/use-promise-library":37,"./util/core/wrap-method":40,"@sinonjs/commons":48,"@sinonjs/samsam":88}],13:[function(require,module,exports){ + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } - const fake = require("./fake"); - const isRestorable = require("./util/core/is-restorable"); + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; - const STATUS_PENDING = "pending"; - const STATUS_RESOLVED = "resolved"; - const STATUS_REJECTED = "rejected"; + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } /** - * Returns a fake for a given function or undefined. If no function is given, a - * new fake is returned. If the given function is already a fake, it is - * returned as is. Otherwise the given function is wrapped in a new fake. + * Checks if `value` is classified as a `Function` object. * - * @param {Function} [executor] The optional executor function. - * @returns {Function} + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false */ - function getFakeExecutor(executor) { - if (isRestorable(executor)) { - return executor; - } - if (executor) { - return fake(executor); - } - return fake(); + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; } /** - * Returns a new promise that exposes it's internal `status`, `resolvedValue` - * and `rejectedValue` and can be resolved or rejected from the outside by - * calling `resolve(value)` or `reject(reason)`. + * Checks if `value` is a valid array-like length. * - * @param {Function} [executor] The optional executor function. - * @returns {Promise} + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false */ - function promise(executor) { - const fakeExecutor = getFakeExecutor(executor); - const sinonPromise = new Promise(fakeExecutor); + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } - sinonPromise.status = STATUS_PENDING; - sinonPromise - .then(function (value) { - sinonPromise.status = STATUS_RESOLVED; - sinonPromise.resolvedValue = value; - }) - .catch(function (reason) { - sinonPromise.status = STATUS_REJECTED; - sinonPromise.rejectedValue = reason; - }); + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } - /** - * Resolves or rejects the promise with the given status and value. - * - * @param {string} status - * @param {*} value - * @param {Function} callback - */ - function finalize(status, value, callback) { - if (sinonPromise.status !== STATUS_PENDING) { - throw new Error(`Promise already ${sinonPromise.status}`); - } + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } - sinonPromise.status = status; - callback(value); - } + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - sinonPromise.resolve = function (value) { - finalize(STATUS_RESOLVED, value, fakeExecutor.firstCall.args[0]); - // Return the promise so that callers can await it: - return sinonPromise; - }; - sinonPromise.reject = function (reason) { - finalize(STATUS_REJECTED, reason, fakeExecutor.firstCall.args[1]); - // Return a new promise that resolves when the sinon promise was - // rejected, so that callers can await it: - return new Promise(function (resolve) { - sinonPromise.catch(() => resolve()); - }); - }; + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } - return sinonPromise; + /** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ + function stubArray() { + return []; } - module.exports = promise; + /** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ + function stubFalse() { + return false; + } - },{"./fake":10,"./util/core/is-restorable":33}],14:[function(require,module,exports){ + module.exports = isEqual; + }); - const push = require("@sinonjs/commons").prototypes.array.push; + const { debug, setDebugNamespace } = debug_1; - exports.incrementCallCount = function incrementCallCount(proxy) { - proxy.called = true; - proxy.callCount += 1; - proxy.notCalled = false; - proxy.calledOnce = proxy.callCount === 1; - proxy.calledTwice = proxy.callCount === 2; - proxy.calledThrice = proxy.callCount === 3; + + + + const { + headers: headerUtils, + getPath, + getQuery, + normalizeUrl: normalizeUrl$1 + } = requestUtils; + + + const debuggableUrlFunc = func => url => { + debug('Actual url:', url); + return func(url); }; - exports.createCallProperties = function createCallProperties(proxy) { - proxy.firstCall = proxy.getCall(0); - proxy.secondCall = proxy.getCall(1); - proxy.thirdCall = proxy.getCall(2); - proxy.lastCall = proxy.getCall(proxy.callCount - 1); + const stringMatchers = { + begin: targetString => + debuggableUrlFunc(url => url.indexOf(targetString) === 0), + end: targetString => + debuggableUrlFunc(url => url.substr(-targetString.length) === targetString), + glob: targetString => { + const urlRX = globToRegexp(targetString); + return debuggableUrlFunc(url => urlRX.test(url)); + }, + express: targetString => { + const urlRX = pathToRegexp_1(targetString); + return debuggableUrlFunc(url => urlRX.test(getPath(url))); + }, + path: targetString => debuggableUrlFunc(url => getPath(url) === targetString) }; - exports.delegateToCalls = function delegateToCalls( - proxy, - method, - matchAny, - actual, - returnsValues, - notCalled, - totalCallCount - ) { - proxy[method] = function () { - if (!this.called) { - if (notCalled) { - return notCalled.apply(this, arguments); - } - return false; - } + const getHeaderMatcher = ({ headers: expectedHeaders }) => { + debug('Generating header matcher'); + if (!expectedHeaders) { + debug(' No header expectations defined - skipping'); + return; + } + const expectation = headerUtils.toLowerCase(expectedHeaders); + debug(' Expected headers:', expectation); + return (url, { headers = {} }) => { + debug('Attempting to match headers'); + const lowerCaseHeaders = headerUtils.toLowerCase( + headerUtils.normalize(headers) + ); + debug(' Expected headers:', expectation); + debug(' Actual headers:', lowerCaseHeaders); + return Object.keys(expectation).every(headerName => + headerUtils.equal(lowerCaseHeaders[headerName], expectation[headerName]) + ); + }; + }; - if (totalCallCount !== undefined && this.callCount !== totalCallCount) { - return false; - } + const getMethodMatcher = ({ method: expectedMethod }) => { + debug('Generating method matcher'); + if (!expectedMethod) { + debug(' No method expectations defined - skipping'); + return; + } + debug(' Expected method:', expectedMethod); + return (url, { method }) => { + debug('Attempting to match method'); + const actualMethod = method ? method.toLowerCase() : 'get'; + debug(' Expected method:', expectedMethod); + debug(' Actual method:', actualMethod); + return expectedMethod === actualMethod; + }; + }; - let currentCall; - let matches = 0; - const returnValues = []; + const getQueryStringMatcher = ({ query: expectedQuery }) => { + debug('Generating query parameters matcher'); + if (!expectedQuery) { + debug(' No query parameters expectations defined - skipping'); + return; + } + debug(' Expected query parameters:', expectedQuery); + const keys = Object.keys(expectedQuery); + return url => { + debug('Attempting to match query parameters'); + const query = querystring.parse(getQuery(url)); + debug(' Expected query parameters:', expectedQuery); + debug(' Actual query parameters:', query); + return keys.every(key => query[key] === expectedQuery[key]); + }; + }; - for (let i = 0, l = this.callCount; i < l; i += 1) { - currentCall = this.getCall(i); - const returnValue = currentCall[actual || method].apply( - currentCall, - arguments - ); - push(returnValues, returnValue); - if (returnValue) { - matches += 1; + const getParamsMatcher = ({ params: expectedParams, url: matcherUrl }) => { + debug('Generating path parameters matcher'); + if (!expectedParams) { + debug(' No path parameters expectations defined - skipping'); + return; + } + if (!/express:/.test(matcherUrl)) { + throw new Error( + 'fetch-mock: matching on params is only possible when using an express: matcher' + ); + } + debug(' Expected path parameters:', expectedParams); + const expectedKeys = Object.keys(expectedParams); + const keys = []; + const re = pathToRegexp_1(matcherUrl.replace(/^express:/, ''), keys); + return url => { + debug('Attempting to match path parameters'); + const vals = re.exec(getPath(url)) || []; + vals.shift(); + const params = keys.reduce( + (map, { name }, i) => + vals[i] ? Object.assign(map, { [name]: vals[i] }) : map, + {} + ); + debug(' Expected path parameters:', expectedParams); + debug(' Actual path parameters:', params); + return expectedKeys.every(key => params[key] === expectedParams[key]); + }; + }; - if (matchAny) { - return true; - } - } - } + const getBodyMatcher = (route, fetchMock) => { + const matchPartialBody = fetchMock.getOption('matchPartialBody', route); + const { body: expectedBody } = route; + + debug('Generating body matcher'); + return (url, { body, method = 'get' }) => { + debug('Attempting to match body'); + if (method.toLowerCase() === 'get') { + debug(' GET request - skip matching body'); + // GET requests don’t send a body so the body matcher should be ignored for them + return true; + } + + let sentBody; + + try { + debug(' Parsing request body as JSON'); + sentBody = JSON.parse(body); + } catch (err) { + debug(' Failed to parse request body as JSON', err); + } + debug('Expected body:', expectedBody); + debug('Actual body:', sentBody); + if (matchPartialBody) { + debug('matchPartialBody is true - checking for partial match only'); + } + + return ( + sentBody && + (matchPartialBody + ? isSubset_1(sentBody, expectedBody) + : lodash_isequal(sentBody, expectedBody)) + ); + }; + }; - if (returnsValues) { - return returnValues; - } - return matches === this.callCount; - }; + const getFullUrlMatcher = (route, matcherUrl, query) => { + // if none of the special syntaxes apply, it's just a simple string match + // but we have to be careful to normalize the url we check and the name + // of the route to allow for e.g. http://it.at.there being indistinguishable + // from http://it.at.there/ once we start generating Request/Url objects + debug(' Matching using full url', matcherUrl); + const expectedUrl = normalizeUrl$1(matcherUrl); + debug(' Normalised url to:', matcherUrl); + if (route.identifier === matcherUrl) { + debug(' Updating route identifier to match normalized url:', matcherUrl); + route.identifier = expectedUrl; + } + + return matcherUrl => { + debug('Expected url:', expectedUrl); + debug('Actual url:', matcherUrl); + if (query && expectedUrl.indexOf('?')) { + debug('Ignoring query string when matching url'); + return matcherUrl.indexOf(expectedUrl) === 0; + } + return normalizeUrl$1(matcherUrl) === expectedUrl; + }; }; - },{"@sinonjs/commons":48}],15:[function(require,module,exports){ + const getFunctionMatcher = ({ functionMatcher }) => { + debug('Detected user defined function matcher', functionMatcher); + return (...args) => { + debug('Calling function matcher with arguments', args); + return functionMatcher(...args); + }; + }; - const arrayProto = require("@sinonjs/commons").prototypes.array; - const match = require("@sinonjs/samsam").createMatcher; - const deepEqual = require("@sinonjs/samsam").deepEqual; - const functionName = require("@sinonjs/commons").functionName; - const inspect = require("util").inspect; - const valueToString = require("@sinonjs/commons").valueToString; + const getUrlMatcher = route => { + debug('Generating url matcher'); + const { url: matcherUrl, query } = route; + + if (matcherUrl === '*') { + debug(' Using universal * rule to match any url'); + return () => true; + } + + if (matcherUrl instanceof RegExp) { + debug(' Using regular expression to match url:', matcherUrl); + return url => matcherUrl.test(url); + } + + if (matcherUrl.href) { + debug(` Using URL object to match url`, matcherUrl); + return getFullUrlMatcher(route, matcherUrl.href, query); + } + + for (const shorthand in stringMatchers) { + if (matcherUrl.indexOf(shorthand + ':') === 0) { + debug(` Using ${shorthand}: pattern to match url`, matcherUrl); + const urlFragment = matcherUrl.replace(new RegExp(`^${shorthand}:`), ''); + return stringMatchers[shorthand](urlFragment); + } + } + + return getFullUrlMatcher(route, matcherUrl, query); + }; - const concat = arrayProto.concat; - const filter = arrayProto.filter; - const join = arrayProto.join; - const map = arrayProto.map; - const reduce = arrayProto.reduce; - const slice = arrayProto.slice; + var generateMatcher = (route, fetchMock) => { + setDebugNamespace('generateMatcher()'); + debug('Compiling matcher for route'); + const matchers = [ + route.query && getQueryStringMatcher(route), + route.method && getMethodMatcher(route), + route.headers && getHeaderMatcher(route), + route.params && getParamsMatcher(route), + route.body && getBodyMatcher(route, fetchMock), + route.functionMatcher && getFunctionMatcher(route), + route.url && getUrlMatcher(route) + ].filter(matcher => !!matcher); + + debug('Compiled matcher for route'); + setDebugNamespace(); + return (url, options = {}, request) => + matchers.every(matcher => matcher(url, options, request)); + }; - /** - * @param proxy - * @param text - * @param args - */ - function throwYieldError(proxy, text, args) { - let msg = functionName(proxy) + text; - if (args.length) { - msg += ` Received [${join(slice(args), ", ")}]`; - } - throw new Error(msg); - } + const { getDebug } = debug_1; - const callProto = { - calledOn: function calledOn(thisValue) { - if (match.isMatcher(thisValue)) { - return thisValue.test(this.thisValue); - } - return this.thisValue === thisValue; - }, - calledWith: function calledWith() { - const self = this; - const calledWithArgs = slice(arguments); + const matcherProperties = [ + 'query', + 'method', + 'headers', + 'params', + 'body', + 'functionMatcher', + 'url' + ]; - if (calledWithArgs.length > self.args.length) { - return false; - } + const isUrlMatcher = matcher => + matcher instanceof RegExp || + typeof matcher === 'string' || + (typeof matcher === 'object' && 'href' in matcher); - return reduce( - calledWithArgs, - function (prev, arg, i) { - return prev && deepEqual(self.args[i], arg); - }, - true - ); - }, + const isFunctionMatcher = matcher => typeof matcher === 'function'; - calledWithMatch: function calledWithMatch() { - const self = this; - const calledWithMatchArgs = slice(arguments); + const argsToRoute = args => { + const [matcher, response, options = {}] = args; - if (calledWithMatchArgs.length > self.args.length) { - return false; - } + const routeConfig = {}; - return reduce( - calledWithMatchArgs, - function (prev, expectation, i) { - const actual = self.args[i]; + if (isUrlMatcher(matcher) || isFunctionMatcher(matcher)) { + routeConfig.matcher = matcher; + } else { + Object.assign(routeConfig, matcher); + } - return prev && match(expectation).test(actual); - }, - true - ); - }, + if (response) { + routeConfig.response = response; + } - calledWithExactly: function calledWithExactly() { - return ( - arguments.length === this.args.length && - this.calledWith.apply(this, arguments) - ); - }, + Object.assign(routeConfig, options); + return routeConfig; + }; - notCalledWith: function notCalledWith() { - return !this.calledWith.apply(this, arguments); - }, + const sanitizeRoute = route => { + const debug = getDebug('sanitizeRoute()'); + debug('Sanitizing route properties'); + route = Object.assign({}, route); + + if (route.method) { + debug(`Converting method ${route.method} to lower case`); + route.method = route.method.toLowerCase(); + } + if (isUrlMatcher(route.matcher)) { + debug('Mock uses a url matcher', route.matcher); + route.url = route.matcher; + delete route.matcher; + } + + route.functionMatcher = route.matcher || route.functionMatcher; + + debug('Setting route.identifier...'); + debug(` route.name is ${route.name}`); + debug(` route.url is ${route.url}`); + debug(` route.functionMatcher is ${route.functionMatcher}`); + route.identifier = route.name || route.url || route.functionMatcher; + debug(` -> route.identifier set to ${route.identifier}`); + return route; + }; - notCalledWithMatch: function notCalledWithMatch() { - return !this.calledWithMatch.apply(this, arguments); - }, + const validateRoute = route => { + if (!('response' in route)) { + throw new Error('fetch-mock: Each route must define a response'); + } - returned: function returned(value) { - return deepEqual(this.returnValue, value); - }, + if (!matcherProperties.some(matcherType => matcherType in route)) { + throw new Error( + "fetch-mock: Each route must specify some criteria for matching calls to fetch. To match all calls use '*'" + ); + } + }; - threw: function threw(error) { - if (typeof error === "undefined" || !this.exception) { - return Boolean(this.exception); - } + const limit = route => { + const debug = getDebug('limit()'); + debug('Limiting number of requests to handle by route'); + if (!route.repeat) { + debug( + ' No `repeat` value set on route. Will match any number of requests' + ); + return; + } + + debug(` Route set to repeat ${route.repeat} times`); + const matcher = route.matcher; + let timesLeft = route.repeat; + route.matcher = (url, options) => { + const match = timesLeft && matcher(url, options); + if (match) { + timesLeft--; + return true; + } + }; + route.reset = () => (timesLeft = route.repeat); + }; - return this.exception === error || this.exception.name === error; - }, + const delayResponse = route => { + const debug = getDebug('delayResponse()'); + debug(`Applying response delay settings`); + const { delay } = route; + if (delay) { + debug(` Wrapping response in delay of ${delay} miliseconds`); + const response = route.response; + route.response = () => { + debug(`Delaying response by ${delay} miliseconds`); + return new Promise(res => setTimeout(() => res(response), delay)); + }; + } else { + debug( + ` No delay set on route. Will respond 'immediately' (but asynchronously)` + ); + } + }; - calledWithNew: function calledWithNew() { - return this.proxy.prototype && this.thisValue instanceof this.proxy; - }, + const compileRoute = function(args) { + const debug = getDebug('compileRoute()'); + debug('Compiling route'); + const route = sanitizeRoute(argsToRoute(args)); + validateRoute(route); + route.matcher = generateMatcher(route, this); + limit(route); + delayResponse(route); + return route; + }; - calledBefore: function (other) { - return this.callId < other.callId; - }, + var compileRoute_1 = { + compileRoute, + sanitizeRoute + }; - calledAfter: function (other) { - return this.callId > other.callId; - }, + const { debug: debug$1, setDebugPhase } = debug_1; + const { compileRoute: compileRoute$1 } = compileRoute_1; + const FetchMock = {}; - calledImmediatelyBefore: function (other) { - return this.callId === other.callId - 1; - }, + FetchMock.mock = function(...args) { + setDebugPhase('setup'); + if (args.length) { + this.addRoute(args); + } - calledImmediatelyAfter: function (other) { - return this.callId === other.callId + 1; - }, + return this._mock(); + }; - callArg: function (pos) { - this.ensureArgIsAFunction(pos); - return this.args[pos](); - }, + FetchMock.addRoute = function(uncompiledRoute) { + debug$1('Adding route', uncompiledRoute); + const route = this.compileRoute(uncompiledRoute); + const clashes = this.routes.filter( + ({ identifier, method }) => + identifier === route.identifier && + (!method || !route.method || method === route.method) + ); + + if (this.getOption('overwriteRoutes', route) === false || !clashes.length) { + this._uncompiledRoutes.push(uncompiledRoute); + return this.routes.push(route); + } + + if (this.getOption('overwriteRoutes', route) === true) { + clashes.forEach(clash => { + const index = this.routes.indexOf(clash); + this._uncompiledRoutes.splice(index, 1, uncompiledRoute); + this.routes.splice(index, 1, route); + }); + return this.routes; + } + + if (clashes.length) { + throw new Error( + 'fetch-mock: Adding route with same name or matcher as existing route. See `overwriteRoutes` option.' + ); + } + + this._uncompiledRoutes.push(uncompiledRoute); + this.routes.push(route); + }; - callArgOn: function (pos, thisValue) { - this.ensureArgIsAFunction(pos); - return this.args[pos].apply(thisValue); - }, + FetchMock._mock = function() { + if (!this.isSandbox) { + // Do this here rather than in the constructor to ensure it's scoped to the test + this.realFetch = this.realFetch || this.global.fetch; + this.global.fetch = this.fetchHandler; + } + setDebugPhase(); + return this; + }; - callArgWith: function (pos) { - return this.callArgOnWith.apply( - this, - concat([pos, null], slice(arguments, 1)) - ); - }, + FetchMock.catch = function(response) { + if (this.fallbackResponse) { + console.warn( + 'calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response' + ); // eslint-disable-line + } + this.fallbackResponse = response || 'ok'; + return this._mock(); + }; - callArgOnWith: function (pos, thisValue) { - this.ensureArgIsAFunction(pos); - const args = slice(arguments, 2); - return this.args[pos].apply(thisValue, args); - }, + FetchMock.spy = function() { + this._mock(); + return this.catch(this.getNativeFetch()); + }; - throwArg: function (pos) { - if (pos > this.args.length) { - throw new TypeError( - `Not enough arguments: ${pos} required but only ${this.args.length} present` - ); - } + FetchMock.compileRoute = compileRoute$1; - throw this.args[pos]; - }, + const defineShorthand = (methodName, underlyingMethod, shorthandOptions) => { + FetchMock[methodName] = function(matcher, response, options) { + return this[underlyingMethod]( + matcher, + response, + Object.assign(options || {}, shorthandOptions) + ); + }; + }; + defineShorthand('once', 'mock', { repeat: 1 }); - yield: function () { - return this.yieldOn.apply(this, concat([null], slice(arguments, 0))); - }, + ['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(method => { + defineShorthand(method, 'mock', { method }); + defineShorthand(`${method}Once`, 'once', { method }); + }); - yieldOn: function (thisValue) { - const args = slice(this.args); - const yieldFn = filter(args, function (arg) { - return typeof arg === "function"; - })[0]; + FetchMock.resetBehavior = function() { + if (this.realFetch) { + this.global.fetch = this.realFetch; + this.realFetch = undefined; + } + this.fallbackResponse = undefined; + this.routes = []; + this._uncompiledRoutes = []; + return this; + }; - if (!yieldFn) { - throwYieldError( - this.proxy, - " cannot yield since no callback was passed.", - args - ); - } + FetchMock.resetHistory = function() { + this._calls = []; + this._holdingPromises = []; + this.routes.forEach(route => route.reset && route.reset()); + return this; + }; - return yieldFn.apply(thisValue, slice(arguments, 1)); - }, + FetchMock.restore = FetchMock.reset = function() { + this.resetBehavior(); + this.resetHistory(); + return this; + }; - yieldTo: function (prop) { - return this.yieldToOn.apply( - this, - concat([prop, null], slice(arguments, 1)) - ); - }, + var setUpAndTearDown = FetchMock; - yieldToOn: function (prop, thisValue) { - const args = slice(this.args); - const yieldArg = filter(args, function (arg) { - return arg && typeof arg[prop] === "function"; - })[0]; - const yieldFn = yieldArg && yieldArg[prop]; + const { getDebug: getDebug$1 } = debug_1; + const responseConfigProps = [ + 'body', + 'headers', + 'throws', + 'status', + 'redirectUrl' + ]; - if (!yieldFn) { - throwYieldError( - this.proxy, - ` cannot yield to '${valueToString( - prop - )}' since no callback was passed.`, - args - ); - } + class ResponseBuilder { + constructor(options) { + this.debug = getDebug$1('ResponseBuilder()'); + this.debug('Response builder created with options', options); + Object.assign(this, options); + } + + exec() { + this.debug('building response'); + this.normalizeResponseConfig(); + this.constructFetchOpts(); + this.constructResponseBody(); + return this.buildObservableResponse( + new this.fetchMock.config.Response(this.body, this.options) + ); + } + + sendAsObject() { + if (responseConfigProps.some(prop => this.responseConfig[prop])) { + if ( + Object.keys(this.responseConfig).every(key => + responseConfigProps.includes(key) + ) + ) { + return false; + } else { + return true; + } + } else { + return true; + } + } + + normalizeResponseConfig() { + // If the response config looks like a status, start to generate a simple response + if (typeof this.responseConfig === 'number') { + this.debug('building response using status', this.responseConfig); + this.responseConfig = { + status: this.responseConfig + }; + // If the response config is not an object, or is an object that doesn't use + // any reserved properties, assume it is meant to be the body of the response + } else if (typeof this.responseConfig === 'string' || this.sendAsObject()) { + this.debug('building text response from', this.responseConfig); + this.responseConfig = { + body: this.responseConfig + }; + } + } + + validateStatus(status) { + if (!status) { + this.debug('No status provided. Defaulting to 200'); + return 200; + } + + if ( + (typeof status === 'number' && + parseInt(status, 10) !== status && + status >= 200) || + status < 600 + ) { + this.debug('Valid status provided', status); + return status; + } + + throw new TypeError(`fetch-mock: Invalid status ${status} passed on response object. +To respond with a JSON object that has status as a property assign the object to body +e.g. {"body": {"status: "registered"}}`); + } + + constructFetchOpts() { + this.options = this.responseConfig.options || {}; + this.options.url = this.responseConfig.redirectUrl || this.url; + this.options.status = this.validateStatus(this.responseConfig.status); + this.options.statusText = this.fetchMock.statusTextMap[ + '' + this.options.status + ]; + // Set up response headers. The empty object is to cope with + // new Headers(undefined) throwing in Chrome + // https://code.google.com/p/chromium/issues/detail?id=335871 + this.options.headers = new this.fetchMock.config.Headers( + this.responseConfig.headers || {} + ); + } + + getOption(name) { + return this.fetchMock.getOption(name, this.route); + } + + convertToJson() { + // convert to json if we need to + if ( + this.getOption('sendAsJson') && + this.responseConfig.body != null && //eslint-disable-line + typeof this.body === 'object' + ) { + this.debug('Stringifying JSON response body'); + this.body = JSON.stringify(this.body); + if (!this.options.headers.has('Content-Type')) { + this.options.headers.set('Content-Type', 'application/json'); + } + } + } + + setContentLength() { + // add a Content-Length header if we need to + if ( + this.getOption('includeContentLength') && + typeof this.body === 'string' && + !this.options.headers.has('Content-Length') + ) { + this.debug('Setting content-length header:', this.body.length.toString()); + this.options.headers.set('Content-Length', this.body.length.toString()); + } + } + + constructResponseBody() { + // start to construct the body + this.body = this.responseConfig.body; + this.convertToJson(); + this.setContentLength(); + + // On the server we need to manually construct the readable stream for the + // Response object (on the client this done automatically) + if (this.Stream) { + this.debug('Creating response stream'); + const stream = new this.Stream.Readable(); + if (this.body != null) { //eslint-disable-line + stream.push(this.body, 'utf-8'); + } + stream.push(null); + this.body = stream; + } + this.body = this.body; + } + + buildObservableResponse(response) { + const fetchMock = this.fetchMock; + + // Using a proxy means we can set properties that may not be writable on + // the original Response. It also means we can track the resolution of + // promises returned by res.json(), res.text() etc + this.debug('Wrappipng Response in ES proxy for observability'); + return new Proxy(response, { + get: (originalResponse, name) => { + if (this.responseConfig.redirectUrl) { + if (name === 'url') { + this.debug( + 'Retrieving redirect url', + this.responseConfig.redirectUrl + ); + return this.responseConfig.redirectUrl; + } + + if (name === 'redirected') { + this.debug('Retrieving redirected status', true); + return true; + } + } + + if (typeof originalResponse[name] === 'function') { + this.debug('Wrapping body promises in ES proxies for observability'); + return new Proxy(originalResponse[name], { + apply: (func, thisArg, args) => { + this.debug(`Calling res.${name}`); + const result = func.apply(response, args); + if (result.then) { + fetchMock._holdingPromises.push(result.catch(() => null)); + } + return result; + } + }); + } + + return originalResponse[name]; + } + }); + } + } - return yieldFn.apply(thisValue, slice(arguments, 2)); - }, + var responseBuilder = options => new ResponseBuilder(options).exec(); - toString: function () { - if (!this.args) { - return ":("; - } + const { debug: debug$2, setDebugPhase: setDebugPhase$1, getDebug: getDebug$2 } = debug_1; - let callStr = this.proxy ? `${String(this.proxy)}(` : ""; - const formattedArgs = map(this.args, function (arg) { - return inspect(arg); - }); - callStr = `${callStr + join(formattedArgs, ", ")})`; + const FetchMock$1 = {}; - if (typeof this.returnValue !== "undefined") { - callStr += ` => ${inspect(this.returnValue)}`; - } + // see https://heycam.github.io/webidl/#aborterror for the standardised interface + // Note that this differs slightly from node-fetch + class AbortError extends Error { + constructor() { + super(...arguments); + this.name = 'AbortError'; + this.message = 'The operation was aborted.'; - if (this.exception) { - callStr += ` !${this.exception.name}`; + // Do not include this class in the stacktrace + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + } - if (this.exception.message) { - callStr += `(${this.exception.message})`; - } - } - if (this.stack) { - // If we have a stack, add the first frame that's in end-user code - // Skip the first two frames because they will refer to Sinon code - callStr += (this.stack.split("\n")[3] || "unknown").replace( - /^\s*(?:at\s+|@)?/, - " at " - ); - } + const resolve = async ( + { response, responseIsFetch = false }, + url, + options, + request + ) => { + const debug = getDebug$2('resolve()'); + debug('Recursively resolving function and promise responses'); + // We want to allow things like + // - function returning a Promise for a response + // - delaying (using a timeout Promise) a function's execution to generate + // a response + // Because of this we can't safely check for function before Promisey-ness, + // or vice versa. So to keep it DRY, and flexible, we keep trying until we + // have something that looks like neither Promise nor function + while (true) { + if (typeof response === 'function') { + debug(' Response is a function'); + // in the case of falling back to the network we need to make sure we're using + // the original Request instance, not our normalised url + options + if (responseIsFetch) { + if (request) { + debug(' -> Calling fetch with Request instance'); + return response(request); + } + debug(' -> Calling fetch with url and options'); + return response(url, options); + } else { + debug(' -> Calling response function'); + response = response(url, options, request); + } + } else if (typeof response.then === 'function') { + debug(' Response is a promise'); + debug(' -> Resolving promise'); + response = await response; + } else { + debug(' Response is not a function or a promise'); + debug(' -> Exiting response resolution recursion'); + return response; + } + } + }; - return callStr; - }, + FetchMock$1.fetchHandler = function(url, options, request) { + setDebugPhase$1('handle'); + const debug = getDebug$2('fetchHandler()'); + debug('fetch called with:', url, options); + const normalizedRequest = requestUtils.normalizeRequest( + url, + options, + this.config.Request + ); + + ({ url, options, request } = normalizedRequest); + + const { signal } = normalizedRequest; + + debug('Request normalised'); + debug(' url', url); + debug(' options', options); + debug(' request', request); + debug(' signal', signal); + + if (request && this.routes.some(({ body }) => !!body)) { + debug( + 'Need to wait for Body to be streamed before calling router: switching to async mode' + ); + return this._asyncFetchHandler(url, options, request, signal); + } + return this._fetchHandler(url, options, request, signal); + }; - ensureArgIsAFunction: function (pos) { - if (typeof this.args[pos] !== "function") { - throw new TypeError( - `Expected argument at position ${pos} to be a Function, but was ${typeof this - .args[pos]}` - ); - } - }, + FetchMock$1._asyncFetchHandler = async function(url, options, request, signal) { + options.body = await options.body; + return this._fetchHandler(url, options, request, signal); }; - Object.defineProperty(callProto, "stack", { - enumerable: true, - configurable: true, - get: function () { - return (this.errorWithCallStack && this.errorWithCallStack.stack) || ""; - }, - }); - callProto.invokeCallback = callProto.yield; + FetchMock$1._fetchHandler = function(url, options, request, signal) { + const route = this.executeRouter(url, options, request); + + // this is used to power the .flush() method + let done; + this._holdingPromises.push(new this.config.Promise(res => (done = res))); + + // wrapped in this promise to make sure we respect custom Promise + // constructors defined by the user + return new this.config.Promise((res, rej) => { + if (signal) { + debug$2('signal exists - enabling fetch abort'); + const abort = () => { + debug$2('aborting fetch'); + // note that DOMException is not available in node.js; even node-fetch uses a custom error class: https://github.com/bitinn/node-fetch/blob/master/src/abort-error.js + rej( + typeof DOMException !== 'undefined' + ? new DOMException('The operation was aborted.', 'AbortError') + : new AbortError() + ); + done(); + }; + if (signal.aborted) { + debug$2('signal is already aborted - aborting the fetch'); + abort(); + } + signal.addEventListener('abort', abort); + } + + this.generateResponse(route, url, options, request) + .then(res, rej) + .then(done, done) + .then(() => { + setDebugPhase$1(); + }); + }); + }; - /** - * @param proxy - * @param thisValue - * @param args - * @param returnValue - * @param exception - * @param id - * @param errorWithCallStack - */ - function createProxyCall( - proxy, - thisValue, - args, - returnValue, - exception, - id, - errorWithCallStack - ) { - if (typeof id !== "number") { - throw new TypeError("Call id is not a number"); - } + FetchMock$1.fetchHandler.isMock = true; + + FetchMock$1.executeRouter = function(url, options, request) { + const debug = getDebug$2('executeRouter()'); + debug(`Attempting to match request to a route`); + if (this.getOption('fallbackToNetwork') === 'always') { + debug( + ' Configured with fallbackToNetwork=always - passing through to fetch' + ); + return { response: this.getNativeFetch(), responseIsFetch: true }; + } + + const match = this.router(url, options, request); + + if (match) { + debug(' Matching route found'); + return match; + } + + if (this.getOption('warnOnFallback')) { + console.warn(`Unmatched ${(options && options.method) || 'GET'} to ${url}`); // eslint-disable-line + } + + this.push({ url, options, request, isUnmatched: true }); + + if (this.fallbackResponse) { + debug(' No matching route found - using fallbackResponse'); + return { response: this.fallbackResponse }; + } + + if (!this.getOption('fallbackToNetwork')) { + throw new Error( + `fetch-mock: No fallback response defined for ${(options && + options.method) || + 'GET'} to ${url}` + ); + } + + debug(' Configured to fallbackToNetwork - passing through to fetch'); + return { response: this.getNativeFetch(), responseIsFetch: true }; + }; - let firstArg, lastArg; + FetchMock$1.generateResponse = async function(route, url, options, request) { + const debug = getDebug$2('generateResponse()'); + const response = await resolve(route, url, options, request); + + // If the response says to throw an error, throw it + // Type checking is to deal with sinon spies having a throws property :-0 + if (response.throws && typeof response !== 'function') { + debug('response.throws is defined - throwing an error'); + throw response.throws; + } + + // If the response is a pre-made Response, respond with it + if (this.config.Response.prototype.isPrototypeOf(response)) { + debug('response is already a Response instance - returning it'); + return response; + } + + // finally, if we need to convert config into a response, we do it + return responseBuilder({ + url, + responseConfig: response, + fetchMock: this, + route + }); + }; - if (args.length > 0) { - firstArg = args[0]; - lastArg = args[args.length - 1]; - } + FetchMock$1.router = function(url, options, request) { + const route = this.routes.find((route, i) => { + debug$2(`Trying to match route ${i}`); + return route.matcher(url, options, request); + }); + + if (route) { + this.push({ + url, + options, + request, + identifier: route.identifier + }); + return route; + } + }; - const proxyCall = Object.create(callProto); - const callback = - lastArg && typeof lastArg === "function" ? lastArg : undefined; + FetchMock$1.getNativeFetch = function() { + const func = this.realFetch || (this.isSandbox && this.config.fetch); + if (!func) { + throw new Error( + 'fetch-mock: Falling back to network only available on global fetch-mock, or by setting config.fetch on sandboxed fetch-mock' + ); + } + return func; + }; - proxyCall.proxy = proxy; - proxyCall.thisValue = thisValue; - proxyCall.args = args; - proxyCall.firstArg = firstArg; - proxyCall.lastArg = lastArg; - proxyCall.callback = callback; - proxyCall.returnValue = returnValue; - proxyCall.exception = exception; - proxyCall.callId = id; - proxyCall.errorWithCallStack = errorWithCallStack; + FetchMock$1.push = function({ url, options, request, isUnmatched, identifier }) { + debug$2('Recording fetch call', { + url, + options, + request, + isUnmatched, + identifier + }); + const args = [url, options]; + args.request = request; + args.identifier = identifier; + args.isUnmatched = isUnmatched; + this._calls.push(args); + }; - return proxyCall; - } - createProxyCall.toString = callProto.toString; // used by mocks + var fetchHandler = FetchMock$1; - module.exports = createProxyCall; + const { setDebugPhase: setDebugPhase$2, setDebugNamespace: setDebugNamespace$1, debug: debug$3 } = debug_1; + const { normalizeUrl: normalizeUrl$2 } = requestUtils; + const FetchMock$2 = {}; + const { sanitizeRoute: sanitizeRoute$1 } = compileRoute_1; - },{"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],16:[function(require,module,exports){ + const isName = nameOrMatcher => + typeof nameOrMatcher === 'string' && /^[\da-zA-Z\-]+$/.test(nameOrMatcher); - const arrayProto = require("@sinonjs/commons").prototypes.array; - const proxyCallUtil = require("./proxy-call-util"); + const filterCallsWithMatcher = function(matcher, options = {}, calls) { + matcher = generateMatcher( + sanitizeRoute$1(Object.assign({ matcher }, options)), + this + ); + return calls.filter(([url, options]) => matcher(normalizeUrl$2(url), options)); + }; - const push = arrayProto.push; - const forEach = arrayProto.forEach; - const concat = arrayProto.concat; - const ErrorConstructor = Error.prototype.constructor; - const bind = Function.prototype.bind; + const formatDebug = func => { + return function(...args) { + setDebugPhase$2('inspect'); + const result = func.call(this, ...args); + setDebugPhase$2(); + return result; + }; + }; - let callId = 0; + FetchMock$2.filterCalls = function(nameOrMatcher, options) { + debug$3('Filtering fetch calls'); + let calls = this._calls; + let matcher = '*'; + + if ([true, 'matched'].includes(nameOrMatcher)) { + debug$3(`Filter provided is ${nameOrMatcher}. Returning matched calls only`); + calls = calls.filter(({ isUnmatched }) => !isUnmatched); + } else if ([false, 'unmatched'].includes(nameOrMatcher)) { + debug$3( + `Filter provided is ${nameOrMatcher}. Returning unmatched calls only` + ); + calls = calls.filter(({ isUnmatched }) => isUnmatched); + } else if (typeof nameOrMatcher === 'undefined') { + debug$3(`Filter provided is undefined. Returning all calls`); + calls = calls; + } else if (isName(nameOrMatcher)) { + debug$3( + `Filter provided, looks like the name of a named route. Returning only calls handled by that route` + ); + calls = calls.filter(({ identifier }) => identifier === nameOrMatcher); + } else { + matcher = normalizeUrl$2(nameOrMatcher); + if (this.routes.some(({ identifier }) => identifier === matcher)) { + debug$3( + `Filter provided, ${nameOrMatcher}, identifies a route. Returning only calls handled by that route` + ); + calls = calls.filter(call => call.identifier === matcher); + } + } + + if ((options || matcher !== '*') && calls.length) { + if (typeof options === 'string') { + options = { method: options }; + } + debug$3( + 'Compiling filter and options to route in order to filter all calls', + nameOrMatcher + ); + calls = filterCallsWithMatcher.call(this, matcher, options, calls); + } + debug$3(`Retrieved ${calls.length} calls`); + return calls; + }; - module.exports = function invoke(func, thisValue, args) { - const matchings = this.matchingFakes(args); - const currentCallId = callId++; - let exception, returnValue; + FetchMock$2.calls = formatDebug(function(nameOrMatcher, options) { + debug$3('retrieving matching calls'); + return this.filterCalls(nameOrMatcher, options); + }); - proxyCallUtil.incrementCallCount(this); - push(this.thisValues, thisValue); - push(this.args, args); - push(this.callIds, currentCallId); - forEach(matchings, function (matching) { - proxyCallUtil.incrementCallCount(matching); - push(matching.thisValues, thisValue); - push(matching.args, args); - push(matching.callIds, currentCallId); - }); + FetchMock$2.lastCall = formatDebug(function(nameOrMatcher, options) { + debug$3('retrieving last matching call'); + return [...this.filterCalls(nameOrMatcher, options)].pop(); + }); - // Make call properties available from within the spied function: - proxyCallUtil.createCallProperties(this); - forEach(matchings, proxyCallUtil.createCallProperties); + FetchMock$2.lastUrl = formatDebug(function(nameOrMatcher, options) { + debug$3('retrieving url of last matching call'); + return (this.lastCall(nameOrMatcher, options) || [])[0]; + }); - try { - this.invoking = true; + FetchMock$2.lastOptions = formatDebug(function(nameOrMatcher, options) { + debug$3('retrieving options of last matching call'); + return (this.lastCall(nameOrMatcher, options) || [])[1]; + }); - const thisCall = this.getCall(this.callCount - 1); + FetchMock$2.called = formatDebug(function(nameOrMatcher, options) { + debug$3('checking if matching call was made'); + return !!this.filterCalls(nameOrMatcher, options).length; + }); - if (thisCall.calledWithNew()) { - // Call through with `new` - returnValue = new (bind.apply( - this.func || func, - concat([thisValue], args) - ))(); + FetchMock$2.flush = formatDebug(async function(waitForResponseMethods) { + setDebugNamespace$1('flush'); + debug$3( + `flushing all fetch calls. ${ + waitForResponseMethods ? '' : 'Not ' + }waiting for response bodies to complete download` + ); + + const queuedPromises = this._holdingPromises; + this._holdingPromises = []; + debug$3(`${queuedPromises.length} fetch calls to be awaited`); + + await Promise.all(queuedPromises); + debug$3(`All fetch calls have completed`); + if (waitForResponseMethods && this._holdingPromises.length) { + debug$3(`Awaiting all fetch bodies to download`); + await this.flush(waitForResponseMethods); + debug$3(`All fetch bodies have completed downloading`); + } + setDebugNamespace$1(); + }); - if ( - typeof returnValue !== "object" && - typeof returnValue !== "function" - ) { - returnValue = thisValue; - } - } else { - returnValue = (this.func || func).apply(thisValue, args); - } - } catch (e) { - exception = e; - } finally { - delete this.invoking; - } + FetchMock$2.done = formatDebug(function(nameOrMatcher) { + setDebugPhase$2('inspect'); + setDebugNamespace$1('done'); + debug$3('Checking to see if expected calls have been made'); + let routesToCheck; + + if (nameOrMatcher && typeof nameOrMatcher !== 'boolean') { + debug$3( + 'Checking to see if expected calls have been made for single route:', + nameOrMatcher + ); + routesToCheck = [{ identifier: nameOrMatcher }]; + } else { + debug$3('Checking to see if expected calls have been made for all routes'); + routesToCheck = this.routes; + } + + // Can't use array.every because would exit after first failure, which would + // break the logging + const result = routesToCheck + .map(({ identifier }) => { + if (!this.called(identifier)) { + debug$3('No calls made for route:', identifier); + console.warn(`Warning: ${identifier} not called`); // eslint-disable-line + return false; + } + + const expectedTimes = ( + this.routes.find(r => r.identifier === identifier) || {} + ).repeat; + + if (!expectedTimes) { + debug$3( + 'Route has been called at least once, and no expectation of more set:', + identifier + ); + return true; + } + const actualTimes = this.filterCalls(identifier).length; + + debug$3(`Route called ${actualTimes} times:`, identifier); + if (expectedTimes > actualTimes) { + debug$3( + `Route called ${actualTimes} times, but expected ${expectedTimes}:`, + identifier + ); + console.warn( + `Warning: ${identifier} only called ${actualTimes} times, but ${expectedTimes} expected` + ); // eslint-disable-line + return false; + } else { + return true; + } + }) + .every(isDone => isDone); + + setDebugNamespace$1(); + setDebugPhase$2(); + return result; + }); - push(this.exceptions, exception); - push(this.returnValues, returnValue); - forEach(matchings, function (matching) { - push(matching.exceptions, exception); - push(matching.returnValues, returnValue); - }); + var inspecting = FetchMock$2; - const err = new ErrorConstructor(); - // 1. Please do not get stack at this point. It may be so very slow, and not actually used - // 2. PhantomJS does not serialize the stack trace until the error has been thrown: - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack - try { - throw err; - } catch (e) { - /* empty */ - } - push(this.errorsWithCallStack, err); - forEach(matchings, function (matching) { - push(matching.errorsWithCallStack, err); - }); + const { debug: debug$4 } = debug_1; - // Make return value and exception available in the calls: - proxyCallUtil.createCallProperties(this); - forEach(matchings, proxyCallUtil.createCallProperties); - if (exception !== undefined) { - throw exception; - } - return returnValue; - }; - },{"./proxy-call-util":14,"@sinonjs/commons":48}],17:[function(require,module,exports){ + const FetchMock$3 = Object.assign({}, fetchHandler, setUpAndTearDown, inspecting); - const arrayProto = require("@sinonjs/commons").prototypes.array; - const extend = require("./util/core/extend"); - const functionToString = require("./util/core/function-to-string"); - const proxyCall = require("./proxy-call"); - const proxyCallUtil = require("./proxy-call-util"); - const proxyInvoke = require("./proxy-invoke"); - const inspect = require("util").inspect; + FetchMock$3.config = { + fallbackToNetwork: false, + includeContentLength: true, + sendAsJson: true, + warnOnFallback: true, + overwriteRoutes: undefined + }; - const push = arrayProto.push; - const forEach = arrayProto.forEach; - const slice = arrayProto.slice; + FetchMock$3.createInstance = function() { + debug$4('Creating fetch-mock instance'); + const instance = Object.create(FetchMock$3); + instance._uncompiledRoutes = (this._uncompiledRoutes || []).slice(); + instance.routes = instance._uncompiledRoutes.map(config => + instance.compileRoute(config) + ); + instance.fallbackResponse = this.fallbackResponse || undefined; + instance.config = Object.assign({}, this.config || FetchMock$3.config); + instance._calls = []; + instance._holdingPromises = []; + instance.bindMethods(); + return instance; + }; - const emptyFakes = Object.freeze([]); + FetchMock$3.bindMethods = function() { + this.fetchHandler = FetchMock$3.fetchHandler.bind(this); + this.reset = this.restore = FetchMock$3.reset.bind(this); + this.resetHistory = FetchMock$3.resetHistory.bind(this); + this.resetBehavior = FetchMock$3.resetBehavior.bind(this); + }; - // Public API - const proxyApi = { - toString: functionToString, + FetchMock$3.sandbox = function() { + debug$4('Creating sandboxed fetch-mock instance'); + // this construct allows us to create a fetch-mock instance which is also + // a callable function, while circumventing circularity when defining the + // object that this function should be bound to + const proxy = (url, options) => sandbox.fetchHandler(url, options); + + const sandbox = Object.assign( + proxy, // Ensures that the entire returned object is a callable function + FetchMock$3, // prototype methods + this.createInstance() // instance data + ); + + sandbox.bindMethods(); + sandbox.isSandbox = true; + return sandbox; + }; - named: function named(name) { - this.displayName = name; - const nameDescriptor = Object.getOwnPropertyDescriptor(this, "name"); - if (nameDescriptor && nameDescriptor.configurable) { - // IE 11 functions don't have a name. - // Safari 9 has names that are not configurable. - nameDescriptor.value = name; - Object.defineProperty(this, "name", nameDescriptor); - } - return this; - }, + FetchMock$3.getOption = function(name, route = {}) { + return name in route ? route[name] : this.config[name]; + }; - invoke: proxyInvoke, + var lib = FetchMock$3; + + const statusTextMap = { + '100': 'Continue', + '101': 'Switching Protocols', + '102': 'Processing', + '200': 'OK', + '201': 'Created', + '202': 'Accepted', + '203': 'Non-Authoritative Information', + '204': 'No Content', + '205': 'Reset Content', + '206': 'Partial Content', + '207': 'Multi-Status', + '208': 'Already Reported', + '226': 'IM Used', + '300': 'Multiple Choices', + '301': 'Moved Permanently', + '302': 'Found', + '303': 'See Other', + '304': 'Not Modified', + '305': 'Use Proxy', + '307': 'Temporary Redirect', + '308': 'Permanent Redirect', + '400': 'Bad Request', + '401': 'Unauthorized', + '402': 'Payment Required', + '403': 'Forbidden', + '404': 'Not Found', + '405': 'Method Not Allowed', + '406': 'Not Acceptable', + '407': 'Proxy Authentication Required', + '408': 'Request Timeout', + '409': 'Conflict', + '410': 'Gone', + '411': 'Length Required', + '412': 'Precondition Failed', + '413': 'Payload Too Large', + '414': 'URI Too Long', + '415': 'Unsupported Media Type', + '416': 'Range Not Satisfiable', + '417': 'Expectation Failed', + '418': "I'm a teapot", + '421': 'Misdirected Request', + '422': 'Unprocessable Entity', + '423': 'Locked', + '424': 'Failed Dependency', + '425': 'Unordered Collection', + '426': 'Upgrade Required', + '428': 'Precondition Required', + '429': 'Too Many Requests', + '431': 'Request Header Fields Too Large', + '451': 'Unavailable For Legal Reasons', + '500': 'Internal Server Error', + '501': 'Not Implemented', + '502': 'Bad Gateway', + '503': 'Service Unavailable', + '504': 'Gateway Timeout', + '505': 'HTTP Version Not Supported', + '506': 'Variant Also Negotiates', + '507': 'Insufficient Storage', + '508': 'Loop Detected', + '509': 'Bandwidth Limit Exceeded', + '510': 'Not Extended', + '511': 'Network Authentication Required' + }; - /* - * Hook for derived implementation to return fake instances matching the - * given arguments. - */ - matchingFakes: function (/*args, strict*/) { - return emptyFakes; - }, + var statusText = statusTextMap; - getCall: function getCall(index) { - let i = index; - if (i < 0) { - // Negative indices means counting backwards from the last call - i += this.callCount; - } - if (i < 0 || i >= this.callCount) { - return null; - } + const theGlobal = typeof window !== 'undefined' ? window : self; + const { setUrlImplementation } = requestUtils; + setUrlImplementation(theGlobal.URL); - return proxyCall( - this, - this.thisValues[i], - this.args[i], - this.returnValues[i], - this.exceptions[i], - this.callIds[i], - this.errorsWithCallStack[i] - ); - }, + lib.global = theGlobal; + lib.statusTextMap = statusText; - getCalls: function () { - const calls = []; - let i; + lib.config = Object.assign(lib.config, { + Promise: theGlobal.Promise, + Request: theGlobal.Request, + Response: theGlobal.Response, + Headers: theGlobal.Headers + }); - for (i = 0; i < this.callCount; i++) { - push(calls, this.getCall(i)); + var client = lib.createInstance(); + + function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } + function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } + var DefaultConfig = Constants.DefaultConfig, + setLocalStorage$4 = TestsCore.setLocalStorage, + findRequest = TestsCore.findRequest, + findRequestURL = TestsCore.findRequestURL, + findEventFromRequest$7 = TestsCore.findEventFromRequest, + findBatch$6 = TestsCore.findBatch; + var mockServer$d; + describe('core SDK', function () { + beforeEach(function () { + client.post(urls.events, 200); + mockServer$d = sinon$2.createFakeServer(); + mockServer$d.respondImmediately = true; + mockServer$d.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$d.reset(); + mParticle._resetForTests(MPConfig); + client.restore(); + sinon$2.restore(); + }); + it('starts new session', function (done) { + mParticle.startNewSession(); + var sessionStartEvent = findEventFromRequest$7(client._calls, 'session_start'); + sessionStartEvent.should.be.ok(); + sessionStartEvent.data.should.have.property('session_uuid'); + done(); + }); + it('sessionIds are all capital letters', function (done) { + var lowercaseLetters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; + var sessionId = mParticle.sessionManager.getSession(); + var lowercaseLetterExists; + sessionId.split('').forEach(function (letter) { + if (lowercaseLetters.indexOf(letter) > -1) { + lowercaseLetterExists = true; + } + }); + Should(lowercaseLetterExists).not.be.ok(); + done(); + }); + it('ends existing session with an event that includes SessionLength', function (done) { + mParticle.startNewSession(); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + sessionEndEvent.should.be.ok(); + sessionEndEvent.data.should.have.property('session_duration_ms'); + done(); + }); + it('creates a new dateLastEventSent when logging an event, and retains the previous one when ending session', function (done) { + mParticle.logEvent('Test Event1'); + var testEvent1 = findEventFromRequest$7(client._calls, 'Test Event1'); + setTimeout(function () { + mParticle.logEvent('Test Event2'); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + var result1 = testEvent1.data.timestamp_unixtime_ms === testEvent2.data.timestamp_unixtime_ms; + var result2 = testEvent2.data.timestamp_unixtime_ms === sessionEndEvent.data.timestamp_unixtime_ms; + Should(result1).not.be.ok(); + Should(result2).be.ok(); + done(); + }, 5); + }); + it('should process ready queue when initialized', function (done) { + var readyFuncCalled = false; + mParticle._resetForTests(MPConfig); + mParticle.ready(function () { + readyFuncCalled = true; + }); + mParticle.init(apiKey, window.mParticle.config); + Should(readyFuncCalled).equal(true); + done(); + }); + it('should set app version', function (done) { + mParticle.setAppVersion('1.0'); + window.mParticle.logEvent('Test Event', mParticle.EventType.Navigation); + var testEventBatch = findBatch$6(client._calls, 'Test Event'); + testEventBatch.application_info.should.have.property('application_version', '1.0'); + done(); + }); + it('should get app version', function (done) { + mParticle.setAppVersion('2.0'); + var appVersion = mParticle.getAppVersion(); + appVersion.should.equal('2.0'); + done(); + }); + it('should get environment setting when set to `production`', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, _objectSpread(_objectSpread({}, window.mParticle.config), {}, { + isDevelopmentMode: false + })); + mParticle.getEnvironment().should.equal('production'); + done(); + }); + it('should get environment setting when set to `development`', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, _objectSpread(_objectSpread({}, window.mParticle.config), {}, { + isDevelopmentMode: true + })); + mParticle.getEnvironment().should.equal('development'); + done(); + }); + it('should get app version from config', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.appName = "testAppName"; + mParticle.init(apiKey, window.mParticle.config); + var appName = mParticle.getAppName(); + appName.should.equal('testAppName'); + done(); + }); + it('should send new appName via event payload', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.appName = 'newAppName'; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.application_info.should.have.property('application_name', 'newAppName'); + done(); + }); + it('should allow app name to be changed via setAppName', function (done) { + mParticle._resetForTests(MPConfig); + var newConfig = _objectSpread(_objectSpread({}, window.mParticle.config), {}, { + appName: 'OverrideTestName' + }); + mParticle.init(apiKey, newConfig); + var appName = mParticle.getAppName(); + appName.should.equal('OverrideTestName'); + done(); + }); + it('should set Package Name on Batch Payload', function (done) { + mParticle.config["package"] = 'my-web-package'; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.have.property('application_info'); + batch.application_info.should.have.property('package', 'my-web-package'); + done(); + }); + it('should sanitize event attributes', function (done) { + mParticle.logEvent('sanitized event', 1, { + key1: 'value1', + mydate: new Date(), + ishouldberemoved: { + test: 'test' + }, + ishouldalsoberemoved: ['test'], + removeme: new Error() + }); + var sanitizedEvent = findEventFromRequest$7(client._calls, 'sanitized event'); + sanitizedEvent.data.custom_attributes.should.have.property('key1', 'value1'); + sanitizedEvent.data.custom_attributes.should.have.property('mydate'); + sanitizedEvent.data.custom_attributes.should.not.have.property('ishouldberemoved'); + sanitizedEvent.data.custom_attributes.should.not.have.property('ishouldalsoberemoved'); + sanitizedEvent.data.custom_attributes.should.not.have.property('removeme'); + done(); + }); + it('sanitizes attributes when attrs are provided', function (done) { + var attrs = { + valid: '123', + invalid: ['123', '345'] + }; + var product = mParticle.eCommerce.createProduct('name', 'sku', 100, 1, 'variant', 'category', 'brand', 'position', 'coupon', attrs); + product.Attributes.should.not.have.property('invalid'); + product.Attributes.should.have.property('valid'); + mParticle.eCommerce.logCheckout(1, 'visa', attrs); + var checkoutEvent = findEventFromRequest$7(client._calls, 'checkout'); + checkoutEvent.data.custom_attributes.should.not.have.property('invalid'); + checkoutEvent.data.custom_attributes.should.have.property('valid'); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, product, attrs); + var addToCartEvent = findEventFromRequest$7(client._calls, 'add_to_cart'); + addToCartEvent.data.custom_attributes.should.not.have.property('invalid'); + addToCartEvent.data.custom_attributes.should.have.property('valid'); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mockServer$d.requests = []; + mParticle.eCommerce.logPurchase(transactionAttributes, product, false, attrs); + var purchaseEvent = findEventFromRequest$7(client._calls, 'purchase'); + purchaseEvent.data.custom_attributes.should.not.have.property('invalid'); + purchaseEvent.data.custom_attributes.should.have.property('valid'); + var promotion = mParticle.eCommerce.createPromotion('id', 'creative', 'name', 'position'); + mockServer$d.requests = []; + mParticle.eCommerce.logPromotion(1, promotion, attrs); + var promotionViewEvent = findEventFromRequest$7(client._calls, 'view'); + promotionViewEvent.data.custom_attributes.should.not.have.property('invalid'); + promotionViewEvent.data.custom_attributes.should.have.property('valid'); + mockServer$d.requests = []; + mParticle.eCommerce.logRefund(transactionAttributes, product, false, attrs); + var refundEvent = findEventFromRequest$7(client._calls, 'refund'); + refundEvent.data.custom_attributes.should.not.have.property('invalid'); + refundEvent.data.custom_attributes.should.have.property('valid'); + done(); + }); + it('should not generate a new device ID if a deviceId exists in localStorage', function (done) { + mParticle._resetForTests(MPConfig); + setLocalStorage$4(); + mParticle.init(apiKey, window.mParticle.config); + var deviceId = mParticle.getDeviceId(); + deviceId.should.equal(das); + done(); + }); + it('should return the deviceId when requested', function (done) { + var deviceId = mParticle.getDeviceId(); + Should(deviceId).be.ok(); + deviceId.length.should.equal(36); + done(); + }); + it('will create a cgid when no previous cgid exists after initializing storage, and no sid', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.getInstance()._Store.storageName = TestsCore.workspaceCookieName; + mParticle.getInstance()._Persistence.initializeStorage(); + mParticle.getInstance()._Persistence.update(); + var cookieData = mParticle.getInstance()._Persistence.getLocalStorage(); + cookieData.gs.should.have.properties(['cgid']); + cookieData.gs.should.not.have.property('sid'); + done(); + }); + it('creates a new session when elapsed time between actions is greater than session timeout', function (done) { + mParticle._resetForTests(MPConfig); + var clock = sinon$2.useFakeTimers(); + mParticle.config.sessionTimeout = 1; + mParticle.init(apiKey, window.mParticle.config); + clock.tick(100); + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + clock.tick(70000); + mParticle.logEvent('Test Event2'); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + testEvent.data.session_uuid.should.not.equal(testEvent2.data.session_uuid); + mParticle.getInstance()._SessionManager.clearSessionTimeout(); + clock.restore(); + done(); + }); + it('should end session when last event sent is outside of sessionTimeout', function (done) { + mParticle._resetForTests(MPConfig); + var clock = sinon$2.useFakeTimers(); + mParticle.config.sessionTimeout = 1; + mParticle.init(apiKey, window.mParticle.config); + clock.tick(100); + mParticle.logEvent('Test Event'); + clock.tick(10000); + mParticle.logEvent('Test Event2'); + clock.tick(120000); + mParticle.logEvent('Test Event3'); + clock.tick(150000); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + var testEvent3 = findEventFromRequest$7(client._calls, 'Test Event3'); + testEvent2.data.session_uuid.should.equal(testEvent.data.session_uuid); + testEvent3.data.session_uuid.should.not.equal(testEvent.data.session_uuid); + clock.restore(); + done(); + }); + it('should not end session when end session is called within sessionTimeout timeframe', function (done) { + // This test mimics if another tab is open and events are sent, but previous tab's sessionTimeout is still ongoing + mParticle._resetForTests(MPConfig); + var clock = sinon$2.useFakeTimers(); + mParticle.config.sessionTimeout = 1; + mParticle.init(apiKey, window.mParticle.config); + mockServer$d.requests = []; + clock.tick(100); + mParticle.logEvent('Test Event'); + + // This clock tick initiates a session end event that is successful + clock.tick(70000); + var sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + Should(sessionEndEvent).be.ok(); + client._calls = []; + clock.tick(100); + mParticle.logEvent('Test Event2'); + var sid = mParticle.getInstance()._Persistence.getLocalStorage().gs.sid; + var new_Persistence = { + gs: { + sid: sid, + ie: 1, + les: 120000 + } + }; + setLocalStorage$4(workspaceCookieName, new_Persistence); + // // This clock tick initiates a session end event that is not successful + clock.tick(70000); + sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + Should(sessionEndEvent).not.be.ok(); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + mParticle.logEvent('Test Event3'); + var testEvent3 = findEventFromRequest$7(client._calls, 'Test Event3'); + testEvent3.data.session_uuid.should.equal(testEvent2.data.session_uuid); + clock.restore(); + done(); + }); + it('should get sessionId', function (done) { + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + var sessionId = mParticle.getInstance()._SessionManager.getSession(); + testEvent.data.session_uuid.should.equal(sessionId); + done(); + }); + it('should set session start date in dto', function (done) { + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + testEvent.data.session_start_unixtime_ms.should.be.above(0); + done(); + }); + it('should update session start date when manually ending session then starting a new one', function (done) { + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + var testEventSessionStartTime = testEvent.data.session_start_unixtime_ms; + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + var sessionEndEventSessionStartDate = sessionEndEvent.data.session_start_unixtime_ms; + sessionEndEventSessionStartDate.should.equal(testEventSessionStartTime); + mParticle.logEvent('Test Event2'); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + var testEvent2SessionStartDate = testEvent2.data.session_start_unixtime_ms; + testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate); + done(); + }); + it('should update session start date when session times out,then starting a new one', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.sessionTimeout = 1; + var clock = sinon$2.useFakeTimers(); + mParticle.init(apiKey, mParticle.config); + clock.tick(10); + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + var testEventSessionStartDate = testEvent.data.session_start_unixtime_ms; + + // trigger session timeout which ends session automatically + clock.tick(60000); + + // note to self - session end event not being triggered, could be the same bug + var sessionEndEvent = findEventFromRequest$7(client._calls, 'session_end'); + var sessionEndEventSessionStartDate = sessionEndEvent.data.session_start_unixtime_ms; + sessionEndEventSessionStartDate.should.equal(testEventSessionStartDate); + clock.tick(100); + mParticle.logEvent('Test Event2'); + var testEvent2 = findEventFromRequest$7(client._calls, 'Test Event2'); + var testEvent2SessionStartDate = testEvent2.data.session_start_unixtime_ms; + testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate); + clock.restore(); + done(); + }); + it('should load SDK with the included api on init and not send events to previous apikey in persistence', function (done) { + mParticle.logEvent('Test Event1'); + var testEvent1URL = findRequest(client._calls, 'Test Event1')[0]; + testEvent1URL.should.equal(urls.events); + client.post('https://jssdks.mparticle.com/v3/JS/new-api-key/events', 200); + mParticle.init('new-api-key', window.mParticle.config); + mParticle.logEvent('Test Event2'); + var testEvent2URL = findRequestURL(client._calls, 'Test Event2'); + testEvent2URL.should.equal('https://jssdks.mparticle.com/v3/JS/new-api-key/events'); + done(); + }); + it('should have default options as well as configured options on configuration object, overwriting when appropriate', function (done) { + var defaults = new Store({}, mParticle.getInstance()); + // all items here should be the default values + for (var key in DefaultConfig) { + defaults.SDKConfig.should.have.property(key, DefaultConfig[key]); + } + var config = { + useCookieStorage: true, + logLevel: 'abc', + useNativeSdk: true, + isIOS: true, + maxProducts: 10, + maxCookieSize: 2000, + appName: 'testApp', + integrationDelayTimeout: 100, + identifyRequest: { + userIdentities: { + customerid: 'test' } + }, + identityCallback: function identityCallback() { + return 'identityCallback'; + }, + appVersion: 'v2.0.0', + sessionTimeout: 3000, + forceHttps: false, + customFlags: { + flag1: 'attr1' + }, + workspaceToken: 'abcdef', + requiredWebviewBridgeName: 'exampleWebviewBridgeName', + minWebviewBridgeVersion: 2, + aliasMaxWindow: 3 + }; + var mp = new Store(config, mParticle.getInstance()); + mp.isEnabled.should.equal(true); + Object.keys(mp.sessionAttributes).length.should.equal(0); + Object.keys(mp.serverSettings).length.should.equal(0); + Object.keys(mp.nonCurrentUserMPIDs).length.should.equal(0); + Object.keys(mp.integrationAttributes).length.should.equal(0); + Object.keys(mp.cookieSyncDates).length.should.equal(0); + mp.currentSessionMPIDs.length.should.equal(0); + mp.isTracking.should.equal(false); + mp.cartProducts.length.should.equal(0); + mp.eventQueue.length.should.equal(0); + mp.identityCallInFlight.should.equal(false); + mp.identifyCalled.should.equal(false); + mp.isLoggedIn.should.equal(false); + mp.requireDelay.should.equal(true); + mp.activeForwarders.length.should.equal(0); + (mp.consentState === null).should.equal(true); + (mp.context === null).should.equal(true); + (mp.sessionId === null).should.equal(true); + (mp.isFirstRun === null).should.equal(true); + (mp.clientId === null).should.equal(true); + (mp.deviceId === null).should.equal(true); + (mp.devToken === null).should.equal(true); + (mp.dateLastEventSent === null).should.equal(true); + (mp.sessionStartDate === null).should.equal(true); + (mp.currentPosition === null).should.equal(true); + (mp.watchPositionId === null).should.equal(true); + (mp.currencyCode === null).should.equal(true); + (mp.globalTimer === null).should.equal(true); + (mp.isLocalStorageAvailable === null).should.equal(true); + + // all items here should be the overwritten values + mp.SDKConfig.useCookieStorage.should.equal(config.useCookieStorage); + mp.SDKConfig.useNativeSdk.should.equal(config.useNativeSdk); + mp.SDKConfig.isIOS.should.equal(config.isIOS); + mp.SDKConfig.maxProducts.should.equal(config.maxProducts); + mp.SDKConfig.maxCookieSize.should.equal(config.maxCookieSize); + mp.SDKConfig.appName.should.equal(config.appName); + mp.SDKConfig.integrationDelayTimeout.should.equal(config.integrationDelayTimeout); + JSON.stringify(mp.SDKConfig.identifyRequest).should.equal(JSON.stringify(config.identifyRequest)); + mp.SDKConfig.identityCallback().should.equal(config.identityCallback()); + mp.SDKConfig.appVersion.should.equal(config.appVersion); + mp.SDKConfig.sessionTimeout.should.equal(3000); + mp.SDKConfig.forceHttps.should.equal(config.forceHttps); + mp.SDKConfig.customFlags.should.equal(config.customFlags); + mp.SDKConfig.workspaceToken.should.equal(config.workspaceToken); + mp.SDKConfig.requiredWebviewBridgeName.should.equal(config.requiredWebviewBridgeName); + mp.SDKConfig.minWebviewBridgeVersion.should.equal(config.minWebviewBridgeVersion); + mp.SDKConfig.aliasMaxWindow.should.equal(config.aliasMaxWindow); + mParticle._resetForTests(MPConfig); + done(); + }); + it('should use custom loggers when provided', function (done) { + mParticle.config.logLevel = 'verbose'; + var errorMessage; + var warnMessage; + var infoMessage; + mParticle.config.logger = { + error: function error(msg) { + errorMessage = msg; + }, + warning: function warning(msg) { + warnMessage = msg; + }, + verbose: function verbose(msg) { + infoMessage = msg; + } + }; + mParticle.init(apiKey, window.mParticle.config); + infoMessage.should.equal('Batch count: 1'); + mParticle.eCommerce.createProduct(); + errorMessage.should.equal('Name is required when creating a product'); + mParticle.startTrackingLocation(); + warnMessage.should.equal('Warning: Location tracking is triggered, but not including a callback into the `startTrackingLocation` may result in events logged too quickly and not being associated with a location.'); + done(); + }); + it('should be able to change logLevel on the fly, postuse custom loggers when provided', function (done) { + var infoMessages = []; + mParticle.config.logger = { + verbose: function verbose(msg) { + infoMessages.push(msg); + } + }; + mParticle.init(apiKey, window.mParticle.config); + infoMessages.length.should.equal(0); + mParticle.setLogLevel('verbose'); + mParticle.logEvent('hi'); + infoMessages[0].should.equal('Starting to log event: hi'); + done(); + }); + it("should not log anything to console when logLevel = 'none'", function (done) { + var infoMessages = []; + var warnMessages = []; + var errorMessages = []; + mParticle.config.logger = { + error: function error(msg) { + errorMessages.push(msg); + }, + warning: function warning(msg) { + warnMessages.push(msg); + }, + verbose: function verbose(msg) { + infoMessages.push(msg); + } + }; + mParticle.init(apiKey, window.mParticle.config); + infoMessages.length.should.equal(0); + warnMessages.length.should.equal(0); + errorMessages.length.should.equal(0); + mParticle.setLogLevel('none'); + mParticle.logEvent('Test Event'); + infoMessages.length.should.equal(0); + warnMessages.length.should.equal(0); + errorMessages.length.should.equal(0); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + Should(testEvent).be.ok(); + done(); + }); + it('should not error when logger custom loggers when provided', function (done) { + /* Previously the Store was initialized before Logger, and since Store contains Logger, and it would throw. + This no longer throws because Store takes the Logger as an argument, which is now initialized first. + */ + mParticle.config.logLevel = 'verbose'; + delete mParticle.config.workspaceToken; // no workspace token would previously make the Store fail to Log this fact + + var warnMessage; + mParticle.config.logger = { + warning: function warning(msg) { + warnMessage = msg; + } + }; + mParticle.init(apiKey, window.mParticle.config); + warnMessage.should.equal('You should have a workspaceToken on your config object for security purposes.'); + done(); + }); + it('should use default urls if no custom urls are set in config object', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.SDKConfig.v1SecureServiceUrl.should.equal(Constants.DefaultUrls.v1SecureServiceUrl); + mParticle.getInstance()._Store.SDKConfig.v2SecureServiceUrl.should.equal(Constants.DefaultUrls.v2SecureServiceUrl); + mParticle.getInstance()._Store.SDKConfig.v3SecureServiceUrl.should.equal(Constants.DefaultUrls.v3SecureServiceUrl); + mParticle.getInstance()._Store.SDKConfig.configUrl.should.equal(Constants.DefaultUrls.configUrl); + mParticle.getInstance()._Store.SDKConfig.identityUrl.should.equal(Constants.DefaultUrls.identityUrl); + mParticle.getInstance()._Store.SDKConfig.aliasUrl.should.equal(Constants.DefaultUrls.aliasUrl); + done(); + }); + it('should have default urls if no custom urls are set in config object, but use custom urls when they are set', function (done) { + window.mParticle.config.v3SecureServiceUrl = 'testtesttest-custom-v3secureserviceurl/v3/JS/'; + window.mParticle.config.configUrl = 'foo-custom-configUrl/v2/JS/'; + window.mParticle.config.identityUrl = 'custom-identityUrl/'; + window.mParticle.config.aliasUrl = 'custom-aliasUrl/'; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.SDKConfig.v3SecureServiceUrl.should.equal(window.mParticle.config.v3SecureServiceUrl); + mParticle.getInstance()._Store.SDKConfig.configUrl.should.equal(window.mParticle.config.configUrl); + mParticle.getInstance()._Store.SDKConfig.identityUrl.should.equal(window.mParticle.config.identityUrl); + mParticle.getInstance()._Store.SDKConfig.aliasUrl.should.equal(window.mParticle.config.aliasUrl); + + // test events endpoint + mParticle.logEvent('Test Event'); + var testEventURL = findRequestURL(client._calls, 'Test Event'); + testEventURL.should.equal('https://' + window.mParticle.config.v3SecureServiceUrl + 'test_key/events'); + + // test Identity endpoint + mockServer$d.requests = []; + mParticle.Identity.login({ + userIdentities: { + customerid: 'test1' + } + }); + mockServer$d.requests[0].url.should.equal('https://' + window.mParticle.config.identityUrl + 'login'); + + // test alias endpoint + mockServer$d.requests = []; + mParticle.Identity.aliasUsers({ + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4 + }); + mockServer$d.requests[0].url.should.equal('https://' + window.mParticle.config.aliasUrl + 'test_key/Alias'); + done(); + }); + it('should use configUrl when specified on config object', function (done) { + mParticle.config.configUrl = 'testConfigUrl/'; + mParticle.config.requestConfig = true; + mockServer$d.requests = []; + mParticle.init(apiKey, window.mParticle.config); + mockServer$d.requests[0].url.should.equal('https://testConfigUrl/test_key/config?env=0'); + done(); + }); + it('should use custom v3 endpoint when specified on config object', function (done) { + mParticle.config.v3SecureServiceUrl = 'def-v3SecureServiceUrl/v3/JS/'; + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + client.post('https://def-v3SecureServiceUrl/v3/JS/test_key/events', 200); + mParticle.init(apiKey, mParticle.config); + mockServer$d.requests = []; + mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + client.lastOptions().body.should.be.ok(); + done(); + }); + it('should add onCreateBatch to _Store.SDKConfig if onCreateBatch is provide on mParticle.config object', function (done) { + window.mParticle._resetForTests(); + mParticle.config.onCreateBatch = function (batch) { + return batch; + }; + mParticle.init(apiKey, mParticle.config); + _typeof(mParticle.getInstance()._Store.SDKConfig.onCreateBatch).should.equal('function'); + done(); + }); + it('should not add onCreateBatch to _Store.SDKConfig if it is not a function', function (done) { + window.mParticle._resetForTests(); + mParticle.config.onCreateBatch = 'not a function'; + mParticle.init(apiKey, mParticle.config); + _typeof(mParticle.getInstance()._Store.SDKConfig.onCreateBatch).should.equal('undefined'); + done(); + }); + it('should hit url with query parameter of env=1 for debug mode for forwarders', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = true; + mParticle.config.requestConfig = true; + mockServer$d.requests = []; + mParticle.init(apiKey, window.mParticle.config); + (mockServer$d.requests[0].url.indexOf('?env=1') > 0).should.equal(true); + mockServer$d.requests = []; + mParticle.config.requestConfig = true; + mParticle.config.isDevelopmentMode = false; + mParticle.init(apiKey, window.mParticle.config); + (mockServer$d.requests[0].url.indexOf('?env=0') > 0).should.equal(true); + done(); + }); - return calls; - }, - - calledBefore: function calledBefore(proxy) { - if (!this.called) { - return false; - } + // TODO - there are no actual tests here....what's going on? + it('should fetch from /config and keep everything properly on the store', function (done) { + mParticle._resetForTests(MPConfig); + var config = { + appName: 'appNameTest', + minWebviewBridgeVersion: 1, + workspaceToken: 'token1' + }; + mockServer$d.respondWith(urls.config, [200, {}, JSON.stringify(config)]); + window.mParticle.config.requestConfig = true; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.SDKConfig.appName = config.appName; + mParticle.getInstance()._Store.SDKConfig.minWebviewBridgeVersion = config.minWebviewBridgeVersion; + mParticle.getInstance()._Store.SDKConfig.workspaceToken = config.workspaceToken; + localStorage.removeItem(config.workspaceToken); + done(); + }); + it('should initialize and log events even with a failed /config fetch and empty config', function (done) { + // this instance occurs when self hosting and the user only passes an object into init + mParticle._resetForTests(MPConfig); + mockServer$d.respondWith(urls.identify, [400, {}, JSON.stringify('')]); + + // force config to be only requestConfig = true; + delete window.mParticle.config.kitConfigs; + delete window.mParticle.config.isDevelopmentMode; + delete window.mParticle.config.logLevel; + delete window.mParticle.config.workspaceToken; + delete window.mParticle.config.requestConfig; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.isInitialized.should.equal(true); - if (!proxy.called) { - return true; - } + // have to manually call identify although it was called as part of init because we can only mock the server response once + mockServer$d.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1' + })]); + mParticle.Identity.identify({ + userIdentities: { + customerid: 'test' + } + }); + mParticle.logEvent('Test Event'); + var testEvent = findEventFromRequest$7(client._calls, 'Test Event'); + testEvent.should.be.ok(); + done(); + }); + it('should initialize without a config object passed to init', function (done) { + // this instance occurs when self hosting and the user only passes an object into init + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey); + mParticle.getInstance()._Store.isInitialized.should.equal(true); + done(); + }); + it('should generate hash both on the mparticle instance and the mparticle instance manager', function (done) { + var hashValue = -1146196832; + var hash1 = mParticle.generateHash('TestHash'); + var hash2 = mParticle.getInstance().generateHash('TestHash'); + hash1.should.equal(hashValue); + hash2.should.equal(hashValue); + done(); + }); + it('should remove localstorage when calling reset', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.workspaceToken = 'defghi'; + mParticle.init(apiKey, window.mParticle.config); + var ls = localStorage.getItem('mprtcl-v4_defghi'); + ls.should.be.ok(); + mParticle.reset(); + ls = localStorage.getItem('mprtcl-v4_defghi'); + (ls === null).should.equal(true); + done(); + }); + it('should remove cookies when calling reset', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.useCookieStorage = true; + window.mParticle.config.workspaceToken = 'defghi'; + mParticle.init(apiKey, window.mParticle.config); + var cookie = document.cookie; + cookie.includes('mprtcl-v4_defghi').should.equal(true); + mParticle.reset(); + cookie = document.cookie; + cookie.includes('mprtcl-v4_defghi').should.equal(false); + window.mParticle.config.useCookieStorage = false; + done(); + }); + it('should queue setCurrencyCode successfully when SDK is not yet initialized, and then later initialized', function (done) { + mParticle._resetForTests(MPConfig); + // mock a non-initialized state + mParticle.getInstance()._Store.isInitialized = false; - return this.callIds[0] < proxy.callIds[proxy.callIds.length - 1]; - }, + // when SDK is not yet initialized, this will add to the ready queue + mParticle.eCommerce.setCurrencyCode('USD'); - calledAfter: function calledAfter(proxy) { - if (!this.called || !proxy.called) { - return false; - } + // initializing SDK will flush the ready queue and setCurrencyCode should not throw an error + mParticle.init(apiKey, window.mParticle.config); + done(); + }); + it('should set a device id when calling setDeviceId', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + // this das should be the SDK auto generated one, which is 36 characters long + mParticle.getDeviceId().length.should.equal(36); + mParticle.setDeviceId('foo-guid'); + mParticle.getDeviceId().should.equal('foo-guid'); + done(); + }); + it('should set a device id when set on mParticle.config', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.deviceId = 'foo-guid'; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getDeviceId().should.equal('foo-guid'); + done(); + }); + it('should not set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called if init not called', function (done) { + mParticle._resetForTests(MPConfig); + mParticle._setWrapperSDKInfo('flutter', '1.0.3'); + mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none'); + (mParticle.getInstance()._Store.wrapperSDKInfo.version === null).should.equal(true); + mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(false); + done(); + }); + it('should have the correct wrapper sdk info default values when init is called', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none'); + (mParticle.getInstance()._Store.wrapperSDKInfo.version === null).should.equal(true); + mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(false); + done(); + }); + it('should set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called after init is called', function (done) { + mParticle._resetForTests(MPConfig); + mParticle._setWrapperSDKInfo('flutter', '1.0.3'); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('flutter'); + mParticle.getInstance()._Store.wrapperSDKInfo.version.should.equal('1.0.3'); + mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(true); + done(); + }); + it('should not set the wrapper sdk info in Store after it has previously been set', function (done) { + mParticle._resetForTests(MPConfig); + mParticle._setWrapperSDKInfo('flutter', '1.0.3'); + mParticle.init(apiKey, window.mParticle.config); + mParticle._setWrapperSDKInfo('none', '2.0.5'); + mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('flutter'); + mParticle.getInstance()._Store.wrapperSDKInfo.version.should.equal('1.0.3'); + mParticle.getInstance()._Store.wrapperSDKInfo.isInfoSet.should.equal(true); + done(); + }); + }); - return this.callIds[this.callCount - 1] > proxy.callIds[0]; - }, + /****************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise, SuppressedError, Symbol */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + + function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + } + + typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; - calledImmediatelyBefore: function calledImmediatelyBefore(proxy) { - if (!this.called || !proxy.called) { - return false; - } + /* Sinon.JS 16.1.0, 2023-10-05, @license BSD-3 */let sinon;(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t);}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i sandbox.leakThreshold && - !loggedLeakWarning - ) { - // eslint-disable-next-line no-console - logger.printWarning( - "Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox." - ); - loggedLeakWarning = true; - } - } + verifyIsValidAssertion(name, args); - sandbox.assert = sinonAssert.createAssertObject(); + if (typeof meth === "function") { + failed = !meth(fake); + } else { + failed = + typeof fake[meth] === "function" + ? !fake[meth].apply(fake, args) + : !fake[meth]; + } - sandbox.serverPrototype = fakeServer; + if (failed) { + failAssertion( + this, + (fake.printf || fake.proxy.printf).apply( + fake, + concat([msg], args) + ) + ); + } else { + assert.pass(name); + } + }; + } - // this is for testing only - sandbox.getFakes = function getFakes() { - return collection; - }; + function exposedName(prefix, prop) { + return !prefix || /^fail/.test(prop) + ? prop + : prefix + + stringSlice(prop, 0, 1).toUpperCase() + + stringSlice(prop, 1); + } - sandbox.createStubInstance = function createStubInstance() { - const stubbed = sinonCreateStubInstance.apply(null, arguments); + mirrorPropAsAssertion( + "called", + "expected %n to have been called at least once but was never called" + ); + mirrorPropAsAssertion( + "notCalled", + function (spy) { + return !spy.called; + }, + "expected %n to not have been called but was called %c%C" + ); + mirrorPropAsAssertion( + "calledOnce", + "expected %n to be called once but was called %c%C" + ); + mirrorPropAsAssertion( + "calledTwice", + "expected %n to be called twice but was called %c%C" + ); + mirrorPropAsAssertion( + "calledThrice", + "expected %n to be called thrice but was called %c%C" + ); + mirrorPropAsAssertion( + "calledOn", + "expected %n to be called with %1 as this but was called with %t" + ); + mirrorPropAsAssertion( + "alwaysCalledOn", + "expected %n to always be called with %1 as this but was called with %t" + ); + mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new"); + mirrorPropAsAssertion( + "alwaysCalledWithNew", + "expected %n to always be called with new" + ); + mirrorPropAsAssertion( + "calledWith", + "expected %n to be called with arguments %D" + ); + mirrorPropAsAssertion( + "calledWithMatch", + "expected %n to be called with match %D" + ); + mirrorPropAsAssertion( + "alwaysCalledWith", + "expected %n to always be called with arguments %D" + ); + mirrorPropAsAssertion( + "alwaysCalledWithMatch", + "expected %n to always be called with match %D" + ); + mirrorPropAsAssertion( + "calledWithExactly", + "expected %n to be called with exact arguments %D" + ); + mirrorPropAsAssertion( + "calledOnceWithExactly", + "expected %n to be called once and with exact arguments %D" + ); + mirrorPropAsAssertion( + "calledOnceWithMatch", + "expected %n to be called once and with match %D" + ); + mirrorPropAsAssertion( + "alwaysCalledWithExactly", + "expected %n to always be called with exact arguments %D" + ); + mirrorPropAsAssertion( + "neverCalledWith", + "expected %n to never be called with arguments %*%C" + ); + mirrorPropAsAssertion( + "neverCalledWithMatch", + "expected %n to never be called with match %*%C" + ); + mirrorPropAsAssertion("threw", "%n did not throw exception%C"); + mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C"); - const ownMethods = collectOwnMethods(stubbed); + return assert; + } - forEach(ownMethods, function (method) { - addToCollection(method); - }); + module.exports = createAssertObject(); + module.exports.createAssertObject = createAssertObject; - usePromiseLibrary(promiseLib, ownMethods); + },{"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],4:[function(require,module,exports){ - return stubbed; - }; + const arrayProto = require("@sinonjs/commons").prototypes.array; + const extend = require("./util/core/extend"); + const functionName = require("@sinonjs/commons").functionName; + const nextTick = require("./util/core/next-tick"); + const valueToString = require("@sinonjs/commons").valueToString; + const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); - sandbox.inject = function inject(obj) { - obj.spy = function () { - return sandbox.spy.apply(null, arguments); - }; + const concat = arrayProto.concat; + const join = arrayProto.join; + const reverse = arrayProto.reverse; + const slice = arrayProto.slice; - obj.stub = function () { - return sandbox.stub.apply(null, arguments); - }; + const useLeftMostCallback = -1; + const useRightMostCallback = -2; - obj.mock = function () { - return sandbox.mock.apply(null, arguments); - }; + function getCallback(behavior, args) { + const callArgAt = behavior.callArgAt; - obj.createStubInstance = function () { - return sandbox.createStubInstance.apply(sandbox, arguments); - }; + if (callArgAt >= 0) { + return args[callArgAt]; + } - obj.fake = function () { - return sandbox.fake.apply(null, arguments); - }; + let argumentList; - obj.define = function () { - return sandbox.define.apply(null, arguments); - }; + if (callArgAt === useLeftMostCallback) { + argumentList = args; + } - obj.replace = function () { - return sandbox.replace.apply(null, arguments); - }; + if (callArgAt === useRightMostCallback) { + argumentList = reverse(slice(args)); + } - obj.replaceSetter = function () { - return sandbox.replaceSetter.apply(null, arguments); - }; + const callArgProp = behavior.callArgProp; - obj.replaceGetter = function () { - return sandbox.replaceGetter.apply(null, arguments); - }; - - if (sandbox.clock) { - obj.clock = sandbox.clock; + for (let i = 0, l = argumentList.length; i < l; ++i) { + if (!callArgProp && typeof argumentList[i] === "function") { + return argumentList[i]; } - if (sandbox.server) { - obj.server = sandbox.server; - obj.requests = sandbox.server.requests; + if ( + callArgProp && + argumentList[i] && + typeof argumentList[i][callArgProp] === "function" + ) { + return argumentList[i][callArgProp]; } + } - obj.match = match; + return null; + } - return obj; - }; + function getCallbackError(behavior, func, args) { + if (behavior.callArgAt < 0) { + let msg; - sandbox.mock = function mock() { - const m = sinonMock.apply(null, arguments); + if (behavior.callArgProp) { + msg = `${functionName( + behavior.stub + )} expected to yield to '${valueToString( + behavior.callArgProp + )}', but no object with such a property was passed.`; + } else { + msg = `${functionName( + behavior.stub + )} expected to yield, but no callback was passed.`; + } - addToCollection(m); - usePromiseLibrary(promiseLib, m); + if (args.length > 0) { + msg += ` Received [${join(args, ", ")}]`; + } - return m; - }; + return msg; + } - sandbox.reset = function reset() { - applyOnEach(collection, "reset"); - applyOnEach(collection, "resetHistory"); - }; + return `argument at index ${behavior.callArgAt} is not a function: ${func}`; + } - sandbox.resetBehavior = function resetBehavior() { - applyOnEach(collection, "resetBehavior"); - }; + function ensureArgs(name, behavior, args) { + // map function name to internal property + // callsArg => callArgAt + const property = name.replace(/sArg/, "ArgAt"); + const index = behavior[property]; - sandbox.resetHistory = function resetHistory() { - function privateResetHistory(f) { - const method = f.resetHistory || f.reset; - if (method) { - method.call(f); - } - } + if (index >= args.length) { + throw new TypeError( + `${name} failed: ${index + 1} arguments required but only ${ + args.length + } present` + ); + } + } - forEach(collection, privateResetHistory); - }; + function callCallback(behavior, args) { + if (typeof behavior.callArgAt === "number") { + ensureArgs("callsArg", behavior, args); + const func = getCallback(behavior, args); - sandbox.restore = function restore() { - if (arguments.length) { - throw new Error( - "sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()" - ); + if (typeof func !== "function") { + throw new TypeError(getCallbackError(behavior, func, args)); } - reverse(collection); - applyOnEach(collection, "restore"); - collection = []; + if (behavior.callbackAsync) { + nextTick(function () { + func.apply( + behavior.callbackContext, + behavior.callbackArguments + ); + }); + } else { + return func.apply( + behavior.callbackContext, + behavior.callbackArguments + ); + } + } - forEach(fakeRestorers, function (restorer) { - restorer(); - }); - fakeRestorers = []; + return undefined; + } - sandbox.restoreContext(); - }; + const proto = { + create: function create(stub) { + const behavior = extend({}, proto); + delete behavior.create; + delete behavior.addBehavior; + delete behavior.createBehavior; + behavior.stub = stub; - sandbox.restoreContext = function restoreContext() { - if (!sandbox.injectedKeys) { - return; + if (stub.defaultBehavior && stub.defaultBehavior.promiseLibrary) { + behavior.promiseLibrary = stub.defaultBehavior.promiseLibrary; } - forEach(sandbox.injectedKeys, function (injectedKey) { - delete sandbox.injectInto[injectedKey]; - }); + return behavior; + }, - sandbox.injectedKeys.length = 0; - }; + isPresent: function isPresent() { + return ( + typeof this.callArgAt === "number" || + this.exception || + this.exceptionCreator || + typeof this.returnArgAt === "number" || + this.returnThis || + typeof this.resolveArgAt === "number" || + this.resolveThis || + typeof this.throwArgAt === "number" || + this.fakeFn || + this.returnValueDefined + ); + }, - /** - * Creates a restorer function for the property - * - * @param {object|Function} object - * @param {string} property - * @param {boolean} forceAssignment - * @returns {Function} restorer function - */ - function getFakeRestorer(object, property, forceAssignment = false) { - const descriptor = getPropertyDescriptor(object, property); - const value = object[property]; + /*eslint complexity: ["error", 20]*/ + invoke: function invoke(context, args) { + /* + * callCallback (conditionally) calls ensureArgs + * + * Note: callCallback intentionally happens before + * everything else and cannot be moved lower + */ + const returnValue = callCallback(this, args); - function restorer() { - if (forceAssignment) { - object[property] = value; - } else if (descriptor?.isOwn) { - Object.defineProperty(object, property, descriptor); - } else { - delete object[property]; - } + if (this.exception) { + throw this.exception; + } else if (this.exceptionCreator) { + this.exception = this.exceptionCreator(); + this.exceptionCreator = undefined; + throw this.exception; + } else if (typeof this.returnArgAt === "number") { + ensureArgs("returnsArg", this, args); + return args[this.returnArgAt]; + } else if (this.returnThis) { + return context; + } else if (typeof this.throwArgAt === "number") { + ensureArgs("throwsArg", this, args); + throw args[this.throwArgAt]; + } else if (this.fakeFn) { + return this.fakeFn.apply(context, args); + } else if (typeof this.resolveArgAt === "number") { + ensureArgs("resolvesArg", this, args); + return (this.promiseLibrary || Promise).resolve( + args[this.resolveArgAt] + ); + } else if (this.resolveThis) { + return (this.promiseLibrary || Promise).resolve(context); + } else if (this.resolve) { + return (this.promiseLibrary || Promise).resolve(this.returnValue); + } else if (this.reject) { + return (this.promiseLibrary || Promise).reject(this.returnValue); + } else if (this.callsThrough) { + const wrappedMethod = this.effectiveWrappedMethod(); + + return wrappedMethod.apply(context, args); + } else if (this.callsThroughWithNew) { + // Get the original method (assumed to be a constructor in this case) + const WrappedClass = this.effectiveWrappedMethod(); + // Turn the arguments object into a normal array + const argsArray = slice(args); + // Call the constructor + const F = WrappedClass.bind.apply( + WrappedClass, + concat([null], argsArray) + ); + return new F(); + } else if (typeof this.returnValue !== "undefined") { + return this.returnValue; + } else if (typeof this.callArgAt === "number") { + return returnValue; } - restorer.object = object; - restorer.property = property; - return restorer; - } + return this.returnValue; + }, - function verifyNotReplaced(object, property) { - forEach(fakeRestorers, function (fakeRestorer) { - if ( - fakeRestorer.object === object && - fakeRestorer.property === property - ) { - throw new TypeError( - `Attempted to replace ${property} which is already replaced` - ); + effectiveWrappedMethod: function effectiveWrappedMethod() { + for (let stubb = this.stub; stubb; stubb = stubb.parent) { + if (stubb.wrappedMethod) { + return stubb.wrappedMethod; } - }); - } + } + throw new Error("Unable to find wrapped method"); + }, - /** - * Replace an existing property - * - * @param {object|Function} object - * @param {string} property - * @param {*} replacement a fake, stub, spy or any other value - * @returns {*} - */ - sandbox.replace = function replace(object, property, replacement) { - const descriptor = getPropertyDescriptor(object, property); - checkForValidArguments(descriptor, property, replacement); - throwOnAccessors(descriptor); - verifySameType(object, property, replacement); - - verifyNotReplaced(object, property); - - // store a function for restoring the replaced property - push(fakeRestorers, getFakeRestorer(object, property)); - - object[property] = replacement; - - return replacement; - }; + onCall: function onCall(index) { + return this.stub.onCall(index); + }, - sandbox.replace.usingAccessor = function replaceUsingAccessor( - object, - property, - replacement - ) { - const descriptor = getPropertyDescriptor(object, property); - checkForValidArguments(descriptor, property, replacement); - verifySameType(object, property, replacement); + onFirstCall: function onFirstCall() { + return this.stub.onFirstCall(); + }, - verifyNotReplaced(object, property); + onSecondCall: function onSecondCall() { + return this.stub.onSecondCall(); + }, - // store a function for restoring the replaced property - push(fakeRestorers, getFakeRestorer(object, property, true)); + onThirdCall: function onThirdCall() { + return this.stub.onThirdCall(); + }, - object[property] = replacement; + withArgs: function withArgs(/* arguments */) { + throw new Error( + 'Defining a stub by invoking "stub.onCall(...).withArgs(...)" ' + + 'is not supported. Use "stub.withArgs(...).onCall(...)" ' + + "to define sequential behavior for calls with certain arguments." + ); + }, + }; - return replacement; + function createBehavior(behaviorMethod) { + return function () { + this.defaultBehavior = this.defaultBehavior || proto.create(this); + this.defaultBehavior[behaviorMethod].apply( + this.defaultBehavior, + arguments + ); + return this; }; + } - sandbox.define = function define(object, property, value) { - const descriptor = getPropertyDescriptor(object, property); + function addBehavior(stub, name, fn) { + proto[name] = function () { + fn.apply(this, concat([this], slice(arguments))); + return this.stub || this; + }; - if (descriptor) { - throw new TypeError( - `Cannot define the already existing property ${valueToString( - property - )}. Perhaps you meant sandbox.replace()?` - ); - } + stub[name] = createBehavior(name); + } - if (typeof value === "undefined") { - throw new TypeError("Expected value argument to be defined"); - } + proto.addBehavior = addBehavior; + proto.createBehavior = createBehavior; - verifyNotReplaced(object, property); + const asyncBehaviors = exportAsyncBehaviors(proto); - // store a function for restoring the defined property - push(fakeRestorers, getFakeRestorer(object, property)); + module.exports = extend.nonEnum({}, proto, asyncBehaviors); - object[property] = value; + },{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/next-tick":34,"@sinonjs/commons":48}],5:[function(require,module,exports){ - return value; - }; + const walk = require("./util/core/walk"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const push = require("@sinonjs/commons").prototypes.array.push; - sandbox.replaceGetter = function replaceGetter( - object, - property, - replacement + function collectMethod(methods, object, prop, propOwner) { + if ( + typeof getPropertyDescriptor(propOwner, prop).value === "function" && + hasOwnProperty(object, prop) ) { - const descriptor = getPropertyDescriptor(object, property); + push(methods, object[prop]); + } + } - if (typeof descriptor === "undefined") { - throw new TypeError( - `Cannot replace non-existent property ${valueToString( - property - )}` - ); - } + // This function returns an array of all the own methods on the passed object + function collectOwnMethods(object) { + const methods = []; - if (typeof replacement !== "function") { - throw new TypeError( - "Expected replacement argument to be a function" - ); - } + walk(object, collectMethod.bind(null, methods, object)); - if (typeof descriptor.get !== "function") { - throw new Error("`object.property` is not a getter"); - } + return methods; + } - verifyNotReplaced(object, property); + module.exports = collectOwnMethods; - // store a function for restoring the replaced property - push(fakeRestorers, getFakeRestorer(object, property)); + },{"./util/core/get-property-descriptor":29,"./util/core/walk":39,"@sinonjs/commons":48}],6:[function(require,module,exports){ - Object.defineProperty(object, property, { - get: replacement, - configurable: isPropertyConfigurable(object, property), - }); + const supportsColor = require("supports-color"); - return replacement; - }; + function colorize(str, color) { + if (supportsColor.stdout === false) { + return str; + } - sandbox.replaceSetter = function replaceSetter( - object, - property, - replacement - ) { - const descriptor = getPropertyDescriptor(object, property); + return `\x1b[${color}m${str}\x1b[0m`; + } - if (typeof descriptor === "undefined") { - throw new TypeError( - `Cannot replace non-existent property ${valueToString( - property - )}` - ); - } + exports.red = function (str) { + return colorize(str, 31); + }; - if (typeof replacement !== "function") { - throw new TypeError( - "Expected replacement argument to be a function" - ); - } + exports.green = function (str) { + return colorize(str, 32); + }; - if (typeof descriptor.set !== "function") { - throw new Error("`object.property` is not a setter"); - } + exports.cyan = function (str) { + return colorize(str, 96); + }; - verifyNotReplaced(object, property); + exports.white = function (str) { + return colorize(str, 39); + }; - // store a function for restoring the replaced property - push(fakeRestorers, getFakeRestorer(object, property)); + exports.bold = function (str) { + return colorize(str, 1); + }; - // eslint-disable-next-line accessor-pairs - Object.defineProperty(object, property, { - set: replacement, - configurable: isPropertyConfigurable(object, property), - }); + },{"supports-color":150}],7:[function(require,module,exports){ - return replacement; - }; + const arrayProto = require("@sinonjs/commons").prototypes.array; + const Sandbox = require("./sandbox"); - function commonPostInitSetup(args, spy) { - const [object, property, types] = args; + const forEach = arrayProto.forEach; + const push = arrayProto.push; - const isSpyingOnEntireObject = - typeof property === "undefined" && typeof object === "object"; + function prepareSandboxFromConfig(config) { + const sandbox = new Sandbox(); - if (isSpyingOnEntireObject) { - const ownMethods = collectOwnMethods(spy); + if (config.useFakeServer) { + if (typeof config.useFakeServer === "object") { + sandbox.serverPrototype = config.useFakeServer; + } - forEach(ownMethods, function (method) { - addToCollection(method); - }); + sandbox.useFakeServer(); + } - usePromiseLibrary(promiseLib, ownMethods); - } else if (Array.isArray(types)) { - for (const accessorType of types) { - addToCollection(spy[accessorType]); - usePromiseLibrary(promiseLib, spy[accessorType]); - } + if (config.useFakeTimers) { + if (typeof config.useFakeTimers === "object") { + sandbox.useFakeTimers(config.useFakeTimers); } else { - addToCollection(spy); - usePromiseLibrary(promiseLib, spy); + sandbox.useFakeTimers(); } - - return spy; } - sandbox.spy = function spy() { - const createdSpy = sinonSpy.apply(sinonSpy, arguments); - return commonPostInitSetup(arguments, createdSpy); - }; - - sandbox.stub = function stub() { - const createdStub = sinonStub.apply(sinonStub, arguments); - return commonPostInitSetup(arguments, createdStub); - }; + return sandbox; + } - // eslint-disable-next-line no-unused-vars - sandbox.fake = function fake(f) { - const s = sinonFake.apply(sinonFake, arguments); + function exposeValue(sandbox, config, key, value) { + if (!value) { + return; + } - addToCollection(s); + if (config.injectInto && !(key in config.injectInto)) { + config.injectInto[key] = value; + push(sandbox.injectedKeys, key); + } else { + push(sandbox.args, value); + } + } - return s; - }; + function createSandbox(config) { + if (!config) { + return new Sandbox(); + } - forEach(Object.keys(sinonFake), function (key) { - const fakeBehavior = sinonFake[key]; - if (typeof fakeBehavior === "function") { - sandbox.fake[key] = function () { - const s = fakeBehavior.apply(fakeBehavior, arguments); - - addToCollection(s); - - return s; - }; - } - }); + const configuredSandbox = prepareSandboxFromConfig(config); + configuredSandbox.args = configuredSandbox.args || []; + configuredSandbox.injectedKeys = []; + configuredSandbox.injectInto = config.injectInto; + const exposed = configuredSandbox.inject({}); - sandbox.useFakeTimers = function useFakeTimers(args) { - const clock = sinonClock.useFakeTimers.call(null, args); + if (config.properties) { + forEach(config.properties, function (prop) { + const value = + exposed[prop] || (prop === "sandbox" && configuredSandbox); + exposeValue(configuredSandbox, config, prop, value); + }); + } else { + exposeValue(configuredSandbox, config, "sandbox"); + } - sandbox.clock = clock; - addToCollection(clock); + return configuredSandbox; + } - return clock; - }; + module.exports = createSandbox; - sandbox.verify = function verify() { - applyOnEach(collection, "verify"); - }; + },{"./sandbox":19,"@sinonjs/commons":48}],8:[function(require,module,exports){ - sandbox.verifyAndRestore = function verifyAndRestore() { - let exception; + const stub = require("./stub"); + const sinonType = require("./util/core/sinon-type"); + const forEach = require("@sinonjs/commons").prototypes.array.forEach; - try { - sandbox.verify(); - } catch (e) { - exception = e; - } + function isStub(value) { + return sinonType.get(value) === "stub"; + } - sandbox.restore(); + module.exports = function createStubInstance(constructor, overrides) { + if (typeof constructor !== "function") { + throw new TypeError("The constructor should be a function."); + } - if (exception) { - throw exception; - } - }; + const stubInstance = Object.create(constructor.prototype); + sinonType.set(stubInstance, "stub-instance"); - sandbox.useFakeServer = function useFakeServer() { - const proto = sandbox.serverPrototype || fakeServer; + const stubbedObject = stub(stubInstance); - if (!proto || !proto.create) { - return null; + forEach(Object.keys(overrides || {}), function (propertyName) { + if (propertyName in stubbedObject) { + const value = overrides[propertyName]; + if (isStub(value)) { + stubbedObject[propertyName] = value; + } else { + stubbedObject[propertyName].returns(value); + } + } else { + throw new Error( + `Cannot stub ${propertyName}. Property does not exist!` + ); } + }); + return stubbedObject; + }; - sandbox.server = proto.create(); - addToCollection(sandbox.server); + },{"./stub":22,"./util/core/sinon-type":35,"@sinonjs/commons":48}],9:[function(require,module,exports){ - return sandbox.server; - }; + const arrayProto = require("@sinonjs/commons").prototypes.array; + const isPropertyConfigurable = require("./util/core/is-property-configurable"); + const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); + const extend = require("./util/core/extend"); - sandbox.useFakeXMLHttpRequest = function useFakeXMLHttpRequest() { - const xhr = fakeXhr.useFakeXMLHttpRequest(); - addToCollection(xhr); - return xhr; - }; + const slice = arrayProto.slice; - sandbox.usingPromise = function usingPromise(promiseLibrary) { - promiseLib = promiseLibrary; - collection.promiseLibrary = promiseLibrary; + const useLeftMostCallback = -1; + const useRightMostCallback = -2; - return sandbox; - }; + function throwsException(fake, error, message) { + if (typeof error === "function") { + fake.exceptionCreator = error; + } else if (typeof error === "string") { + fake.exceptionCreator = function () { + const newException = new Error( + message || `Sinon-provided ${error}` + ); + newException.name = error; + return newException; + }; + } else if (!error) { + fake.exceptionCreator = function () { + return new Error("Error"); + }; + } else { + fake.exception = error; + } } - Sandbox.prototype.match = match; + const defaultBehaviors = { + callsFake: function callsFake(fake, fn) { + fake.fakeFn = fn; + fake.exception = undefined; + fake.exceptionCreator = undefined; + }, - module.exports = Sandbox; + callsArg: function callsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } - },{"./assert":3,"./collect-own-methods":5,"./create-stub-instance":8,"./fake":10,"./mock":12,"./spy":21,"./stub":22,"./util/core/get-property-descriptor":29,"./util/core/is-property-configurable":32,"./util/core/use-promise-library":37,"./util/fake-timers":41,"@sinonjs/commons":48,"@sinonjs/samsam":88,"nise":128}],20:[function(require,module,exports){ + fake.callArgAt = index; + fake.callbackArguments = []; + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, - const arrayProto = require("@sinonjs/commons").prototypes.array; - const color = require("./color"); - const match = require("@sinonjs/samsam").createMatcher; - const timesInWords = require("./util/core/times-in-words"); - const inspect = require("util").inspect; - const jsDiff = require("diff"); + callsArgOn: function callsArgOn(fake, index, context) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } - const join = arrayProto.join; - const map = arrayProto.map; - const push = arrayProto.push; - const slice = arrayProto.slice; + fake.callArgAt = index; + fake.callbackArguments = []; + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, - function colorSinonMatchText(matcher, calledArg, calledArgMessage) { - let calledArgumentMessage = calledArgMessage; - let matcherMessage = matcher.message; - if (!matcher.test(calledArg)) { - matcherMessage = color.red(matcher.message); - if (calledArgumentMessage) { - calledArgumentMessage = color.green(calledArgumentMessage); + callsArgWith: function callsArgWith(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); } - } - return `${calledArgumentMessage} ${matcherMessage}`; - } - function colorDiffText(diff) { - const objects = map(diff, function (part) { - let text = part.value; - if (part.added) { - text = color.green(text); - } else if (part.removed) { - text = color.red(text); - } - if (diff.length === 2) { - text += " "; // format simple diffs + fake.callArgAt = index; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, + + callsArgOnWith: function callsArgWith(fake, index, context) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); } - return text; - }); - return join(objects, ""); - } - function quoteStringValue(value) { - if (typeof value === "string") { - return JSON.stringify(value); - } - return value; - } + fake.callArgAt = index; + fake.callbackArguments = slice(arguments, 3); + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + }, - module.exports = { - c: function (spyInstance) { - return timesInWords(spyInstance.callCount); + usingPromise: function usingPromise(fake, promiseLibrary) { + fake.promiseLibrary = promiseLibrary; }, - n: function (spyInstance) { - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - return spyInstance.toString(); + yields: function (fake) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 1); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; }, - D: function (spyInstance, args) { - let message = ""; + yieldsRight: function (fake) { + fake.callArgAt = useRightMostCallback; + fake.callbackArguments = slice(arguments, 1); + fake.callbackContext = undefined; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, - for (let i = 0, l = spyInstance.callCount; i < l; ++i) { - // describe multiple calls - if (l > 1) { - message += `\nCall ${i + 1}:`; - } - const calledArgs = spyInstance.getCall(i).args; - const expectedArgs = slice(args); + yieldsOn: function (fake, context) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = context; + fake.callArgProp = undefined; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, - for ( - let j = 0; - j < calledArgs.length || j < expectedArgs.length; - ++j - ) { - let calledArg = calledArgs[j]; - let expectedArg = expectedArgs[j]; - if (calledArg) { - calledArg = quoteStringValue(calledArg); - } - - if (expectedArg) { - expectedArg = quoteStringValue(expectedArg); - } + yieldsTo: function (fake, prop) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 2); + fake.callbackContext = undefined; + fake.callArgProp = prop; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, - message += "\n"; + yieldsToOn: function (fake, prop, context) { + fake.callArgAt = useLeftMostCallback; + fake.callbackArguments = slice(arguments, 3); + fake.callbackContext = context; + fake.callArgProp = prop; + fake.callbackAsync = false; + fake.fakeFn = undefined; + }, - const calledArgMessage = - j < calledArgs.length ? inspect(calledArg) : ""; - if (match.isMatcher(expectedArg)) { - message += colorSinonMatchText( - expectedArg, - calledArg, - calledArgMessage - ); - } else { - const expectedArgMessage = - j < expectedArgs.length ? inspect(expectedArg) : ""; - const diff = jsDiff.diffJson( - calledArgMessage, - expectedArgMessage - ); - message += colorDiffText(diff); - } - } - } + throws: throwsException, + throwsException: throwsException, - return message; + returns: function returns(fake, value) { + fake.returnValue = value; + fake.resolve = false; + fake.reject = false; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; }, - C: function (spyInstance) { - const calls = []; - - for (let i = 0, l = spyInstance.callCount; i < l; ++i) { - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - let stringifiedCall = ` ${spyInstance.getCall(i).toString()}`; - if (/\n/.test(calls[i - 1])) { - stringifiedCall = `\n${stringifiedCall}`; - } - push(calls, stringifiedCall); + returnsArg: function returnsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); } - return calls.length > 0 ? `\n${join(calls, "\n")}` : ""; + fake.returnArgAt = index; }, - t: function (spyInstance) { - const objects = []; - - for (let i = 0, l = spyInstance.callCount; i < l; ++i) { - push(objects, inspect(spyInstance.thisValues[i])); + throwsArg: function throwsArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); } - return join(objects, ", "); + fake.throwArgAt = index; }, - "*": function (spyInstance, args) { - return join( - map(args, function (arg) { - return inspect(arg); - }), - ", " - ); + returnsThis: function returnsThis(fake) { + fake.returnThis = true; }, - }; - - },{"./color":6,"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"diff":114,"util":113}],21:[function(require,module,exports){ - const arrayProto = require("@sinonjs/commons").prototypes.array; - const createProxy = require("./proxy"); - const extend = require("./util/core/extend"); - const functionName = require("@sinonjs/commons").functionName; - const getPropertyDescriptor = require("./util/core/get-property-descriptor"); - const deepEqual = require("@sinonjs/samsam").deepEqual; - const isEsModule = require("./util/core/is-es-module"); - const proxyCallUtil = require("./proxy-call-util"); - const walkObject = require("./util/core/walk-object"); - const wrapMethod = require("./util/core/wrap-method"); - const valueToString = require("@sinonjs/commons").valueToString; + resolves: function resolves(fake, value) { + fake.returnValue = value; + fake.resolve = true; + fake.resolveThis = false; + fake.reject = false; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, - /* cache references to library methods so that they also can be stubbed without problems */ - const forEach = arrayProto.forEach; - const pop = arrayProto.pop; - const push = arrayProto.push; - const slice = arrayProto.slice; - const filter = Array.prototype.filter; + resolvesArg: function resolvesArg(fake, index) { + if (typeof index !== "number") { + throw new TypeError("argument index is not number"); + } + fake.resolveArgAt = index; + fake.returnValue = undefined; + fake.resolve = true; + fake.resolveThis = false; + fake.reject = false; + fake.returnValueDefined = false; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, - let uuid = 0; + rejects: function rejects(fake, error, message) { + let reason; + if (typeof error === "string") { + reason = new Error(message || ""); + reason.name = error; + } else if (!error) { + reason = new Error("Error"); + } else { + reason = error; + } + fake.returnValue = reason; + fake.resolve = false; + fake.resolveThis = false; + fake.reject = true; + fake.returnValueDefined = true; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; - function matches(fake, args, strict) { - const margs = fake.matchingArguments; - if ( - margs.length <= args.length && - deepEqual(slice(args, 0, margs.length), margs) - ) { - return !strict || margs.length === args.length; - } - return false; - } + return fake; + }, - // Public API - const spyApi = { - withArgs: function () { - const args = slice(arguments); - const matching = pop(this.matchingFakes(args, true)); - if (matching) { - return matching; - } + resolvesThis: function resolvesThis(fake) { + fake.returnValue = undefined; + fake.resolve = false; + fake.resolveThis = true; + fake.reject = false; + fake.returnValueDefined = false; + fake.exception = undefined; + fake.exceptionCreator = undefined; + fake.fakeFn = undefined; + }, - const original = this; - const fake = this.instantiateFake(); - fake.matchingArguments = args; - fake.parent = this; - push(this.fakes, fake); + callThrough: function callThrough(fake) { + fake.callsThrough = true; + }, - fake.withArgs = function () { - return original.withArgs.apply(original, arguments); - }; + callThroughWithNew: function callThroughWithNew(fake) { + fake.callsThroughWithNew = true; + }, - forEach(original.args, function (arg, i) { - if (!matches(fake, arg)) { - return; - } + get: function get(fake, getterFunction) { + const rootStub = fake.stub || fake; - proxyCallUtil.incrementCallCount(fake); - push(fake.thisValues, original.thisValues[i]); - push(fake.args, arg); - push(fake.returnValues, original.returnValues[i]); - push(fake.exceptions, original.exceptions[i]); - push(fake.callIds, original.callIds[i]); + Object.defineProperty(rootStub.rootObj, rootStub.propName, { + get: getterFunction, + configurable: isPropertyConfigurable( + rootStub.rootObj, + rootStub.propName + ), }); - proxyCallUtil.createCallProperties(fake); + return fake; + }, + + set: function set(fake, setterFunction) { + const rootStub = fake.stub || fake; + + Object.defineProperty( + rootStub.rootObj, + rootStub.propName, + // eslint-disable-next-line accessor-pairs + { + set: setterFunction, + configurable: isPropertyConfigurable( + rootStub.rootObj, + rootStub.propName + ), + } + ); return fake; }, - // Override proxy default implementation - matchingFakes: function (args, strict) { - return filter.call(this.fakes, function (fake) { - return matches(fake, args, strict); + value: function value(fake, newVal) { + const rootStub = fake.stub || fake; + + Object.defineProperty(rootStub.rootObj, rootStub.propName, { + value: newVal, + enumerable: true, + writable: true, + configurable: + rootStub.shadowsPropOnPrototype || + isPropertyConfigurable(rootStub.rootObj, rootStub.propName), }); + + return fake; }, }; - /* eslint-disable @sinonjs/no-prototype-methods/no-prototype-methods */ - const delegateToCalls = proxyCallUtil.delegateToCalls; - delegateToCalls(spyApi, "callArg", false, "callArgWith", true, function () { - throw new Error( - `${this.toString()} cannot call arg since it was not yet invoked.` - ); - }); - spyApi.callArgWith = spyApi.callArg; - delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", true, function () { - throw new Error( - `${this.toString()} cannot call arg since it was not yet invoked.` - ); - }); - spyApi.callArgOnWith = spyApi.callArgOn; - delegateToCalls(spyApi, "throwArg", false, "throwArg", false, function () { - throw new Error( - `${this.toString()} cannot throw arg since it was not yet invoked.` - ); - }); - delegateToCalls(spyApi, "yield", false, "yield", true, function () { - throw new Error( - `${this.toString()} cannot yield since it was not yet invoked.` - ); - }); - // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. - spyApi.invokeCallback = spyApi.yield; - delegateToCalls(spyApi, "yieldOn", false, "yieldOn", true, function () { - throw new Error( - `${this.toString()} cannot yield since it was not yet invoked.` - ); - }); - delegateToCalls(spyApi, "yieldTo", false, "yieldTo", true, function (property) { - throw new Error( - `${this.toString()} cannot yield to '${valueToString( - property - )}' since it was not yet invoked.` - ); - }); - delegateToCalls( - spyApi, - "yieldToOn", - false, - "yieldToOn", - true, - function (property) { - throw new Error( - `${this.toString()} cannot yield to '${valueToString( - property - )}' since it was not yet invoked.` - ); - } - ); - - function createSpy(func) { - let name; - let funk = func; + const asyncBehaviors = exportAsyncBehaviors(defaultBehaviors); - if (typeof funk !== "function") { - funk = function () { - return; - }; - } else { - name = functionName(funk); - } + module.exports = extend({}, defaultBehaviors, asyncBehaviors); - const proxy = createProxy(funk, funk); + },{"./util/core/export-async-behaviors":25,"./util/core/extend":26,"./util/core/is-property-configurable":32,"@sinonjs/commons":48}],10:[function(require,module,exports){ - // Inherit spy API: - extend.nonEnum(proxy, spyApi); - extend.nonEnum(proxy, { - displayName: name || "spy", - fakes: [], - instantiateFake: createSpy, - id: `spy#${uuid++}`, - }); - return proxy; - } + const arrayProto = require("@sinonjs/commons").prototypes.array; + const createProxy = require("./proxy"); + const nextTick = require("./util/core/next-tick"); - function spy(object, property, types) { - if (isEsModule(object)) { - throw new TypeError("ES Modules cannot be spied"); - } + const slice = arrayProto.slice; + let promiseLib = Promise; - if (!property && typeof object === "function") { - return createSpy(object); - } + module.exports = fake; - if (!property && typeof object === "object") { - return walkObject(spy, object); + /** + * Returns a `fake` that records all calls, arguments and return values. + * + * When an `f` argument is supplied, this implementation will be used. + * + * @example + * // create an empty fake + * var f1 = sinon.fake(); + * + * f1(); + * + * f1.calledOnce() + * // true + * + * @example + * function greet(greeting) { + * console.log(`Hello ${greeting}`); + * } + * + * // create a fake with implementation + * var f2 = sinon.fake(greet); + * + * // Hello world + * f2("world"); + * + * f2.calledWith("world"); + * // true + * + * @param {Function|undefined} f + * @returns {Function} + * @namespace + */ + function fake(f) { + if (arguments.length > 0 && typeof f !== "function") { + throw new TypeError("Expected f argument to be a Function"); } - if (!object && !property) { - return createSpy(function () { - return; - }); - } + return wrapFunc(f); + } - if (!types) { - return wrapMethod(object, property, createSpy(object[property])); + /** + * Creates a `fake` that returns the provided `value`, as well as recording all + * calls, arguments and return values. + * + * @example + * var f1 = sinon.fake.returns(42); + * + * f1(); + * // 42 + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.returns = function returns(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return value; } - const descriptor = {}; - const methodDesc = getPropertyDescriptor(object, property); - - forEach(types, function (type) { - descriptor[type] = createSpy(methodDesc[type]); - }); + return wrapFunc(f); + }; - return wrapMethod(object, property, descriptor); - } + /** + * Creates a `fake` that throws an Error. + * If the `value` argument does not have Error in its prototype chain, it will + * be used for creating a new error. + * + * @example + * var f1 = sinon.fake.throws("hello"); + * + * f1(); + * // Uncaught Error: hello + * + * @example + * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); + * + * f2(); + * // Uncaught TypeError: Invalid argument + * + * @memberof fake + * @param {*|Error} value + * @returns {Function} + */ + fake.throws = function throws(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + throw getError(value); + } - extend(spy, spyApi); - module.exports = spy; + return wrapFunc(f); + }; - },{"./proxy":17,"./proxy-call-util":14,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48,"@sinonjs/samsam":88}],22:[function(require,module,exports){ + /** + * Creates a `fake` that returns a promise that resolves to the passed `value` + * argument. + * + * @example + * var f1 = sinon.fake.resolves("apple pie"); + * + * await f1(); + * // "apple pie" + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.resolves = function resolves(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return promiseLib.resolve(value); + } - const arrayProto = require("@sinonjs/commons").prototypes.array; - const behavior = require("./behavior"); - const behaviors = require("./default-behaviors"); - const createProxy = require("./proxy"); - const functionName = require("@sinonjs/commons").functionName; - const hasOwnProperty = - require("@sinonjs/commons").prototypes.object.hasOwnProperty; - const isNonExistentProperty = require("./util/core/is-non-existent-property"); - const spy = require("./spy"); - const extend = require("./util/core/extend"); - const getPropertyDescriptor = require("./util/core/get-property-descriptor"); - const isEsModule = require("./util/core/is-es-module"); - const sinonType = require("./util/core/sinon-type"); - const wrapMethod = require("./util/core/wrap-method"); - const throwOnFalsyObject = require("./throw-on-falsy-object"); - const valueToString = require("@sinonjs/commons").valueToString; - const walkObject = require("./util/core/walk-object"); + return wrapFunc(f); + }; - const forEach = arrayProto.forEach; - const pop = arrayProto.pop; - const slice = arrayProto.slice; - const sort = arrayProto.sort; + /** + * Creates a `fake` that returns a promise that rejects to the passed `value` + * argument. When `value` does not have Error in its prototype chain, it will be + * wrapped in an Error. + * + * @example + * var f1 = sinon.fake.rejects(":("); + * + * try { + * await ft(); + * } catch (error) { + * console.log(error); + * // ":(" + * } + * + * @memberof fake + * @param {*} value + * @returns {Function} + */ + fake.rejects = function rejects(value) { + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + return promiseLib.reject(getError(value)); + } - let uuid = 0; + return wrapFunc(f); + }; - function createStub(originalFunc) { - // eslint-disable-next-line prefer-const - let proxy; + /** + * Causes `fake` to use a custom Promise implementation, instead of the native + * Promise implementation. + * + * @example + * const bluebird = require("bluebird"); + * sinon.fake.usingPromise(bluebird); + * + * @memberof fake + * @param {*} promiseLibrary + * @returns {Function} + */ + fake.usingPromise = function usingPromise(promiseLibrary) { + promiseLib = promiseLibrary; + return fake; + }; - function functionStub() { - const args = slice(arguments); - const matchings = proxy.matchingFakes(args); + /** + * Returns a `fake` that calls the callback with the defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * // "apple*pie" + * + * @memberof fake + * @returns {Function} + */ + fake.yields = function yields() { + const values = slice(arguments); - const fnStub = - pop( - sort(matchings, function (a, b) { - return ( - a.matchingArguments.length - b.matchingArguments.length - ); - }) - ) || proxy; - return getCurrentBehavior(fnStub).invoke(this, arguments); + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + const callback = arguments[arguments.length - 1]; + if (typeof callback !== "function") { + throw new TypeError("Expected last argument to be a function"); + } + + callback.apply(null, values); } - proxy = createProxy(functionStub, originalFunc || functionStub); - // Inherit spy API: - extend.nonEnum(proxy, spy); - // Inherit stub API: - extend.nonEnum(proxy, stub); + return wrapFunc(f); + }; - const name = originalFunc ? functionName(originalFunc) : null; - extend.nonEnum(proxy, { - fakes: [], - instantiateFake: createStub, - displayName: name || "stub", - defaultBehavior: null, - behaviors: [], - id: `stub#${uuid++}`, - }); + /** + * Returns a `fake` that calls the callback **asynchronously** with the + * defined arguments. + * + * @example + * function callback() { + * console.log(arguments.join("*")); + * } + * + * const f1 = sinon.fake.yields("apple", "pie"); + * + * f1(callback); + * + * setTimeout(() => { + * // "apple*pie" + * }); + * + * @memberof fake + * @returns {Function} + */ + fake.yieldsAsync = function yieldsAsync() { + const values = slice(arguments); - sinonType.set(proxy, "stub"); + // eslint-disable-next-line jsdoc/require-jsdoc + function f() { + const callback = arguments[arguments.length - 1]; + if (typeof callback !== "function") { + throw new TypeError("Expected last argument to be a function"); + } + nextTick(function () { + callback.apply(null, values); + }); + } + + return wrapFunc(f); + }; + + let uuid = 0; + /** + * Creates a proxy (sinon concept) from the passed function. + * + * @private + * @param {Function} f + * @returns {Function} + */ + function wrapFunc(f) { + const fakeInstance = function () { + let firstArg, lastArg; + + if (arguments.length > 0) { + firstArg = arguments[0]; + lastArg = arguments[arguments.length - 1]; + } + + const callback = + lastArg && typeof lastArg === "function" ? lastArg : undefined; + + /* eslint-disable no-use-before-define */ + proxy.firstArg = firstArg; + proxy.lastArg = lastArg; + proxy.callback = callback; + + return f && f.apply(this, arguments); + }; + const proxy = createProxy(fakeInstance, f || fakeInstance); + + proxy.displayName = "fake"; + proxy.id = `fake#${uuid++}`; return proxy; } - function stub(object, property) { - if (arguments.length > 2) { - throw new TypeError( - "stub(obj, 'meth', fn) has been removed, see documentation" - ); - } + /** + * Returns an Error instance from the passed value, if the value is not + * already an Error instance. + * + * @private + * @param {*} value [description] + * @returns {Error} [description] + */ + function getError(value) { + return value instanceof Error ? value : new Error(value); + } - if (isEsModule(object)) { - throw new TypeError("ES Modules cannot be stubbed"); - } + },{"./proxy":17,"./util/core/next-tick":34,"@sinonjs/commons":48}],11:[function(require,module,exports){ - throwOnFalsyObject.apply(null, arguments); + const arrayProto = require("@sinonjs/commons").prototypes.array; + const proxyInvoke = require("./proxy-invoke"); + const proxyCallToString = require("./proxy-call").toString; + const timesInWords = require("./util/core/times-in-words"); + const extend = require("./util/core/extend"); + const match = require("@sinonjs/samsam").createMatcher; + const stub = require("./stub"); + const assert = require("./assert"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const inspect = require("util").inspect; + const valueToString = require("@sinonjs/commons").valueToString; - if (isNonExistentProperty(object, property)) { - throw new TypeError( - `Cannot stub non-existent property ${valueToString(property)}` - ); + const every = arrayProto.every; + const forEach = arrayProto.forEach; + const push = arrayProto.push; + const slice = arrayProto.slice; + + function callCountInWords(callCount) { + if (callCount === 0) { + return "never called"; } - const actualDescriptor = getPropertyDescriptor(object, property); + return `called ${timesInWords(callCount)}`; + } - assertValidPropertyDescriptor(actualDescriptor, property); + function expectedCallCountInWords(expectation) { + const min = expectation.minCalls; + const max = expectation.maxCalls; - const isObjectOrFunction = - typeof object === "object" || typeof object === "function"; - const isStubbingEntireObject = - typeof property === "undefined" && isObjectOrFunction; - const isCreatingNewStub = !object && typeof property === "undefined"; - const isStubbingNonFuncProperty = - isObjectOrFunction && - typeof property !== "undefined" && - (typeof actualDescriptor === "undefined" || - typeof actualDescriptor.value !== "function"); + if (typeof min === "number" && typeof max === "number") { + let str = timesInWords(min); - if (isStubbingEntireObject) { - return walkObject(stub, object); + if (min !== max) { + str = `at least ${str} and at most ${timesInWords(max)}`; + } + + return str; } - if (isCreatingNewStub) { - return createStub(); + if (typeof min === "number") { + return `at least ${timesInWords(min)}`; } - const func = - typeof actualDescriptor.value === "function" - ? actualDescriptor.value - : null; - const s = createStub(func); + return `at most ${timesInWords(max)}`; + } - extend.nonEnum(s, { - rootObj: object, - propName: property, - shadowsPropOnPrototype: !actualDescriptor.isOwn, - restore: function restore() { - if (actualDescriptor !== undefined && actualDescriptor.isOwn) { - Object.defineProperty(object, property, actualDescriptor); - return; - } + function receivedMinCalls(expectation) { + const hasMinLimit = typeof expectation.minCalls === "number"; + return !hasMinLimit || expectation.callCount >= expectation.minCalls; + } - delete object[property]; - }, - }); + function receivedMaxCalls(expectation) { + if (typeof expectation.maxCalls !== "number") { + return false; + } - return isStubbingNonFuncProperty ? s : wrapMethod(object, property, s); + return expectation.callCount === expectation.maxCalls; } - function assertValidPropertyDescriptor(descriptor, property) { - if (!descriptor || !property) { - return; - } - if (descriptor.isOwn && !descriptor.configurable && !descriptor.writable) { - throw new TypeError( - `Descriptor for property ${property} is non-configurable and non-writable` - ); - } - if ((descriptor.get || descriptor.set) && !descriptor.configurable) { - throw new TypeError( - `Descriptor for accessor property ${property} is non-configurable` - ); - } - if (isDataDescriptor(descriptor) && !descriptor.writable) { - throw new TypeError( - `Descriptor for data property ${property} is non-writable` - ); - } - } - - function isDataDescriptor(descriptor) { - return ( - !descriptor.value && - !descriptor.writable && - !descriptor.set && - !descriptor.get - ); - } + function verifyMatcher(possibleMatcher, arg) { + const isMatcher = match.isMatcher(possibleMatcher); - /*eslint-disable no-use-before-define*/ - function getParentBehaviour(stubInstance) { - return stubInstance.parent && getCurrentBehavior(stubInstance.parent); + return (isMatcher && possibleMatcher.test(arg)) || true; } - function getDefaultBehavior(stubInstance) { - return ( - stubInstance.defaultBehavior || - getParentBehaviour(stubInstance) || - behavior.create(stubInstance) - ); - } + const mockExpectation = { + minCalls: 1, + maxCalls: 1, - function getCurrentBehavior(stubInstance) { - const currentBehavior = stubInstance.behaviors[stubInstance.callCount - 1]; - return currentBehavior && currentBehavior.isPresent() - ? currentBehavior - : getDefaultBehavior(stubInstance); - } - /*eslint-enable no-use-before-define*/ + create: function create(methodName) { + const expectation = extend.nonEnum(stub(), mockExpectation); + delete expectation.create; + expectation.method = methodName; - const proto = { - resetBehavior: function () { - this.defaultBehavior = null; - this.behaviors = []; + return expectation; + }, - delete this.returnValue; - delete this.returnArgAt; - delete this.throwArgAt; - delete this.resolveArgAt; - delete this.fakeFn; - this.returnThis = false; - this.resolveThis = false; + invoke: function invoke(func, thisValue, args) { + this.verifyCallAllowed(thisValue, args); - forEach(this.fakes, function (fake) { - fake.resetBehavior(); - }); + return proxyInvoke.apply(this, arguments); }, - reset: function () { - this.resetHistory(); - this.resetBehavior(); + atLeast: function atLeast(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not number`); + } + + if (!this.limitsSet) { + this.maxCalls = null; + this.limitsSet = true; + } + + this.minCalls = num; + + return this; }, - onCall: function onCall(index) { - if (!this.behaviors[index]) { - this.behaviors[index] = behavior.create(this); + atMost: function atMost(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not number`); } - return this.behaviors[index]; + if (!this.limitsSet) { + this.minCalls = null; + this.limitsSet = true; + } + + this.maxCalls = num; + + return this; }, - onFirstCall: function onFirstCall() { - return this.onCall(0); + never: function never() { + return this.exactly(0); }, - onSecondCall: function onSecondCall() { - return this.onCall(1); + once: function once() { + return this.exactly(1); }, - onThirdCall: function onThirdCall() { - return this.onCall(2); + twice: function twice() { + return this.exactly(2); }, - withArgs: function withArgs() { - const fake = spy.withArgs.apply(this, arguments); - if (this.defaultBehavior && this.defaultBehavior.promiseLibrary) { - fake.defaultBehavior = - fake.defaultBehavior || behavior.create(fake); - fake.defaultBehavior.promiseLibrary = - this.defaultBehavior.promiseLibrary; - } - return fake; + thrice: function thrice() { + return this.exactly(3); }, - }; - forEach(Object.keys(behavior), function (method) { - if ( - hasOwnProperty(behavior, method) && - !hasOwnProperty(proto, method) && - method !== "create" && - method !== "invoke" - ) { - proto[method] = behavior.createBehavior(method); - } - }); + exactly: function exactly(num) { + if (typeof num !== "number") { + throw new TypeError(`'${valueToString(num)}' is not a number`); + } - forEach(Object.keys(behaviors), function (method) { - if (hasOwnProperty(behaviors, method) && !hasOwnProperty(proto, method)) { - behavior.addBehavior(stub, method, behaviors[method]); - } - }); + this.atLeast(num); + return this.atMost(num); + }, - extend(stub, proto); - module.exports = stub; + met: function met() { + return !this.failed && receivedMinCalls(this); + }, - },{"./behavior":4,"./default-behaviors":9,"./proxy":17,"./spy":21,"./throw-on-falsy-object":23,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/is-non-existent-property":31,"./util/core/sinon-type":35,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48}],23:[function(require,module,exports){ - const valueToString = require("@sinonjs/commons").valueToString; + verifyCallAllowed: function verifyCallAllowed(thisValue, args) { + const expectedArguments = this.expectedArguments; - function throwOnFalsyObject(object, property) { - if (property && !object) { - const type = object === null ? "null" : "undefined"; - throw new Error( - `Trying to stub property '${valueToString(property)}' of ${type}` - ); - } - } + if (receivedMaxCalls(this)) { + this.failed = true; + mockExpectation.fail( + `${this.method} already called ${timesInWords(this.maxCalls)}` + ); + } - module.exports = throwOnFalsyObject; + if ("expectedThis" in this && this.expectedThis !== thisValue) { + mockExpectation.fail( + `${this.method} called with ${valueToString( + thisValue + )} as thisValue, expected ${valueToString(this.expectedThis)}` + ); + } - },{"@sinonjs/commons":48}],24:[function(require,module,exports){ + if (!("expectedArguments" in this)) { + return; + } - module.exports = { - injectInto: null, - properties: [ - "spy", - "stub", - "mock", - "clock", - "server", - "requests", - "fake", - "define", - "replace", - "replaceSetter", - "replaceGetter", - "createStubInstance", - ], - useFakeTimers: true, - useFakeServer: true, - }; + if (!args) { + mockExpectation.fail( + `${this.method} received no arguments, expected ${inspect( + expectedArguments + )}` + ); + } - },{}],25:[function(require,module,exports){ + if (args.length < expectedArguments.length) { + mockExpectation.fail( + `${this.method} received too few arguments (${inspect( + args + )}), expected ${inspect(expectedArguments)}` + ); + } - const arrayProto = require("@sinonjs/commons").prototypes.array; - const reduce = arrayProto.reduce; + if ( + this.expectsExactArgCount && + args.length !== expectedArguments.length + ) { + mockExpectation.fail( + `${this.method} received too many arguments (${inspect( + args + )}), expected ${inspect(expectedArguments)}` + ); + } - module.exports = function exportAsyncBehaviors(behaviorMethods) { - return reduce( - Object.keys(behaviorMethods), - function (acc, method) { - // need to avoid creating another async versions of the newly added async methods - if (method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { - acc[`${method}Async`] = function () { - const result = behaviorMethods[method].apply( - this, - arguments + forEach( + expectedArguments, + function (expectedArgument, i) { + if (!verifyMatcher(expectedArgument, args[i])) { + mockExpectation.fail( + `${this.method} received wrong arguments ${inspect( + args + )}, didn't match ${String(expectedArguments)}` ); - this.callbackAsync = true; - return result; - }; - } - return acc; - }, - {} - ); - }; - - },{"@sinonjs/commons":48}],26:[function(require,module,exports){ - - const arrayProto = require("@sinonjs/commons").prototypes.array; - const hasOwnProperty = - require("@sinonjs/commons").prototypes.object.hasOwnProperty; + } - const join = arrayProto.join; - const push = arrayProto.push; + if (!deepEqual(args[i], expectedArgument)) { + mockExpectation.fail( + `${this.method} received wrong arguments ${inspect( + args + )}, expected ${inspect(expectedArguments)}` + ); + } + }, + this + ); + }, - // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug - const hasDontEnumBug = (function () { - const obj = { - constructor: function () { - return "0"; - }, - toString: function () { - return "1"; - }, - valueOf: function () { - return "2"; - }, - toLocaleString: function () { - return "3"; - }, - prototype: function () { - return "4"; - }, - isPrototypeOf: function () { - return "5"; - }, - propertyIsEnumerable: function () { - return "6"; - }, - hasOwnProperty: function () { - return "7"; - }, - length: function () { - return "8"; - }, - unique: function () { - return "9"; - }, - }; + allowsCall: function allowsCall(thisValue, args) { + const expectedArguments = this.expectedArguments; - const result = []; - for (const prop in obj) { - if (hasOwnProperty(obj, prop)) { - push(result, obj[prop]()); + if (this.met() && receivedMaxCalls(this)) { + return false; } - } - return join(result, "") !== "0123456789"; - })(); - /** - * - * @param target - * @param sources - * @param doCopy - * @returns {*} target - */ - function extendCommon(target, sources, doCopy) { - let source, i, prop; + if ("expectedThis" in this && this.expectedThis !== thisValue) { + return false; + } - for (i = 0; i < sources.length; i++) { - source = sources[i]; + if (!("expectedArguments" in this)) { + return true; + } - for (prop in source) { - if (hasOwnProperty(source, prop)) { - doCopy(target, source, prop); - } + // eslint-disable-next-line no-underscore-dangle + const _args = args || []; + + if (_args.length < expectedArguments.length) { + return false; } - // Make sure we copy (own) toString method even when in JScript with DontEnum bug - // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug if ( - hasDontEnumBug && - hasOwnProperty(source, "toString") && - source.toString !== target.toString + this.expectsExactArgCount && + _args.length !== expectedArguments.length ) { - target.toString = source.toString; + return false; } - } - - return target; - } - - /** - * Public: Extend target in place with all (own) properties, except 'name' when [[writable]] is false, - * from sources in-order. Thus, last source will override properties in previous sources. - * - * @param {object} target - The Object to extend - * @param {object[]} sources - Objects to copy properties from. - * @returns {object} the extended target - */ - module.exports = function extend(target, ...sources) { - return extendCommon( - target, - sources, - function copyValue(dest, source, prop) { - const destOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( - dest, - prop - ); - const sourceOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( - source, - prop - ); - if (prop === "name" && !destOwnPropertyDescriptor.writable) { - return; + return every(expectedArguments, function (expectedArgument, i) { + if (!verifyMatcher(expectedArgument, _args[i])) { + return false; } - const descriptors = { - configurable: sourceOwnPropertyDescriptor.configurable, - enumerable: sourceOwnPropertyDescriptor.enumerable, - }; - /* - if the sorce has an Accessor property copy over the accessor functions (get and set) - data properties has writable attribute where as accessor property don't - REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties - */ - if (hasOwnProperty(sourceOwnPropertyDescriptor, "writable")) { - descriptors.writable = sourceOwnPropertyDescriptor.writable; - descriptors.value = sourceOwnPropertyDescriptor.value; - } else { - if (sourceOwnPropertyDescriptor.get) { - descriptors.get = - sourceOwnPropertyDescriptor.get.bind(dest); - } - if (sourceOwnPropertyDescriptor.set) { - descriptors.set = - sourceOwnPropertyDescriptor.set.bind(dest); - } + if (!deepEqual(_args[i], expectedArgument)) { + return false; } - Object.defineProperty(dest, prop, descriptors); - } - ); - }; - /** - * Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will - * override properties in previous sources. Define the properties as non enumerable. - * - * @param {object} target - The Object to extend - * @param {object[]} sources - Objects to copy properties from. - * @returns {object} the extended target - */ - module.exports.nonEnum = function extendNonEnum(target, ...sources) { - return extendCommon( - target, - sources, - function copyProperty(dest, source, prop) { - Object.defineProperty(dest, prop, { - value: source[prop], - enumerable: false, - configurable: true, - writable: true, - }); - } - ); - }; + return true; + }); + }, - },{"@sinonjs/commons":48}],27:[function(require,module,exports){ + withArgs: function withArgs() { + this.expectedArguments = slice(arguments); + return this; + }, - module.exports = function toString() { - let i, prop, thisValue; - if (this.getCall && this.callCount) { - i = this.callCount; + withExactArgs: function withExactArgs() { + this.withArgs.apply(this, arguments); + this.expectsExactArgCount = true; + return this; + }, - while (i--) { - thisValue = this.getCall(i).thisValue; + on: function on(thisValue) { + this.expectedThis = thisValue; + return this; + }, - // eslint-disable-next-line guard-for-in - for (prop in thisValue) { - try { - if (thisValue[prop] === this) { - return prop; - } - } catch (e) { - // no-op - accessing props can throw an error, nothing to do here - } - } + toString: function () { + const args = slice(this.expectedArguments || []); + + if (!this.expectsExactArgCount) { + push(args, "[...]"); } - } - return this.displayName || "sinon fake"; - }; + const callStr = proxyCallToString.call({ + proxy: this.method || "anonymous mock expectation", + args: args, + }); - },{}],28:[function(require,module,exports){ + const message = `${callStr.replace( + ", [...", + "[, ..." + )} ${expectedCallCountInWords(this)}`; - /* istanbul ignore next : not testing that setTimeout works */ - function nextTick(callback) { - setTimeout(callback, 0); - } + if (this.met()) { + return `Expectation met: ${message}`; + } - module.exports = function getNextTick(process, setImmediate) { - if (typeof process === "object" && typeof process.nextTick === "function") { - return process.nextTick; - } + return `Expected ${message} (${callCountInWords(this.callCount)})`; + }, - if (typeof setImmediate === "function") { - return setImmediate; - } + verify: function verify() { + if (!this.met()) { + mockExpectation.fail(String(this)); + } else { + mockExpectation.pass(String(this)); + } - return nextTick; - }; + return true; + }, - },{}],29:[function(require,module,exports){ + pass: function pass(message) { + assert.pass(message); + }, - /* eslint-disable jsdoc/valid-types */ - /* - * The following type def is strictly an illegal JSDoc, but the expression forms a - * legal Typescript union type and is understood by Visual Studio and the IntelliJ - * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these - * days for that reason (and the fact that JSDoc is essentially unmaintained) - */ - - /** - * @typedef {{isOwn: boolean} & PropertyDescriptor} SinonPropertyDescriptor - * a slightly enriched property descriptor - * @property {boolean} isOwn true if the descriptor is owned by this object, false if it comes from the prototype - */ - /* eslint-enable jsdoc/valid-types */ - - /** - * Returns a slightly modified property descriptor that one can tell is from the object or the prototype - * - * @param {*} object - * @param {string} property - * @returns {SinonPropertyDescriptor} - */ - function getPropertyDescriptor(object, property) { - let proto = object; - let descriptor; - const isOwn = Boolean( - object && Object.getOwnPropertyDescriptor(object, property) - ); - - while ( - proto && - !(descriptor = Object.getOwnPropertyDescriptor(proto, property)) - ) { - proto = Object.getPrototypeOf(proto); - } + fail: function fail(message) { + const exception = new Error(message); + exception.name = "ExpectationError"; - if (descriptor) { - descriptor.isOwn = isOwn; - } + throw exception; + }, + }; - return descriptor; - } + module.exports = mockExpectation; - module.exports = getPropertyDescriptor; + },{"./assert":3,"./proxy-call":15,"./proxy-invoke":16,"./stub":22,"./util/core/extend":26,"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],12:[function(require,module,exports){ - },{}],30:[function(require,module,exports){ + const arrayProto = require("@sinonjs/commons").prototypes.array; + const mockExpectation = require("./mock-expectation"); + const proxyCallToString = require("./proxy-call").toString; + const extend = require("./util/core/extend"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const wrapMethod = require("./util/core/wrap-method"); + const usePromiseLibrary = require("./util/core/use-promise-library"); - /** - * Verify if an object is a ECMAScript Module - * - * As the exports from a module is immutable we cannot alter the exports - * using spies or stubs. Let the consumer know this to avoid bug reports - * on weird error messages. - * - * @param {object} object The object to examine - * @returns {boolean} true when the object is a module - */ - module.exports = function (object) { - return ( - object && - typeof Symbol !== "undefined" && - object[Symbol.toStringTag] === "Module" && - Object.isSealed(object) - ); - }; + const concat = arrayProto.concat; + const filter = arrayProto.filter; + const forEach = arrayProto.forEach; + const every = arrayProto.every; + const join = arrayProto.join; + const push = arrayProto.push; + const slice = arrayProto.slice; + const unshift = arrayProto.unshift; - },{}],31:[function(require,module,exports){ + function mock(object) { + if (!object || typeof object === "string") { + return mockExpectation.create(object ? object : "Anonymous mock"); + } - /** - * @param {*} object - * @param {string} property - * @returns {boolean} whether a prop exists in the prototype chain - */ - function isNonExistentProperty(object, property) { - return Boolean( - object && typeof property !== "undefined" && !(property in object) - ); + return mock.create(object); } - module.exports = isNonExistentProperty; - - },{}],32:[function(require,module,exports){ + function each(collection, callback) { + const col = collection || []; - const getPropertyDescriptor = require("./get-property-descriptor"); + forEach(col, callback); + } - function isPropertyConfigurable(obj, propName) { - const propertyDescriptor = getPropertyDescriptor(obj, propName); + function arrayEquals(arr1, arr2, compareLength) { + if (compareLength && arr1.length !== arr2.length) { + return false; + } - return propertyDescriptor ? propertyDescriptor.configurable : true; + return every(arr1, function (element, i) { + return deepEqual(arr2[i], element); + }); } - module.exports = isPropertyConfigurable; + extend(mock, { + create: function create(object) { + if (!object) { + throw new TypeError("object is null"); + } - },{"./get-property-descriptor":29}],33:[function(require,module,exports){ + const mockObject = extend.nonEnum({}, mock, { object: object }); + delete mockObject.create; - function isRestorable(obj) { - return ( - typeof obj === "function" && - typeof obj.restore === "function" && - obj.restore.sinon - ); - } + return mockObject; + }, - module.exports = isRestorable; + expects: function expects(method) { + if (!method) { + throw new TypeError("method is falsy"); + } - },{}],34:[function(require,module,exports){ + if (!this.expectations) { + this.expectations = {}; + this.proxies = []; + this.failures = []; + } - const globalObject = require("@sinonjs/commons").global; - const getNextTick = require("./get-next-tick"); + if (!this.expectations[method]) { + this.expectations[method] = []; + const mockObject = this; - module.exports = getNextTick(globalObject.process, globalObject.setImmediate); + wrapMethod(this.object, method, function () { + return mockObject.invokeMethod(method, this, arguments); + }); - },{"./get-next-tick":28,"@sinonjs/commons":48}],35:[function(require,module,exports){ + push(this.proxies, method); + } - const sinonTypeSymbolProperty = Symbol("SinonType"); + const expectation = mockExpectation.create(method); + expectation.wrappedMethod = this.object[method].wrappedMethod; + push(this.expectations[method], expectation); + usePromiseLibrary(this.promiseLibrary, expectation); - module.exports = { - /** - * Set the type of a Sinon object to make it possible to identify it later at runtime - * - * @param {object|Function} object object/function to set the type on - * @param {string} type the named type of the object/function - */ - set(object, type) { - Object.defineProperty(object, sinonTypeSymbolProperty, { - value: type, - configurable: false, - enumerable: false, - }); - }, - get(object) { - return object && object[sinonTypeSymbolProperty]; + return expectation; }, - }; - - },{}],36:[function(require,module,exports){ - const array = [null, "once", "twice", "thrice"]; + restore: function restore() { + const object = this.object; - module.exports = function timesInWords(count) { - return array[count] || `${count || 0} times`; - }; + each(this.proxies, function (proxy) { + if (typeof object[proxy].restore === "function") { + object[proxy].restore(); + } + }); + }, - },{}],37:[function(require,module,exports){ + verify: function verify() { + const expectations = this.expectations || {}; + const messages = this.failures ? slice(this.failures) : []; + const met = []; - const forEach = Array.prototype.forEach; + each(this.proxies, function (proxy) { + each(expectations[proxy], function (expectation) { + if (!expectation.met()) { + push(messages, String(expectation)); + } else { + push(met, String(expectation)); + } + }); + }); - function usePromiseLibrary(library, fakes) { - if (typeof library === "undefined") { - return; - } + this.restore(); - if (Array.isArray(fakes)) { - forEach.call(fakes, usePromiseLibrary.bind(null, library)); + if (messages.length > 0) { + mockExpectation.fail(join(concat(messages, met), "\n")); + } else if (met.length > 0) { + mockExpectation.pass(join(concat(messages, met), "\n")); + } - return; - } + return true; + }, - if (typeof fakes.usingPromise === "function") { - fakes.usingPromise(library); - } - } + usingPromise: function usingPromise(promiseLibrary) { + this.promiseLibrary = promiseLibrary; - module.exports = usePromiseLibrary; + return this; + }, - },{}],38:[function(require,module,exports){ + invokeMethod: function invokeMethod(method, thisValue, args) { + /* if we cannot find any matching files we will explicitly call mockExpection#fail with error messages */ + /* eslint consistent-return: "off" */ + const expectations = + this.expectations && this.expectations[method] + ? this.expectations[method] + : []; + const currentArgs = args || []; + let available; - const functionName = require("@sinonjs/commons").functionName; + const expectationsWithMatchingArgs = filter( + expectations, + function (expectation) { + const expectedArgs = expectation.expectedArguments || []; - const getPropertyDescriptor = require("./get-property-descriptor"); - const walk = require("./walk"); + return arrayEquals( + expectedArgs, + currentArgs, + expectation.expectsExactArgCount + ); + } + ); - /** - * A utility that allows traversing an object, applying mutating functions on the properties - * - * @param {Function} mutator called on each property - * @param {object} object the object we are walking over - * @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property - * @returns {void} nothing - */ - function walkObject(mutator, object, filter) { - let called = false; - const name = functionName(mutator); - - if (!object) { - throw new Error( - `Trying to ${name} object but received ${String(object)}` + const expectationsToApply = filter( + expectationsWithMatchingArgs, + function (expectation) { + return ( + !expectation.met() && + expectation.allowsCall(thisValue, args) + ); + } ); - } - walk(object, function (prop, propOwner) { - // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object - // is not Object.prototype - if ( - propOwner !== Object.prototype && - prop !== "constructor" && - typeof getPropertyDescriptor(propOwner, prop).value === "function" - ) { - if (filter) { - if (filter(object, prop)) { - called = true; - mutator(object, prop); - } + if (expectationsToApply.length > 0) { + return expectationsToApply[0].apply(thisValue, args); + } + + const messages = []; + let exhausted = 0; + + forEach(expectationsWithMatchingArgs, function (expectation) { + if (expectation.allowsCall(thisValue, args)) { + available = available || expectation; } else { - called = true; - mutator(object, prop); + exhausted += 1; } + }); + + if (available && exhausted === 0) { + return available.apply(thisValue, args); } - }); - if (!called) { - throw new Error( - `Found no methods on object to which we could apply mutations` + forEach(expectations, function (expectation) { + push(messages, ` ${String(expectation)}`); + }); + + unshift( + messages, + `Unexpected call: ${proxyCallToString.call({ + proxy: method, + args: args, + })}` ); - } - return object; - } + const err = new Error(); + if (!err.stack) { + // PhantomJS does not serialize the stack trace until the error has been thrown + try { + throw err; + } catch (e) { + /* empty */ + } + } + push( + this.failures, + `Unexpected call: ${proxyCallToString.call({ + proxy: method, + args: args, + stack: err.stack, + })}` + ); - module.exports = walkObject; + mockExpectation.fail(join(messages, "\n")); + }, + }); - },{"./get-property-descriptor":29,"./walk":39,"@sinonjs/commons":48}],39:[function(require,module,exports){ + module.exports = mock; - const forEach = require("@sinonjs/commons").prototypes.array.forEach; + },{"./mock-expectation":11,"./proxy-call":15,"./util/core/extend":26,"./util/core/use-promise-library":37,"./util/core/wrap-method":40,"@sinonjs/commons":48,"@sinonjs/samsam":88}],13:[function(require,module,exports){ - function walkInternal(obj, iterator, context, originalObj, seen) { - let prop; - const proto = Object.getPrototypeOf(obj); + const fake = require("./fake"); + const isRestorable = require("./util/core/is-restorable"); - if (typeof Object.getOwnPropertyNames !== "function") { - // We explicitly want to enumerate through all of the prototype's properties - // in this case, therefore we deliberately leave out an own property check. - /* eslint-disable-next-line guard-for-in */ - for (prop in obj) { - iterator.call(context, obj[prop], prop, obj); - } + const STATUS_PENDING = "pending"; + const STATUS_RESOLVED = "resolved"; + const STATUS_REJECTED = "rejected"; - return; + /** + * Returns a fake for a given function or undefined. If no function is given, a + * new fake is returned. If the given function is already a fake, it is + * returned as is. Otherwise the given function is wrapped in a new fake. + * + * @param {Function} [executor] The optional executor function. + * @returns {Function} + */ + function getFakeExecutor(executor) { + if (isRestorable(executor)) { + return executor; } - - forEach(Object.getOwnPropertyNames(obj), function (k) { - if (seen[k] !== true) { - seen[k] = true; - const target = - typeof Object.getOwnPropertyDescriptor(obj, k).get === - "function" - ? originalObj - : obj; - iterator.call(context, k, target); - } - }); - - if (proto) { - walkInternal(proto, iterator, context, originalObj, seen); + if (executor) { + return fake(executor); } + return fake(); } - /* Walks the prototype chain of an object and iterates over every own property - * name encountered. The iterator is called in the same fashion that Array.prototype.forEach - * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional - * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will - * default to using a simple for..in loop. + /** + * Returns a new promise that exposes it's internal `status`, `resolvedValue` + * and `rejectedValue` and can be resolved or rejected from the outside by + * calling `resolve(value)` or `reject(reason)`. * - * obj - The object to walk the prototype chain for. - * iterator - The function to be called on each pass of the walk. - * context - (Optional) When given, the iterator will be called with this object as the receiver. + * @param {Function} [executor] The optional executor function. + * @returns {Promise} */ - module.exports = function walk(obj, iterator, context) { - return walkInternal(obj, iterator, context, obj, {}); - }; - - },{"@sinonjs/commons":48}],40:[function(require,module,exports){ - - // eslint-disable-next-line no-empty-function - const noop = () => {}; - const getPropertyDescriptor = require("./get-property-descriptor"); - const extend = require("./extend"); - const sinonType = require("./sinon-type"); - const hasOwnProperty = - require("@sinonjs/commons").prototypes.object.hasOwnProperty; - const valueToString = require("@sinonjs/commons").valueToString; - const push = require("@sinonjs/commons").prototypes.array.push; + function promise(executor) { + const fakeExecutor = getFakeExecutor(executor); + const sinonPromise = new Promise(fakeExecutor); - function isFunction(obj) { - return ( - typeof obj === "function" || - Boolean(obj && obj.constructor && obj.call && obj.apply) - ); - } + sinonPromise.status = STATUS_PENDING; + sinonPromise + .then(function (value) { + sinonPromise.status = STATUS_RESOLVED; + sinonPromise.resolvedValue = value; + }) + .catch(function (reason) { + sinonPromise.status = STATUS_REJECTED; + sinonPromise.rejectedValue = reason; + }); - function mirrorProperties(target, source) { - for (const prop in source) { - if (!hasOwnProperty(target, prop)) { - target[prop] = source[prop]; + /** + * Resolves or rejects the promise with the given status and value. + * + * @param {string} status + * @param {*} value + * @param {Function} callback + */ + function finalize(status, value, callback) { + if (sinonPromise.status !== STATUS_PENDING) { + throw new Error(`Promise already ${sinonPromise.status}`); } + + sinonPromise.status = status; + callback(value); } - } - function getAccessor(object, property, method) { - const accessors = ["get", "set"]; - const descriptor = getPropertyDescriptor(object, property); + sinonPromise.resolve = function (value) { + finalize(STATUS_RESOLVED, value, fakeExecutor.firstCall.args[0]); + // Return the promise so that callers can await it: + return sinonPromise; + }; + sinonPromise.reject = function (reason) { + finalize(STATUS_REJECTED, reason, fakeExecutor.firstCall.args[1]); + // Return a new promise that resolves when the sinon promise was + // rejected, so that callers can await it: + return new Promise(function (resolve) { + sinonPromise.catch(() => resolve()); + }); + }; - for (let i = 0; i < accessors.length; i++) { - if ( - descriptor[accessors[i]] && - descriptor[accessors[i]].name === method.name - ) { - return accessors[i]; - } - } - return null; + return sinonPromise; } - // Cheap way to detect if we have ES5 support. - const hasES5Support = "keys" in Object; + module.exports = promise; - module.exports = function wrapMethod(object, property, method) { - if (!object) { - throw new TypeError("Should wrap property of object"); - } + },{"./fake":10,"./util/core/is-restorable":33}],14:[function(require,module,exports){ - if (typeof method !== "function" && typeof method !== "object") { - throw new TypeError( - "Method wrapper should be a function or a property descriptor" - ); - } + const push = require("@sinonjs/commons").prototypes.array.push; - function checkWrappedMethod(wrappedMethod) { - let error; + exports.incrementCallCount = function incrementCallCount(proxy) { + proxy.called = true; + proxy.callCount += 1; + proxy.notCalled = false; + proxy.calledOnce = proxy.callCount === 1; + proxy.calledTwice = proxy.callCount === 2; + proxy.calledThrice = proxy.callCount === 3; + }; - if (!isFunction(wrappedMethod)) { - error = new TypeError( - `Attempted to wrap ${typeof wrappedMethod} property ${valueToString( - property - )} as function` - ); - } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) { - error = new TypeError( - `Attempted to wrap ${valueToString( - property - )} which is already wrapped` - ); - } else if (wrappedMethod.calledBefore) { - const verb = wrappedMethod.returns ? "stubbed" : "spied on"; - error = new TypeError( - `Attempted to wrap ${valueToString( - property - )} which is already ${verb}` - ); - } + exports.createCallProperties = function createCallProperties(proxy) { + proxy.firstCall = proxy.getCall(0); + proxy.secondCall = proxy.getCall(1); + proxy.thirdCall = proxy.getCall(2); + proxy.lastCall = proxy.getCall(proxy.callCount - 1); + }; - if (error) { - if (wrappedMethod && wrappedMethod.stackTraceError) { - error.stack += `\n--------------\n${wrappedMethod.stackTraceError.stack}`; + exports.delegateToCalls = function delegateToCalls( + proxy, + method, + matchAny, + actual, + returnsValues, + notCalled, + totalCallCount + ) { + proxy[method] = function () { + if (!this.called) { + if (notCalled) { + return notCalled.apply(this, arguments); } - throw error; + return false; } - } - - let error, wrappedMethod, i, wrappedMethodDesc, target, accessor; - - const wrappedMethods = []; - - function simplePropertyAssignment() { - wrappedMethod = object[property]; - checkWrappedMethod(wrappedMethod); - object[property] = method; - method.displayName = property; - } - // Firefox has a problem when using hasOwn.call on objects from other frames. - const owned = object.hasOwnProperty - ? object.hasOwnProperty(property) // eslint-disable-line @sinonjs/no-prototype-methods/no-prototype-methods - : hasOwnProperty(object, property); + if (totalCallCount !== undefined && this.callCount !== totalCallCount) { + return false; + } - if (hasES5Support) { - const methodDesc = - typeof method === "function" ? { value: method } : method; - wrappedMethodDesc = getPropertyDescriptor(object, property); + let currentCall; + let matches = 0; + const returnValues = []; - if (!wrappedMethodDesc) { - error = new TypeError( - `Attempted to wrap ${typeof wrappedMethod} property ${property} as function` - ); - } else if ( - wrappedMethodDesc.restore && - wrappedMethodDesc.restore.sinon - ) { - error = new TypeError( - `Attempted to wrap ${property} which is already wrapped` + for (let i = 0, l = this.callCount; i < l; i += 1) { + currentCall = this.getCall(i); + const returnValue = currentCall[actual || method].apply( + currentCall, + arguments ); - } - if (error) { - if (wrappedMethodDesc && wrappedMethodDesc.stackTraceError) { - error.stack += `\n--------------\n${wrappedMethodDesc.stackTraceError.stack}`; + push(returnValues, returnValue); + if (returnValue) { + matches += 1; + + if (matchAny) { + return true; + } } - throw error; } - const types = Object.keys(methodDesc); - for (i = 0; i < types.length; i++) { - wrappedMethod = wrappedMethodDesc[types[i]]; - checkWrappedMethod(wrappedMethod); - push(wrappedMethods, wrappedMethod); + if (returnsValues) { + return returnValues; } + return matches === this.callCount; + }; + }; - mirrorProperties(methodDesc, wrappedMethodDesc); - for (i = 0; i < types.length; i++) { - mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]); + },{"@sinonjs/commons":48}],15:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const match = require("@sinonjs/samsam").createMatcher; + const deepEqual = require("@sinonjs/samsam").deepEqual; + const functionName = require("@sinonjs/commons").functionName; + const inspect = require("util").inspect; + const valueToString = require("@sinonjs/commons").valueToString; + + const concat = arrayProto.concat; + const filter = arrayProto.filter; + const join = arrayProto.join; + const map = arrayProto.map; + const reduce = arrayProto.reduce; + const slice = arrayProto.slice; + + /** + * @param proxy + * @param text + * @param args + */ + function throwYieldError(proxy, text, args) { + let msg = functionName(proxy) + text; + if (args.length) { + msg += ` Received [${join(slice(args), ", ")}]`; + } + throw new Error(msg); + } + + const callProto = { + calledOn: function calledOn(thisValue) { + if (match.isMatcher(thisValue)) { + return thisValue.test(this.thisValue); } + return this.thisValue === thisValue; + }, - // you are not allowed to flip the configurable prop on an - // existing descriptor to anything but false (#2514) - if (!owned) { - methodDesc.configurable = true; + calledWith: function calledWith() { + const self = this; + const calledWithArgs = slice(arguments); + + if (calledWithArgs.length > self.args.length) { + return false; } - Object.defineProperty(object, property, methodDesc); + return reduce( + calledWithArgs, + function (prev, arg, i) { + return prev && deepEqual(self.args[i], arg); + }, + true + ); + }, - // catch failing assignment - // this is the converse of the check in `.restore` below - if (typeof method === "function" && object[property] !== method) { - // correct any wrongdoings caused by the defineProperty call above, - // such as adding new items (if object was a Storage object) - delete object[property]; - simplePropertyAssignment(); + calledWithMatch: function calledWithMatch() { + const self = this; + const calledWithMatchArgs = slice(arguments); + + if (calledWithMatchArgs.length > self.args.length) { + return false; } - } else { - simplePropertyAssignment(); - } - extendObjectWithWrappedMethods(); + return reduce( + calledWithMatchArgs, + function (prev, expectation, i) { + const actual = self.args[i]; - function extendObjectWithWrappedMethods() { - for (i = 0; i < wrappedMethods.length; i++) { - accessor = getAccessor(object, property, wrappedMethods[i]); - target = accessor ? method[accessor] : method; - extend.nonEnum(target, { - displayName: property, - wrappedMethod: wrappedMethods[i], + return prev && match(expectation).test(actual); + }, + true + ); + }, - // Set up an Error object for a stack trace which can be used later to find what line of - // code the original method was created on. - stackTraceError: new Error("Stack Trace for original"), + calledWithExactly: function calledWithExactly() { + return ( + arguments.length === this.args.length && + this.calledWith.apply(this, arguments) + ); + }, - restore: restore, - }); + notCalledWith: function notCalledWith() { + return !this.calledWith.apply(this, arguments); + }, - target.restore.sinon = true; - if (!hasES5Support) { - mirrorProperties(target, wrappedMethod); - } + notCalledWithMatch: function notCalledWithMatch() { + return !this.calledWithMatch.apply(this, arguments); + }, + + returned: function returned(value) { + return deepEqual(this.returnValue, value); + }, + + threw: function threw(error) { + if (typeof error === "undefined" || !this.exception) { + return Boolean(this.exception); } - } - function restore() { - accessor = getAccessor(object, property, this.wrappedMethod); - let descriptor; - // For prototype properties try to reset by delete first. - // If this fails (ex: localStorage on mobile safari) then force a reset - // via direct assignment. - if (accessor) { - if (!owned) { - try { - // In some cases `delete` may throw an error - delete object[property][accessor]; - } catch (e) {} // eslint-disable-line no-empty - // For native code functions `delete` fails without throwing an error - // on Chrome < 43, PhantomJS, etc. - } else if (hasES5Support) { - descriptor = getPropertyDescriptor(object, property); - descriptor[accessor] = wrappedMethodDesc[accessor]; - Object.defineProperty(object, property, descriptor); - } + return this.exception === error || this.exception.name === error; + }, - if (hasES5Support) { - descriptor = getPropertyDescriptor(object, property); - if (descriptor && descriptor.value === target) { - object[property][accessor] = this.wrappedMethod; - } - } else { - // Use strict equality comparison to check failures then force a reset - // via direct assignment. - if (object[property][accessor] === target) { - object[property][accessor] = this.wrappedMethod; - } - } - } else { - if (!owned) { - try { - delete object[property]; - } catch (e) {} // eslint-disable-line no-empty - } else if (hasES5Support) { - Object.defineProperty(object, property, wrappedMethodDesc); - } - - if (hasES5Support) { - descriptor = getPropertyDescriptor(object, property); - if (descriptor && descriptor.value === target) { - object[property] = this.wrappedMethod; - } - } else { - if (object[property] === target) { - object[property] = this.wrappedMethod; - } - } - } - if (sinonType.get(object) === "stub-instance") { - // this is simply to avoid errors after restoring if something should - // traverse the object in a cleanup phase, ref #2477 - object[property] = noop; - } - } - - return method; - }; - - },{"./extend":26,"./get-property-descriptor":29,"./sinon-type":35,"@sinonjs/commons":48}],41:[function(require,module,exports){ - - const extend = require("./core/extend"); - const FakeTimers = require("@sinonjs/fake-timers"); - const globalObject = require("@sinonjs/commons").global; - - /** - * - * @param config - * @param globalCtx - */ - function createClock(config, globalCtx) { - let FakeTimersCtx = FakeTimers; - if (globalCtx !== null && typeof globalCtx === "object") { - FakeTimersCtx = FakeTimers.withGlobal(globalCtx); - } - const clock = FakeTimersCtx.install(config); - clock.restore = clock.uninstall; - return clock; - } + calledWithNew: function calledWithNew() { + return this.proxy.prototype && this.thisValue instanceof this.proxy; + }, - /** - * - * @param obj - * @param globalPropName - */ - function addIfDefined(obj, globalPropName) { - const globalProp = globalObject[globalPropName]; - if (typeof globalProp !== "undefined") { - obj[globalPropName] = globalProp; - } - } + calledBefore: function (other) { + return this.callId < other.callId; + }, - /** - * @param {number|Date|object} dateOrConfig The unix epoch value to install with (default 0) - * @returns {object} Returns a lolex clock instance - */ - exports.useFakeTimers = function (dateOrConfig) { - const hasArguments = typeof dateOrConfig !== "undefined"; - const argumentIsDateLike = - (typeof dateOrConfig === "number" || dateOrConfig instanceof Date) && - arguments.length === 1; - const argumentIsObject = - dateOrConfig !== null && - typeof dateOrConfig === "object" && - arguments.length === 1; + calledAfter: function (other) { + return this.callId > other.callId; + }, - if (!hasArguments) { - return createClock({ - now: 0, - }); - } + calledImmediatelyBefore: function (other) { + return this.callId === other.callId - 1; + }, - if (argumentIsDateLike) { - return createClock({ - now: dateOrConfig, - }); - } + calledImmediatelyAfter: function (other) { + return this.callId === other.callId + 1; + }, - if (argumentIsObject) { - const config = extend.nonEnum({}, dateOrConfig); - const globalCtx = config.global; - delete config.global; - return createClock(config, globalCtx); - } + callArg: function (pos) { + this.ensureArgIsAFunction(pos); + return this.args[pos](); + }, - throw new TypeError( - "useFakeTimers expected epoch or config object. See https://github.com/sinonjs/sinon" - ); - }; + callArgOn: function (pos, thisValue) { + this.ensureArgIsAFunction(pos); + return this.args[pos].apply(thisValue); + }, - exports.clock = { - create: function (now) { - return FakeTimers.createClock(now); + callArgWith: function (pos) { + return this.callArgOnWith.apply( + this, + concat([pos, null], slice(arguments, 1)) + ); }, - }; - const timers = { - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - clearInterval: clearInterval, - Date: Date, - }; - addIfDefined(timers, "setImmediate"); - addIfDefined(timers, "clearImmediate"); + callArgOnWith: function (pos, thisValue) { + this.ensureArgIsAFunction(pos); + const args = slice(arguments, 2); + return this.args[pos].apply(thisValue, args); + }, - exports.timers = timers; + throwArg: function (pos) { + if (pos > this.args.length) { + throw new TypeError( + `Not enough arguments: ${pos} required but only ${this.args.length} present` + ); + } - },{"./core/extend":26,"@sinonjs/commons":48,"@sinonjs/fake-timers":61}],42:[function(require,module,exports){ + throw this.args[pos]; + }, - var every = require("./prototypes/array").every; + yield: function () { + return this.yieldOn.apply(this, concat([null], slice(arguments, 0))); + }, - /** - * @private - */ - function hasCallsLeft(callMap, spy) { - if (callMap[spy.id] === undefined) { - callMap[spy.id] = 0; - } + yieldOn: function (thisValue) { + const args = slice(this.args); + const yieldFn = filter(args, function (arg) { + return typeof arg === "function"; + })[0]; - return callMap[spy.id] < spy.callCount; - } + if (!yieldFn) { + throwYieldError( + this.proxy, + " cannot yield since no callback was passed.", + args + ); + } - /** - * @private - */ - function checkAdjacentCalls(callMap, spy, index, spies) { - var calledBeforeNext = true; + return yieldFn.apply(thisValue, slice(arguments, 1)); + }, - if (index !== spies.length - 1) { - calledBeforeNext = spy.calledBefore(spies[index + 1]); - } + yieldTo: function (prop) { + return this.yieldToOn.apply( + this, + concat([prop, null], slice(arguments, 1)) + ); + }, - if (hasCallsLeft(callMap, spy) && calledBeforeNext) { - callMap[spy.id] += 1; - return true; - } + yieldToOn: function (prop, thisValue) { + const args = slice(this.args); + const yieldArg = filter(args, function (arg) { + return arg && typeof arg[prop] === "function"; + })[0]; + const yieldFn = yieldArg && yieldArg[prop]; - return false; - } + if (!yieldFn) { + throwYieldError( + this.proxy, + ` cannot yield to '${valueToString( + prop + )}' since no callback was passed.`, + args + ); + } - /** - * A Sinon proxy object (fake, spy, stub) - * - * @typedef {object} SinonProxy - * @property {Function} calledBefore - A method that determines if this proxy was called before another one - * @property {string} id - Some id - * @property {number} callCount - Number of times this proxy has been called - */ + return yieldFn.apply(thisValue, slice(arguments, 2)); + }, - /** - * Returns true when the spies have been called in the order they were supplied in - * - * @param {SinonProxy[] | SinonProxy} spies An array of proxies, or several proxies as arguments - * @returns {boolean} true when spies are called in order, false otherwise - */ - function calledInOrder(spies) { - var callMap = {}; - // eslint-disable-next-line no-underscore-dangle - var _spies = arguments.length > 1 ? arguments : spies; + toString: function () { + if (!this.args) { + return ":("; + } - return every(_spies, checkAdjacentCalls.bind(null, callMap)); - } + let callStr = this.proxy ? `${String(this.proxy)}(` : ""; + const formattedArgs = map(this.args, function (arg) { + return inspect(arg); + }); - module.exports = calledInOrder; + callStr = `${callStr + join(formattedArgs, ", ")})`; - },{"./prototypes/array":50}],43:[function(require,module,exports){ + if (typeof this.returnValue !== "undefined") { + callStr += ` => ${inspect(this.returnValue)}`; + } - var functionName = require("./function-name"); + if (this.exception) { + callStr += ` !${this.exception.name}`; - /** - * Returns a display name for a value from a constructor - * - * @param {object} value A value to examine - * @returns {(string|null)} A string or null - */ - function className(value) { - return ( - (value.constructor && value.constructor.name) || - // The next branch is for IE11 support only: - // Because the name property is not set on the prototype - // of the Function object, we finally try to grab the - // name from its definition. This will never be reached - // in node, so we are not able to test this properly. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name - (typeof value.constructor === "function" && - /* istanbul ignore next */ - functionName(value.constructor)) || - null - ); - } - - module.exports = className; + if (this.exception.message) { + callStr += `(${this.exception.message})`; + } + } + if (this.stack) { + // If we have a stack, add the first frame that's in end-user code + // Skip the first two frames because they will refer to Sinon code + callStr += (this.stack.split("\n")[3] || "unknown").replace( + /^\s*(?:at\s+|@)?/, + " at " + ); + } - },{"./function-name":46}],44:[function(require,module,exports){ + return callStr; + }, - /** - * Returns a function that will invoke the supplied function and print a - * deprecation warning to the console each time it is called. - * - * @param {Function} func - * @param {string} msg - * @returns {Function} - */ - exports.wrap = function (func, msg) { - var wrapped = function () { - exports.printWarning(msg); - return func.apply(this, arguments); - }; - if (func.prototype) { - wrapped.prototype = func.prototype; - } - return wrapped; + ensureArgIsAFunction: function (pos) { + if (typeof this.args[pos] !== "function") { + throw new TypeError( + `Expected argument at position ${pos} to be a Function, but was ${typeof this + .args[pos]}` + ); + } + }, }; + Object.defineProperty(callProto, "stack", { + enumerable: true, + configurable: true, + get: function () { + return (this.errorWithCallStack && this.errorWithCallStack.stack) || ""; + }, + }); - /** - * Returns a string which can be supplied to `wrap()` to notify the user that a - * particular part of the sinon API has been deprecated. - * - * @param {string} packageName - * @param {string} funcName - * @returns {string} - */ - exports.defaultMsg = function (packageName, funcName) { - return `${packageName}.${funcName} is deprecated and will be removed from the public API in a future version of ${packageName}.`; - }; + callProto.invokeCallback = callProto.yield; /** - * Prints a warning on the console, when it exists - * - * @param {string} msg - * @returns {undefined} + * @param proxy + * @param thisValue + * @param args + * @param returnValue + * @param exception + * @param id + * @param errorWithCallStack */ - exports.printWarning = function (msg) { - /* istanbul ignore next */ - if (typeof process === "object" && process.emitWarning) { - // Emit Warnings in Node - process.emitWarning(msg); - } else if (console.info) { - console.info(msg); - } else { - console.log(msg); + function createProxyCall( + proxy, + thisValue, + args, + returnValue, + exception, + id, + errorWithCallStack + ) { + if (typeof id !== "number") { + throw new TypeError("Call id is not a number"); } - }; - - },{}],45:[function(require,module,exports){ - /** - * Returns true when fn returns true for all members of obj. - * This is an every implementation that works for all iterables - * - * @param {object} obj - * @param {Function} fn - * @returns {boolean} - */ - module.exports = function every(obj, fn) { - var pass = true; + let firstArg, lastArg; - try { - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - obj.forEach(function () { - if (!fn.apply(this, arguments)) { - // Throwing an error is the only way to break `forEach` - throw new Error(); - } - }); - } catch (e) { - pass = false; + if (args.length > 0) { + firstArg = args[0]; + lastArg = args[args.length - 1]; } - return pass; - }; + const proxyCall = Object.create(callProto); + const callback = + lastArg && typeof lastArg === "function" ? lastArg : undefined; - },{}],46:[function(require,module,exports){ + proxyCall.proxy = proxy; + proxyCall.thisValue = thisValue; + proxyCall.args = args; + proxyCall.firstArg = firstArg; + proxyCall.lastArg = lastArg; + proxyCall.callback = callback; + proxyCall.returnValue = returnValue; + proxyCall.exception = exception; + proxyCall.callId = id; + proxyCall.errorWithCallStack = errorWithCallStack; - /** - * Returns a display name for a function - * - * @param {Function} func - * @returns {string} - */ - module.exports = function functionName(func) { - if (!func) { - return ""; - } + return proxyCall; + } + createProxyCall.toString = callProto.toString; // used by mocks - try { - return ( - func.displayName || - func.name || - // Use function decomposition as a last resort to get function - // name. Does not rely on function decomposition to work - if it - // doesn't debugging will be slightly less informative - // (i.e. toString will say 'spy' rather than 'myFunc'). - (String(func).match(/function ([^\s(]+)/) || [])[1] - ); - } catch (e) { - // Stringify may fail and we might get an exception, as a last-last - // resort fall back to empty string. - return ""; - } - }; + module.exports = createProxyCall; - },{}],47:[function(require,module,exports){ + },{"@sinonjs/commons":48,"@sinonjs/samsam":88,"util":113}],16:[function(require,module,exports){ - /** - * A reference to the global object - * - * @type {object} globalObject - */ - var globalObject; + const arrayProto = require("@sinonjs/commons").prototypes.array; + const proxyCallUtil = require("./proxy-call-util"); - /* istanbul ignore else */ - if (typeof global !== "undefined") { - // Node - globalObject = global; - } else if (typeof window !== "undefined") { - // Browser - globalObject = window; - } else { - // WebWorker - globalObject = self; - } + const push = arrayProto.push; + const forEach = arrayProto.forEach; + const concat = arrayProto.concat; + const ErrorConstructor = Error.prototype.constructor; + const bind = Function.prototype.bind; - module.exports = globalObject; + let callId = 0; - },{}],48:[function(require,module,exports){ + module.exports = function invoke(func, thisValue, args) { + const matchings = this.matchingFakes(args); + const currentCallId = callId++; + let exception, returnValue; - module.exports = { - global: require("./global"), - calledInOrder: require("./called-in-order"), - className: require("./class-name"), - deprecated: require("./deprecated"), - every: require("./every"), - functionName: require("./function-name"), - orderByFirstCall: require("./order-by-first-call"), - prototypes: require("./prototypes"), - typeOf: require("./type-of"), - valueToString: require("./value-to-string"), - }; + proxyCallUtil.incrementCallCount(this); + push(this.thisValues, thisValue); + push(this.args, args); + push(this.callIds, currentCallId); + forEach(matchings, function (matching) { + proxyCallUtil.incrementCallCount(matching); + push(matching.thisValues, thisValue); + push(matching.args, args); + push(matching.callIds, currentCallId); + }); - },{"./called-in-order":42,"./class-name":43,"./deprecated":44,"./every":45,"./function-name":46,"./global":47,"./order-by-first-call":49,"./prototypes":53,"./type-of":59,"./value-to-string":60}],49:[function(require,module,exports){ + // Make call properties available from within the spied function: + proxyCallUtil.createCallProperties(this); + forEach(matchings, proxyCallUtil.createCallProperties); - var sort = require("./prototypes/array").sort; - var slice = require("./prototypes/array").slice; + try { + this.invoking = true; - /** - * @private - */ - function comparator(a, b) { - // uuid, won't ever be equal - var aCall = a.getCall(0); - var bCall = b.getCall(0); - var aId = (aCall && aCall.callId) || -1; - var bId = (bCall && bCall.callId) || -1; + const thisCall = this.getCall(this.callCount - 1); - return aId < bId ? -1 : 1; - } + if (thisCall.calledWithNew()) { + // Call through with `new` + returnValue = new (bind.apply( + this.func || func, + concat([thisValue], args) + ))(); - /** - * A Sinon proxy object (fake, spy, stub) - * - * @typedef {object} SinonProxy - * @property {Function} getCall - A method that can return the first call - */ + if ( + typeof returnValue !== "object" && + typeof returnValue !== "function" + ) { + returnValue = thisValue; + } + } else { + returnValue = (this.func || func).apply(thisValue, args); + } + } catch (e) { + exception = e; + } finally { + delete this.invoking; + } - /** - * Sorts an array of SinonProxy instances (fake, spy, stub) by their first call - * - * @param {SinonProxy[] | SinonProxy} spies - * @returns {SinonProxy[]} - */ - function orderByFirstCall(spies) { - return sort(slice(spies), comparator); - } + push(this.exceptions, exception); + push(this.returnValues, returnValue); + forEach(matchings, function (matching) { + push(matching.exceptions, exception); + push(matching.returnValues, returnValue); + }); - module.exports = orderByFirstCall; + const err = new ErrorConstructor(); + // 1. Please do not get stack at this point. It may be so very slow, and not actually used + // 2. PhantomJS does not serialize the stack trace until the error has been thrown: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack + try { + throw err; + } catch (e) { + /* empty */ + } + push(this.errorsWithCallStack, err); + forEach(matchings, function (matching) { + push(matching.errorsWithCallStack, err); + }); - },{"./prototypes/array":50}],50:[function(require,module,exports){ + // Make return value and exception available in the calls: + proxyCallUtil.createCallProperties(this); + forEach(matchings, proxyCallUtil.createCallProperties); - var copyPrototype = require("./copy-prototype-methods"); + if (exception !== undefined) { + throw exception; + } - module.exports = copyPrototype(Array.prototype); + return returnValue; + }; - },{"./copy-prototype-methods":51}],51:[function(require,module,exports){ + },{"./proxy-call-util":14,"@sinonjs/commons":48}],17:[function(require,module,exports){ - var call = Function.call; - var throwsOnProto = require("./throws-on-proto"); + const arrayProto = require("@sinonjs/commons").prototypes.array; + const extend = require("./util/core/extend"); + const functionToString = require("./util/core/function-to-string"); + const proxyCall = require("./proxy-call"); + const proxyCallUtil = require("./proxy-call-util"); + const proxyInvoke = require("./proxy-invoke"); + const inspect = require("util").inspect; - var disallowedProperties = [ - // ignore size because it throws from Map - "size", - "caller", - "callee", - "arguments", - ]; + const push = arrayProto.push; + const forEach = arrayProto.forEach; + const slice = arrayProto.slice; - // This branch is covered when tests are run with `--disable-proto=throw`, - // however we can test both branches at the same time, so this is ignored - /* istanbul ignore next */ - if (throwsOnProto) { - disallowedProperties.push("__proto__"); - } + const emptyFakes = Object.freeze([]); - module.exports = function copyPrototypeMethods(prototype) { - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - return Object.getOwnPropertyNames(prototype).reduce(function ( - result, - name - ) { - if (disallowedProperties.includes(name)) { - return result; - } + // Public API + const proxyApi = { + toString: functionToString, - if (typeof prototype[name] !== "function") { - return result; + named: function named(name) { + this.displayName = name; + const nameDescriptor = Object.getOwnPropertyDescriptor(this, "name"); + if (nameDescriptor && nameDescriptor.configurable) { + // IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + nameDescriptor.value = name; + Object.defineProperty(this, "name", nameDescriptor); } + return this; + }, - result[name] = call.bind(prototype[name]); + invoke: proxyInvoke, - return result; + /* + * Hook for derived implementation to return fake instances matching the + * given arguments. + */ + matchingFakes: function (/*args, strict*/) { + return emptyFakes; }, - Object.create(null)); - }; - - },{"./throws-on-proto":58}],52:[function(require,module,exports){ - var copyPrototype = require("./copy-prototype-methods"); + getCall: function getCall(index) { + let i = index; + if (i < 0) { + // Negative indices means counting backwards from the last call + i += this.callCount; + } + if (i < 0 || i >= this.callCount) { + return null; + } - module.exports = copyPrototype(Function.prototype); + return proxyCall( + this, + this.thisValues[i], + this.args[i], + this.returnValues[i], + this.exceptions[i], + this.callIds[i], + this.errorsWithCallStack[i] + ); + }, - },{"./copy-prototype-methods":51}],53:[function(require,module,exports){ + getCalls: function () { + const calls = []; + let i; - module.exports = { - array: require("./array"), - function: require("./function"), - map: require("./map"), - object: require("./object"), - set: require("./set"), - string: require("./string"), - }; + for (i = 0; i < this.callCount; i++) { + push(calls, this.getCall(i)); + } - },{"./array":50,"./function":52,"./map":54,"./object":55,"./set":56,"./string":57}],54:[function(require,module,exports){ + return calls; + }, - var copyPrototype = require("./copy-prototype-methods"); + calledBefore: function calledBefore(proxy) { + if (!this.called) { + return false; + } - module.exports = copyPrototype(Map.prototype); + if (!proxy.called) { + return true; + } - },{"./copy-prototype-methods":51}],55:[function(require,module,exports){ + return this.callIds[0] < proxy.callIds[proxy.callIds.length - 1]; + }, - var copyPrototype = require("./copy-prototype-methods"); + calledAfter: function calledAfter(proxy) { + if (!this.called || !proxy.called) { + return false; + } - module.exports = copyPrototype(Object.prototype); + return this.callIds[this.callCount - 1] > proxy.callIds[0]; + }, - },{"./copy-prototype-methods":51}],56:[function(require,module,exports){ + calledImmediatelyBefore: function calledImmediatelyBefore(proxy) { + if (!this.called || !proxy.called) { + return false; + } - var copyPrototype = require("./copy-prototype-methods"); + return ( + this.callIds[this.callCount - 1] === + proxy.callIds[proxy.callCount - 1] - 1 + ); + }, - module.exports = copyPrototype(Set.prototype); + calledImmediatelyAfter: function calledImmediatelyAfter(proxy) { + if (!this.called || !proxy.called) { + return false; + } - },{"./copy-prototype-methods":51}],57:[function(require,module,exports){ + return ( + this.callIds[this.callCount - 1] === + proxy.callIds[proxy.callCount - 1] + 1 + ); + }, - var copyPrototype = require("./copy-prototype-methods"); + formatters: require("./spy-formatters"), + printf: function (format) { + const spyInstance = this; + const args = slice(arguments, 1); + let formatter; - module.exports = copyPrototype(String.prototype); + return (format || "").replace(/%(.)/g, function (match, specifier) { + formatter = proxyApi.formatters[specifier]; - },{"./copy-prototype-methods":51}],58:[function(require,module,exports){ + if (typeof formatter === "function") { + return String(formatter(spyInstance, args)); + } else if (!isNaN(parseInt(specifier, 10))) { + return inspect(args[specifier - 1]); + } - /** - * Is true when the environment causes an error to be thrown for accessing the - * __proto__ property. - * - * This is necessary in order to support `node --disable-proto=throw`. - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto - * - * @type {boolean} - */ - let throwsOnProto; - try { - const object = {}; - // eslint-disable-next-line no-proto, no-unused-expressions - object.__proto__; - throwsOnProto = false; - } catch (_) { - // This branch is covered when tests are run with `--disable-proto=throw`, - // however we can test both branches at the same time, so this is ignored - /* istanbul ignore next */ - throwsOnProto = true; - } + return `%${specifier}`; + }); + }, - module.exports = throwsOnProto; + resetHistory: function () { + if (this.invoking) { + const err = new Error( + "Cannot reset Sinon function while invoking it. " + + "Move the call to .resetHistory outside of the callback." + ); + err.name = "InvalidResetException"; + throw err; + } - },{}],59:[function(require,module,exports){ + this.called = false; + this.notCalled = true; + this.calledOnce = false; + this.calledTwice = false; + this.calledThrice = false; + this.callCount = 0; + this.firstCall = null; + this.secondCall = null; + this.thirdCall = null; + this.lastCall = null; + this.args = []; + this.firstArg = null; + this.lastArg = null; + this.returnValues = []; + this.thisValues = []; + this.exceptions = []; + this.callIds = []; + this.errorsWithCallStack = []; - var type = require("type-detect"); + if (this.fakes) { + forEach(this.fakes, function (fake) { + fake.resetHistory(); + }); + } - /** - * Returns the lower-case result of running type from type-detect on the value - * - * @param {*} value - * @returns {string} - */ - module.exports = function typeOf(value) { - return type(value).toLowerCase(); + return this; + }, }; - },{"type-detect":151}],60:[function(require,module,exports){ - - /** - * Returns a string representation of the value - * - * @param {*} value - * @returns {string} - */ - function valueToString(value) { - if (value && value.toString) { - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - return value.toString(); + const delegateToCalls = proxyCallUtil.delegateToCalls; + delegateToCalls(proxyApi, "calledOn", true); + delegateToCalls(proxyApi, "alwaysCalledOn", false, "calledOn"); + delegateToCalls(proxyApi, "calledWith", true); + delegateToCalls( + proxyApi, + "calledOnceWith", + true, + "calledWith", + false, + undefined, + 1 + ); + delegateToCalls(proxyApi, "calledWithMatch", true); + delegateToCalls(proxyApi, "alwaysCalledWith", false, "calledWith"); + delegateToCalls(proxyApi, "alwaysCalledWithMatch", false, "calledWithMatch"); + delegateToCalls(proxyApi, "calledWithExactly", true); + delegateToCalls( + proxyApi, + "calledOnceWithExactly", + true, + "calledWithExactly", + false, + undefined, + 1 + ); + delegateToCalls( + proxyApi, + "calledOnceWithMatch", + true, + "calledWithMatch", + false, + undefined, + 1 + ); + delegateToCalls( + proxyApi, + "alwaysCalledWithExactly", + false, + "calledWithExactly" + ); + delegateToCalls( + proxyApi, + "neverCalledWith", + false, + "notCalledWith", + false, + function () { + return true; } - return String(value); - } - - module.exports = valueToString; + ); + delegateToCalls( + proxyApi, + "neverCalledWithMatch", + false, + "notCalledWithMatch", + false, + function () { + return true; + } + ); + delegateToCalls(proxyApi, "threw", true); + delegateToCalls(proxyApi, "alwaysThrew", false, "threw"); + delegateToCalls(proxyApi, "returned", true); + delegateToCalls(proxyApi, "alwaysReturned", false, "returned"); + delegateToCalls(proxyApi, "calledWithNew", true); + delegateToCalls(proxyApi, "alwaysCalledWithNew", false, "calledWithNew"); - },{}],61:[function(require,module,exports){ + function createProxy(func, originalFunc) { + const proxy = wrapFunction(func, originalFunc); - const globalObject = require("@sinonjs/commons").global; + // Inherit function properties: + extend(proxy, func); - /** - * @typedef {object} IdleDeadline - * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout - * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period - */ + proxy.prototype = func.prototype; - /** - * Queues a function to be called during a browser's idle periods - * - * @callback RequestIdleCallback - * @param {function(IdleDeadline)} callback - * @param {{timeout: number}} options - an options object - * @returns {number} the id - */ + extend.nonEnum(proxy, proxyApi); - /** - * @callback NextTick - * @param {VoidVarArgsFunc} callback - the callback to run - * @param {...*} arguments - optional arguments to call the callback with - * @returns {void} - */ + return proxy; + } - /** - * @callback SetImmediate - * @param {VoidVarArgsFunc} callback - the callback to run - * @param {...*} arguments - optional arguments to call the callback with - * @returns {NodeImmediate} - */ + function wrapFunction(func, originalFunc) { + const arity = originalFunc.length; + let p; + // Do not change this to use an eval. Projects that depend on sinon block the use of eval. + // ref: https://github.com/sinonjs/sinon/issues/710 + switch (arity) { + /*eslint-disable no-unused-vars, max-len*/ + case 0: + p = function proxy() { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 1: + p = function proxy(a) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 2: + p = function proxy(a, b) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 3: + p = function proxy(a, b, c) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 4: + p = function proxy(a, b, c, d) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 5: + p = function proxy(a, b, c, d, e) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 6: + p = function proxy(a, b, c, d, e, f) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 7: + p = function proxy(a, b, c, d, e, f, g) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 8: + p = function proxy(a, b, c, d, e, f, g, h) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 9: + p = function proxy(a, b, c, d, e, f, g, h, i) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 10: + p = function proxy(a, b, c, d, e, f, g, h, i, j) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 11: + p = function proxy(a, b, c, d, e, f, g, h, i, j, k) { + return p.invoke(func, this, slice(arguments)); + }; + break; + case 12: + p = function proxy(a, b, c, d, e, f, g, h, i, j, k, l) { + return p.invoke(func, this, slice(arguments)); + }; + break; + default: + p = function proxy() { + return p.invoke(func, this, slice(arguments)); + }; + break; + /*eslint-enable*/ + } + const nameDescriptor = Object.getOwnPropertyDescriptor( + originalFunc, + "name" + ); + if (nameDescriptor && nameDescriptor.configurable) { + // IE 11 functions don't have a name. + // Safari 9 has names that are not configurable. + Object.defineProperty(p, "name", nameDescriptor); + } + extend.nonEnum(p, { + isSinonProxy: true, - /** - * @callback VoidVarArgsFunc - * @param {...*} callback - the callback to run - * @returns {void} - */ + called: false, + notCalled: true, + calledOnce: false, + calledTwice: false, + calledThrice: false, + callCount: 0, + firstCall: null, + firstArg: null, + secondCall: null, + thirdCall: null, + lastCall: null, + lastArg: null, + args: [], + returnValues: [], + thisValues: [], + exceptions: [], + callIds: [], + errorsWithCallStack: [], + }); + return p; + } - /** - * @typedef RequestAnimationFrame - * @property {function(number):void} requestAnimationFrame - * @returns {number} - the id - */ + module.exports = createProxy; - /** - * @typedef Performance - * @property {function(): number} now - */ + },{"./proxy-call":15,"./proxy-call-util":14,"./proxy-invoke":16,"./spy-formatters":20,"./util/core/extend":26,"./util/core/function-to-string":27,"@sinonjs/commons":48,"util":113}],18:[function(require,module,exports){ - /* eslint-disable jsdoc/require-property-description */ - /** - * @typedef {object} Clock - * @property {number} now - the current time - * @property {Date} Date - the Date constructor - * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop - * @property {RequestIdleCallback} requestIdleCallback - * @property {function(number):void} cancelIdleCallback - * @property {setTimeout} setTimeout - * @property {clearTimeout} clearTimeout - * @property {NextTick} nextTick - * @property {queueMicrotask} queueMicrotask - * @property {setInterval} setInterval - * @property {clearInterval} clearInterval - * @property {SetImmediate} setImmediate - * @property {function(NodeImmediate):void} clearImmediate - * @property {function():number} countTimers - * @property {RequestAnimationFrame} requestAnimationFrame - * @property {function(number):void} cancelAnimationFrame - * @property {function():void} runMicrotasks - * @property {function(string | number): number} tick - * @property {function(string | number): Promise} tickAsync - * @property {function(): number} next - * @property {function(): Promise} nextAsync - * @property {function(): number} runAll - * @property {function(): number} runToFrame - * @property {function(): Promise} runAllAsync - * @property {function(): number} runToLast - * @property {function(): Promise} runToLastAsync - * @property {function(): void} reset - * @property {function(number | Date): void} setSystemTime - * @property {function(number): void} jump - * @property {Performance} performance - * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) - * @property {function(): void} uninstall Uninstall the clock. - * @property {Function[]} methods - the methods that are faked - * @property {boolean} [shouldClearNativeTimers] inherited from config - */ - /* eslint-enable jsdoc/require-property-description */ + const walkObject = require("./util/core/walk-object"); - /** - * Configuration object for the `install` method. - * - * @typedef {object} Config - * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) - * @property {string[]} [toFake] names of the methods that should be faked. - * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() - * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) - * @property {number} [advanceTimeDelta] increment mocked time every <> ms (default: 20ms) - * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) - */ + function filter(object, property) { + return object[property].restore && object[property].restore.sinon; + } - /* eslint-disable jsdoc/require-property-description */ - /** - * The internal structure to describe a scheduled fake timer - * - * @typedef {object} Timer - * @property {Function} func - * @property {*[]} args - * @property {number} delay - * @property {number} callAt - * @property {number} createdAt - * @property {boolean} immediate - * @property {number} id - * @property {Error} [error] - */ + function restore(object, property) { + object[property].restore(); + } - /** - * A Node timer - * - * @typedef {object} NodeImmediate - * @property {function(): boolean} hasRef - * @property {function(): NodeImmediate} ref - * @property {function(): NodeImmediate} unref - */ - /* eslint-enable jsdoc/require-property-description */ + function restoreObject(object) { + return walkObject(restore, object, filter); + } - /* eslint-disable complexity */ + module.exports = restoreObject; - /** - * Mocks available features in the specified global namespace. - * - * @param {*} _global Namespace to mock (e.g. `window`) - * @returns {FakeTimers} - */ - function withGlobal(_global) { - const userAgent = _global.navigator && _global.navigator.userAgent; - const isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1; - const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint - const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs - const NOOP = function () { - return undefined; - }; - const NOOP_ARRAY = function () { - return []; - }; - const timeoutResult = _global.setTimeout(NOOP, 0); - const addTimerReturnsObject = typeof timeoutResult === "object"; - const hrtimePresent = - _global.process && typeof _global.process.hrtime === "function"; - const hrtimeBigintPresent = - hrtimePresent && typeof _global.process.hrtime.bigint === "function"; - const nextTickPresent = - _global.process && typeof _global.process.nextTick === "function"; - const utilPromisify = _global.process && require("util").promisify; - const performancePresent = - _global.performance && typeof _global.performance.now === "function"; - const hasPerformancePrototype = - _global.Performance && - (typeof _global.Performance).match(/^(function|object)$/); - const hasPerformanceConstructorPrototype = - _global.performance && - _global.performance.constructor && - _global.performance.constructor.prototype; - const queueMicrotaskPresent = _global.hasOwnProperty("queueMicrotask"); - const requestAnimationFramePresent = - _global.requestAnimationFrame && - typeof _global.requestAnimationFrame === "function"; - const cancelAnimationFramePresent = - _global.cancelAnimationFrame && - typeof _global.cancelAnimationFrame === "function"; - const requestIdleCallbackPresent = - _global.requestIdleCallback && - typeof _global.requestIdleCallback === "function"; - const cancelIdleCallbackPresent = - _global.cancelIdleCallback && - typeof _global.cancelIdleCallback === "function"; - const setImmediatePresent = - _global.setImmediate && typeof _global.setImmediate === "function"; + },{"./util/core/walk-object":38}],19:[function(require,module,exports){ - // Make properties writable in IE, as per - // https://www.adequatelygood.com/Replacing-setTimeout-Globally.html - /* eslint-disable no-self-assign */ - if (isRunningInIE) { - _global.setTimeout = _global.setTimeout; - _global.clearTimeout = _global.clearTimeout; - _global.setInterval = _global.setInterval; - _global.clearInterval = _global.clearInterval; - _global.Date = _global.Date; - } + const arrayProto = require("@sinonjs/commons").prototypes.array; + const logger = require("@sinonjs/commons").deprecated; + const collectOwnMethods = require("./collect-own-methods"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const isPropertyConfigurable = require("./util/core/is-property-configurable"); + const match = require("@sinonjs/samsam").createMatcher; + const sinonAssert = require("./assert"); + const sinonClock = require("./util/fake-timers"); + const sinonMock = require("./mock"); + const sinonSpy = require("./spy"); + const sinonStub = require("./stub"); + const sinonCreateStubInstance = require("./create-stub-instance"); + const sinonFake = require("./fake"); + const valueToString = require("@sinonjs/commons").valueToString; + const fakeServer = require("nise").fakeServer; + const fakeXhr = require("nise").fakeXhr; + const usePromiseLibrary = require("./util/core/use-promise-library"); - // setImmediate is not a standard function - // avoid adding the prop to the window object if not present - if (setImmediatePresent) { - _global.setImmediate = _global.setImmediate; - _global.clearImmediate = _global.clearImmediate; - } - /* eslint-enable no-self-assign */ + const DEFAULT_LEAK_THRESHOLD = 10000; - _global.clearTimeout(timeoutResult); + const filter = arrayProto.filter; + const forEach = arrayProto.forEach; + const push = arrayProto.push; + const reverse = arrayProto.reverse; - const NativeDate = _global.Date; - let uniqueTimerId = idCounterStart; + function applyOnEach(fakes, method) { + const matchingFakes = filter(fakes, function (fake) { + return typeof fake[method] === "function"; + }); - /** - * @param {number} num - * @returns {boolean} - */ - function isNumberFinite(num) { - if (Number.isFinite) { - return Number.isFinite(num); - } + forEach(matchingFakes, function (fake) { + fake[method](); + }); + } - return isFinite(num); + function throwOnAccessors(descriptor) { + if (typeof descriptor.get === "function") { + throw new Error("Use sandbox.replaceGetter for replacing getters"); } - let isNearInfiniteLimit = false; - - /** - * @param {Clock} clock - * @param {number} i - */ - function checkIsNearInfiniteLimit(clock, i) { - if (clock.loopLimit && i === clock.loopLimit - 1) { - isNearInfiniteLimit = true; - } + if (typeof descriptor.set === "function") { + throw new Error("Use sandbox.replaceSetter for replacing setters"); } + } - /** - * - */ - function resetIsNearInfiniteLimit() { - isNearInfiniteLimit = false; + function verifySameType(object, property, replacement) { + if (typeof object[property] !== typeof replacement) { + throw new TypeError( + `Cannot replace ${typeof object[ + property + ]} with ${typeof replacement}` + ); } + } - /** - * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into - * number of milliseconds. This is used to support human-readable strings passed - * to clock.tick() - * - * @param {string} str - * @returns {number} - */ - function parseTime(str) { - if (!str) { - return 0; - } + function checkForValidArguments(descriptor, property, replacement) { + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}. Perhaps you meant sandbox.define()?` + ); + } - const strings = str.split(":"); - const l = strings.length; - let i = l; - let ms = 0; - let parsed; + if (typeof replacement === "undefined") { + throw new TypeError("Expected replacement argument to be defined"); + } + } - if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { - throw new Error( - "tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits" + function Sandbox() { + const sandbox = this; + let fakeRestorers = []; + let promiseLib; + + let collection = []; + let loggedLeakWarning = false; + sandbox.leakThreshold = DEFAULT_LEAK_THRESHOLD; + + function addToCollection(object) { + if ( + push(collection, object) > sandbox.leakThreshold && + !loggedLeakWarning + ) { + // eslint-disable-next-line no-console + logger.printWarning( + "Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox." ); + loggedLeakWarning = true; } + } - while (i--) { - parsed = parseInt(strings[i], 10); - - if (parsed >= 60) { - throw new Error(`Invalid time ${str}`); - } + sandbox.assert = sinonAssert.createAssertObject(); - ms += parsed * Math.pow(60, l - i - 1); - } + sandbox.serverPrototype = fakeServer; - return ms * 1000; - } + // this is for testing only + sandbox.getFakes = function getFakes() { + return collection; + }; - /** - * Get the decimal part of the millisecond value as nanoseconds - * - * @param {number} msFloat the number of milliseconds - * @returns {number} an integer number of nanoseconds in the range [0,1e6) - * - * Example: nanoRemainer(123.456789) -> 456789 - */ - function nanoRemainder(msFloat) { - const modulo = 1e6; - const remainder = (msFloat * 1e6) % modulo; - const positiveRemainder = - remainder < 0 ? remainder + modulo : remainder; + sandbox.createStubInstance = function createStubInstance() { + const stubbed = sinonCreateStubInstance.apply(null, arguments); - return Math.floor(positiveRemainder); - } + const ownMethods = collectOwnMethods(stubbed); - /** - * Used to grok the `now` parameter to createClock. - * - * @param {Date|number} epoch the system time - * @returns {number} - */ - function getEpoch(epoch) { - if (!epoch) { - return 0; - } - if (typeof epoch.getTime === "function") { - return epoch.getTime(); - } - if (typeof epoch === "number") { - return epoch; - } - throw new TypeError("now should be milliseconds since UNIX epoch"); - } + forEach(ownMethods, function (method) { + addToCollection(method); + }); - /** - * @param {number} from - * @param {number} to - * @param {Timer} timer - * @returns {boolean} - */ - function inRange(from, to, timer) { - return timer && timer.callAt >= from && timer.callAt <= to; - } + usePromiseLibrary(promiseLib, ownMethods); - /** - * @param {Clock} clock - * @param {Timer} job - */ - function getInfiniteLoopError(clock, job) { - const infiniteLoopError = new Error( - `Aborting after running ${clock.loopLimit} timers, assuming an infinite loop!` - ); + return stubbed; + }; - if (!job.error) { - return infiniteLoopError; - } + sandbox.inject = function inject(obj) { + obj.spy = function () { + return sandbox.spy.apply(null, arguments); + }; - // pattern never matched in Node - const computedTargetPattern = /target\.*[<|(|[].*?[>|\]|)]\s*/; - let clockMethodPattern = new RegExp( - String(Object.keys(clock).join("|")) - ); + obj.stub = function () { + return sandbox.stub.apply(null, arguments); + }; - if (addTimerReturnsObject) { - // node.js environment - clockMethodPattern = new RegExp( - `\\s+at (Object\\.)?(?:${Object.keys(clock).join("|")})\\s+` - ); - } + obj.mock = function () { + return sandbox.mock.apply(null, arguments); + }; - let matchedLineIndex = -1; - job.error.stack.split("\n").some(function (line, i) { - // If we've matched a computed target line (e.g. setTimeout) then we - // don't need to look any further. Return true to stop iterating. - const matchedComputedTarget = line.match(computedTargetPattern); - /* istanbul ignore if */ - if (matchedComputedTarget) { - matchedLineIndex = i; - return true; - } + obj.createStubInstance = function () { + return sandbox.createStubInstance.apply(sandbox, arguments); + }; - // If we've matched a clock method line, then there may still be - // others further down the trace. Return false to keep iterating. - const matchedClockMethod = line.match(clockMethodPattern); - if (matchedClockMethod) { - matchedLineIndex = i; - return false; - } + obj.fake = function () { + return sandbox.fake.apply(null, arguments); + }; - // If we haven't matched anything on this line, but we matched - // previously and set the matched line index, then we can stop. - // If we haven't matched previously, then we should keep iterating. - return matchedLineIndex >= 0; - }); + obj.define = function () { + return sandbox.define.apply(null, arguments); + }; - const stack = `${infiniteLoopError}\n${job.type || "Microtask"} - ${ - job.func.name || "anonymous" - }\n${job.error.stack - .split("\n") - .slice(matchedLineIndex + 1) - .join("\n")}`; + obj.replace = function () { + return sandbox.replace.apply(null, arguments); + }; - try { - Object.defineProperty(infiniteLoopError, "stack", { - value: stack, - }); - } catch (e) { - // noop - } + obj.replaceSetter = function () { + return sandbox.replaceSetter.apply(null, arguments); + }; - return infiniteLoopError; - } + obj.replaceGetter = function () { + return sandbox.replaceGetter.apply(null, arguments); + }; - /** - * @param {Date} target - * @param {Date} source - * @returns {Date} the target after modifications - */ - function mirrorDateProperties(target, source) { - let prop; - for (prop in source) { - if (source.hasOwnProperty(prop)) { - target[prop] = source[prop]; - } + if (sandbox.clock) { + obj.clock = sandbox.clock; } - // set special now implementation - if (source.now) { - target.now = function now() { - return target.clock.now; - }; - } else { - delete target.now; + if (sandbox.server) { + obj.server = sandbox.server; + obj.requests = sandbox.server.requests; } - // set special toSource implementation - if (source.toSource) { - target.toSource = function toSource() { - return source.toSource(); - }; - } else { - delete target.toSource; - } + obj.match = match; - // set special toString implementation - target.toString = function toString() { - return source.toString(); - }; + return obj; + }; - target.prototype = source.prototype; - target.parse = source.parse; - target.UTC = source.UTC; - target.prototype.toUTCString = source.prototype.toUTCString; - target.isFake = true; + sandbox.mock = function mock() { + const m = sinonMock.apply(null, arguments); - return target; - } + addToCollection(m); + usePromiseLibrary(promiseLib, m); - //eslint-disable-next-line jsdoc/require-jsdoc - function createDate() { - /** - * @param {number} year - * @param {number} month - * @param {number} date - * @param {number} hour - * @param {number} minute - * @param {number} second - * @param {number} ms - * @returns {Date} - */ - function ClockDate(year, month, date, hour, minute, second, ms) { - // the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2. - // This remains so in the 10th edition of 2019 as well. - if (!(this instanceof ClockDate)) { - return new NativeDate(ClockDate.clock.now).toString(); - } + return m; + }; - // if Date is called as a constructor with 'new' keyword - // Defensive and verbose to avoid potential harm in passing - // explicit undefined when user does not pass argument - switch (arguments.length) { - case 0: - return new NativeDate(ClockDate.clock.now); - case 1: - return new NativeDate(year); - case 2: - return new NativeDate(year, month); - case 3: - return new NativeDate(year, month, date); - case 4: - return new NativeDate(year, month, date, hour); - case 5: - return new NativeDate(year, month, date, hour, minute); - case 6: - return new NativeDate( - year, - month, - date, - hour, - minute, - second - ); - default: - return new NativeDate( - year, - month, - date, - hour, - minute, - second, - ms - ); + sandbox.reset = function reset() { + applyOnEach(collection, "reset"); + applyOnEach(collection, "resetHistory"); + }; + + sandbox.resetBehavior = function resetBehavior() { + applyOnEach(collection, "resetBehavior"); + }; + + sandbox.resetHistory = function resetHistory() { + function privateResetHistory(f) { + const method = f.resetHistory || f.reset; + if (method) { + method.call(f); } } - return mirrorDateProperties(ClockDate, NativeDate); - } + forEach(collection, privateResetHistory); + }; - //eslint-disable-next-line jsdoc/require-jsdoc - function enqueueJob(clock, job) { - // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob - if (!clock.jobs) { - clock.jobs = []; + sandbox.restore = function restore() { + if (arguments.length) { + throw new Error( + "sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()" + ); } - clock.jobs.push(job); - } - //eslint-disable-next-line jsdoc/require-jsdoc - function runJobs(clock) { - // runs all microtick-deferred tasks - ecma262/#sec-runjobs - if (!clock.jobs) { + reverse(collection); + applyOnEach(collection, "restore"); + collection = []; + + forEach(fakeRestorers, function (restorer) { + restorer(); + }); + fakeRestorers = []; + + sandbox.restoreContext(); + }; + + sandbox.restoreContext = function restoreContext() { + if (!sandbox.injectedKeys) { return; } - for (let i = 0; i < clock.jobs.length; i++) { - const job = clock.jobs[i]; - job.func.apply(null, job.args); - checkIsNearInfiniteLimit(clock, i); - if (clock.loopLimit && i > clock.loopLimit) { - throw getInfiniteLoopError(clock, job); - } - } - resetIsNearInfiniteLimit(); - clock.jobs = []; - } + forEach(sandbox.injectedKeys, function (injectedKey) { + delete sandbox.injectInto[injectedKey]; + }); + + sandbox.injectedKeys.length = 0; + }; /** - * @param {Clock} clock - * @param {Timer} timer - * @returns {number} id of the created timer + * Creates a restorer function for the property + * + * @param {object|Function} object + * @param {string} property + * @param {boolean} forceAssignment + * @returns {Function} restorer function */ - function addTimer(clock, timer) { - if (timer.func === undefined) { - throw new Error("Callback must be provided to timer calls"); + function getFakeRestorer(object, property, forceAssignment = false) { + const descriptor = getPropertyDescriptor(object, property); + const value = object[property]; + + function restorer() { + if (forceAssignment) { + object[property] = value; + } else if (descriptor?.isOwn) { + Object.defineProperty(object, property, descriptor); + } else { + delete object[property]; + } } - if (addTimerReturnsObject) { - // Node.js environment - if (typeof timer.func !== "function") { + restorer.object = object; + restorer.property = property; + return restorer; + } + + function verifyNotReplaced(object, property) { + forEach(fakeRestorers, function (fakeRestorer) { + if ( + fakeRestorer.object === object && + fakeRestorer.property === property + ) { throw new TypeError( - `[ERR_INVALID_CALLBACK]: Callback must be a function. Received ${ - timer.func - } of type ${typeof timer.func}` + `Attempted to replace ${property} which is already replaced` ); } - } + }); + } - if (isNearInfiniteLimit) { - timer.error = new Error(); - } + /** + * Replace an existing property + * + * @param {object|Function} object + * @param {string} property + * @param {*} replacement a fake, stub, spy or any other value + * @returns {*} + */ + sandbox.replace = function replace(object, property, replacement) { + const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + throwOnAccessors(descriptor); + verifySameType(object, property, replacement); - timer.type = timer.immediate ? "Immediate" : "Timeout"; + verifyNotReplaced(object, property); - if (timer.hasOwnProperty("delay")) { - if (typeof timer.delay !== "number") { - timer.delay = parseInt(timer.delay, 10); - } + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); - if (!isNumberFinite(timer.delay)) { - timer.delay = 0; - } - timer.delay = timer.delay > maxTimeout ? 1 : timer.delay; - timer.delay = Math.max(0, timer.delay); - } + object[property] = replacement; - if (timer.hasOwnProperty("interval")) { - timer.type = "Interval"; - timer.interval = timer.interval > maxTimeout ? 1 : timer.interval; - } + return replacement; + }; - if (timer.hasOwnProperty("animation")) { - timer.type = "AnimationFrame"; - timer.animation = true; - } + sandbox.replace.usingAccessor = function replaceUsingAccessor( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + verifySameType(object, property, replacement); - if (timer.hasOwnProperty("idleCallback")) { - timer.type = "IdleCallback"; - timer.idleCallback = true; + verifyNotReplaced(object, property); + + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property, true)); + + object[property] = replacement; + + return replacement; + }; + + sandbox.define = function define(object, property, value) { + const descriptor = getPropertyDescriptor(object, property); + + if (descriptor) { + throw new TypeError( + `Cannot define the already existing property ${valueToString( + property + )}. Perhaps you meant sandbox.replace()?` + ); } - if (!clock.timers) { - clock.timers = {}; + if (typeof value === "undefined") { + throw new TypeError("Expected value argument to be defined"); } - timer.id = uniqueTimerId++; - timer.createdAt = clock.now; - timer.callAt = - clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); + verifyNotReplaced(object, property); - clock.timers[timer.id] = timer; + // store a function for restoring the defined property + push(fakeRestorers, getFakeRestorer(object, property)); - if (addTimerReturnsObject) { - const res = { - refed: true, - ref: function () { - this.refed = true; - return res; - }, - unref: function () { - this.refed = false; - return res; - }, - hasRef: function () { - return this.refed; - }, - refresh: function () { - timer.callAt = - clock.now + - (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); - - // it _might_ have been removed, but if not the assignment is perfectly fine - clock.timers[timer.id] = timer; + object[property] = value; - return res; - }, - [Symbol.toPrimitive]: function () { - return timer.id; - }, - }; - return res; - } + return value; + }; - return timer.id; - } + sandbox.replaceGetter = function replaceGetter( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); - /* eslint consistent-return: "off" */ - /** - * Timer comparitor - * - * @param {Timer} a - * @param {Timer} b - * @returns {number} - */ - function compareTimers(a, b) { - // Sort first by absolute timing - if (a.callAt < b.callAt) { - return -1; - } - if (a.callAt > b.callAt) { - return 1; + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}` + ); } - // Sort next by immediate, immediate timers take precedence - if (a.immediate && !b.immediate) { - return -1; - } - if (!a.immediate && b.immediate) { - return 1; + if (typeof replacement !== "function") { + throw new TypeError( + "Expected replacement argument to be a function" + ); } - // Sort next by creation time, earlier-created timers take precedence - if (a.createdAt < b.createdAt) { - return -1; + if (typeof descriptor.get !== "function") { + throw new Error("`object.property` is not a getter"); } - if (a.createdAt > b.createdAt) { - return 1; + + verifyNotReplaced(object, property); + + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); + + Object.defineProperty(object, property, { + get: replacement, + configurable: isPropertyConfigurable(object, property), + }); + + return replacement; + }; + + sandbox.replaceSetter = function replaceSetter( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); + + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}` + ); } - // Sort next by id, lower-id timers take precedence - if (a.id < b.id) { - return -1; + if (typeof replacement !== "function") { + throw new TypeError( + "Expected replacement argument to be a function" + ); } - if (a.id > b.id) { - return 1; + + if (typeof descriptor.set !== "function") { + throw new Error("`object.property` is not a setter"); } - // As timer ids are unique, no fallback `0` is necessary - } + verifyNotReplaced(object, property); - /** - * @param {Clock} clock - * @param {number} from - * @param {number} to - * @returns {Timer} - */ - function firstTimerInRange(clock, from, to) { - const timers = clock.timers; - let timer = null; - let id, isInRange; + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); - for (id in timers) { - if (timers.hasOwnProperty(id)) { - isInRange = inRange(from, to, timers[id]); + // eslint-disable-next-line accessor-pairs + Object.defineProperty(object, property, { + set: replacement, + configurable: isPropertyConfigurable(object, property), + }); - if ( - isInRange && - (!timer || compareTimers(timer, timers[id]) === 1) - ) { - timer = timers[id]; - } - } - } + return replacement; + }; - return timer; - } + function commonPostInitSetup(args, spy) { + const [object, property, types] = args; - /** - * @param {Clock} clock - * @returns {Timer} - */ - function firstTimer(clock) { - const timers = clock.timers; - let timer = null; - let id; + const isSpyingOnEntireObject = + typeof property === "undefined" && typeof object === "object"; - for (id in timers) { - if (timers.hasOwnProperty(id)) { - if (!timer || compareTimers(timer, timers[id]) === 1) { - timer = timers[id]; - } + if (isSpyingOnEntireObject) { + const ownMethods = collectOwnMethods(spy); + + forEach(ownMethods, function (method) { + addToCollection(method); + }); + + usePromiseLibrary(promiseLib, ownMethods); + } else if (Array.isArray(types)) { + for (const accessorType of types) { + addToCollection(spy[accessorType]); + usePromiseLibrary(promiseLib, spy[accessorType]); } + } else { + addToCollection(spy); + usePromiseLibrary(promiseLib, spy); } - return timer; + return spy; } - /** - * @param {Clock} clock - * @returns {Timer} - */ - function lastTimer(clock) { - const timers = clock.timers; - let timer = null; - let id; + sandbox.spy = function spy() { + const createdSpy = sinonSpy.apply(sinonSpy, arguments); + return commonPostInitSetup(arguments, createdSpy); + }; - for (id in timers) { - if (timers.hasOwnProperty(id)) { - if (!timer || compareTimers(timer, timers[id]) === -1) { - timer = timers[id]; - } - } - } + sandbox.stub = function stub() { + const createdStub = sinonStub.apply(sinonStub, arguments); + return commonPostInitSetup(arguments, createdStub); + }; - return timer; - } + // eslint-disable-next-line no-unused-vars + sandbox.fake = function fake(f) { + const s = sinonFake.apply(sinonFake, arguments); - /** - * @param {Clock} clock - * @param {Timer} timer - */ - function callTimer(clock, timer) { - if (typeof timer.interval === "number") { - clock.timers[timer.id].callAt += timer.interval; - } else { - delete clock.timers[timer.id]; - } + addToCollection(s); - if (typeof timer.func === "function") { - timer.func.apply(null, timer.args); - } else { - /* eslint no-eval: "off" */ - const eval2 = eval; - (function () { - eval2(timer.func); - })(); - } - } + return s; + }; - /** - * Gets clear handler name for a given timer type - * - * @param {string} ttype - */ - function getClearHandler(ttype) { - if (ttype === "IdleCallback" || ttype === "AnimationFrame") { - return `cancel${ttype}`; - } - return `clear${ttype}`; - } + forEach(Object.keys(sinonFake), function (key) { + const fakeBehavior = sinonFake[key]; + if (typeof fakeBehavior === "function") { + sandbox.fake[key] = function () { + const s = fakeBehavior.apply(fakeBehavior, arguments); - /** - * Gets schedule handler name for a given timer type - * - * @param {string} ttype - */ - function getScheduleHandler(ttype) { - if (ttype === "IdleCallback" || ttype === "AnimationFrame") { - return `request${ttype}`; - } - return `set${ttype}`; - } + addToCollection(s); - /** - * Creates an anonymous function to warn only once - */ - function createWarnOnce() { - let calls = 0; - return function (msg) { - // eslint-disable-next-line - !calls++ && console.warn(msg); - }; - } - const warnOnce = createWarnOnce(); - - /** - * @param {Clock} clock - * @param {number} timerId - * @param {string} ttype - */ - function clearTimer(clock, timerId, ttype) { - if (!timerId) { - // null appears to be allowed in most browsers, and appears to be - // relied upon by some libraries, like Bootstrap carousel - return; - } - - if (!clock.timers) { - clock.timers = {}; + return s; + }; } + }); - // in Node, the ID is stored as the primitive value for `Timeout` objects - // for `Immediate` objects, no ID exists, so it gets coerced to NaN - const id = Number(timerId); - - if (Number.isNaN(id) || id < idCounterStart) { - const handlerName = getClearHandler(ttype); + sandbox.useFakeTimers = function useFakeTimers(args) { + const clock = sinonClock.useFakeTimers.call(null, args); - if (clock.shouldClearNativeTimers === true) { - const nativeHandler = clock[`_${handlerName}`]; - return typeof nativeHandler === "function" - ? nativeHandler(timerId) - : undefined; - } - warnOnce( - `FakeTimers: ${handlerName} was invoked to clear a native timer instead of one created by this library.` + - "\nTo automatically clean-up native timers, use `shouldClearNativeTimers`." - ); - } + sandbox.clock = clock; + addToCollection(clock); - if (clock.timers.hasOwnProperty(id)) { - // check that the ID matches a timer of the correct type - const timer = clock.timers[id]; - if ( - timer.type === ttype || - (timer.type === "Timeout" && ttype === "Interval") || - (timer.type === "Interval" && ttype === "Timeout") - ) { - delete clock.timers[id]; - } else { - const clear = getClearHandler(ttype); - const schedule = getScheduleHandler(timer.type); - throw new Error( - `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()` - ); - } - } - } + return clock; + }; - /** - * @param {Clock} clock - * @param {Config} config - * @returns {Timer[]} - */ - function uninstall(clock, config) { - let method, i, l; - const installedHrTime = "_hrtime"; - const installedNextTick = "_nextTick"; + sandbox.verify = function verify() { + applyOnEach(collection, "verify"); + }; - for (i = 0, l = clock.methods.length; i < l; i++) { - method = clock.methods[i]; - if (method === "hrtime" && _global.process) { - _global.process.hrtime = clock[installedHrTime]; - } else if (method === "nextTick" && _global.process) { - _global.process.nextTick = clock[installedNextTick]; - } else if (method === "performance") { - const originalPerfDescriptor = Object.getOwnPropertyDescriptor( - clock, - `_${method}` - ); - if ( - originalPerfDescriptor && - originalPerfDescriptor.get && - !originalPerfDescriptor.set - ) { - Object.defineProperty( - _global, - method, - originalPerfDescriptor - ); - } else if (originalPerfDescriptor.configurable) { - _global[method] = clock[`_${method}`]; - } - } else { - if (_global[method] && _global[method].hadOwnProperty) { - _global[method] = clock[`_${method}`]; - } else { - try { - delete _global[method]; - } catch (ignore) { - /* eslint no-empty: "off" */ - } - } - } - } + sandbox.verifyAndRestore = function verifyAndRestore() { + let exception; - if (config.shouldAdvanceTime === true) { - _global.clearInterval(clock.attachedInterval); + try { + sandbox.verify(); + } catch (e) { + exception = e; } - // Prevent multiple executions which will completely remove these props - clock.methods = []; + sandbox.restore(); - // return pending timers, to enable checking what timers remained on uninstall - if (!clock.timers) { - return []; + if (exception) { + throw exception; } - return Object.keys(clock.timers).map(function mapper(key) { - return clock.timers[key]; - }); - } - - /** - * @param {object} target the target containing the method to replace - * @param {string} method the keyname of the method on the target - * @param {Clock} clock - */ - function hijackMethod(target, method, clock) { - clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call( - target, - method - ); - clock[`_${method}`] = target[method]; - - if (method === "Date") { - const date = mirrorDateProperties(clock[method], target[method]); - target[method] = date; - } else if (method === "performance") { - const originalPerfDescriptor = Object.getOwnPropertyDescriptor( - target, - method - ); - // JSDOM has a read only performance field so we have to save/copy it differently - if ( - originalPerfDescriptor && - originalPerfDescriptor.get && - !originalPerfDescriptor.set - ) { - Object.defineProperty( - clock, - `_${method}`, - originalPerfDescriptor - ); + }; - const perfDescriptor = Object.getOwnPropertyDescriptor( - clock, - method - ); - Object.defineProperty(target, method, perfDescriptor); - } else { - target[method] = clock[method]; - } - } else { - target[method] = function () { - return clock[method].apply(clock, arguments); - }; + sandbox.useFakeServer = function useFakeServer() { + const proto = sandbox.serverPrototype || fakeServer; - Object.defineProperties( - target[method], - Object.getOwnPropertyDescriptors(clock[method]) - ); + if (!proto || !proto.create) { + return null; } - target[method].clock = clock; - } - - /** - * @param {Clock} clock - * @param {number} advanceTimeDelta - */ - function doIntervalTick(clock, advanceTimeDelta) { - clock.tick(advanceTimeDelta); - } + sandbox.server = proto.create(); + addToCollection(sandbox.server); - /** - * @typedef {object} Timers - * @property {setTimeout} setTimeout - * @property {clearTimeout} clearTimeout - * @property {setInterval} setInterval - * @property {clearInterval} clearInterval - * @property {Date} Date - * @property {SetImmediate=} setImmediate - * @property {function(NodeImmediate): void=} clearImmediate - * @property {function(number[]):number[]=} hrtime - * @property {NextTick=} nextTick - * @property {Performance=} performance - * @property {RequestAnimationFrame=} requestAnimationFrame - * @property {boolean=} queueMicrotask - * @property {function(number): void=} cancelAnimationFrame - * @property {RequestIdleCallback=} requestIdleCallback - * @property {function(number): void=} cancelIdleCallback - */ + return sandbox.server; + }; - /** @type {Timers} */ - const timers = { - setTimeout: _global.setTimeout, - clearTimeout: _global.clearTimeout, - setInterval: _global.setInterval, - clearInterval: _global.clearInterval, - Date: _global.Date, + sandbox.useFakeXMLHttpRequest = function useFakeXMLHttpRequest() { + const xhr = fakeXhr.useFakeXMLHttpRequest(); + addToCollection(xhr); + return xhr; }; - if (setImmediatePresent) { - timers.setImmediate = _global.setImmediate; - timers.clearImmediate = _global.clearImmediate; - } + sandbox.usingPromise = function usingPromise(promiseLibrary) { + promiseLib = promiseLibrary; + collection.promiseLibrary = promiseLibrary; - if (hrtimePresent) { - timers.hrtime = _global.process.hrtime; - } + return sandbox; + }; + } - if (nextTickPresent) { - timers.nextTick = _global.process.nextTick; - } + Sandbox.prototype.match = match; - if (performancePresent) { - timers.performance = _global.performance; - } + module.exports = Sandbox; - if (requestAnimationFramePresent) { - timers.requestAnimationFrame = _global.requestAnimationFrame; - } + },{"./assert":3,"./collect-own-methods":5,"./create-stub-instance":8,"./fake":10,"./mock":12,"./spy":21,"./stub":22,"./util/core/get-property-descriptor":29,"./util/core/is-property-configurable":32,"./util/core/use-promise-library":37,"./util/fake-timers":41,"@sinonjs/commons":48,"@sinonjs/samsam":88,"nise":128}],20:[function(require,module,exports){ - if (queueMicrotaskPresent) { - timers.queueMicrotask = true; - } + const arrayProto = require("@sinonjs/commons").prototypes.array; + const color = require("./color"); + const match = require("@sinonjs/samsam").createMatcher; + const timesInWords = require("./util/core/times-in-words"); + const inspect = require("util").inspect; + const jsDiff = require("diff"); - if (cancelAnimationFramePresent) { - timers.cancelAnimationFrame = _global.cancelAnimationFrame; - } + const join = arrayProto.join; + const map = arrayProto.map; + const push = arrayProto.push; + const slice = arrayProto.slice; - if (requestIdleCallbackPresent) { - timers.requestIdleCallback = _global.requestIdleCallback; + function colorSinonMatchText(matcher, calledArg, calledArgMessage) { + let calledArgumentMessage = calledArgMessage; + let matcherMessage = matcher.message; + if (!matcher.test(calledArg)) { + matcherMessage = color.red(matcher.message); + if (calledArgumentMessage) { + calledArgumentMessage = color.green(calledArgumentMessage); + } } + return `${calledArgumentMessage} ${matcherMessage}`; + } - if (cancelIdleCallbackPresent) { - timers.cancelIdleCallback = _global.cancelIdleCallback; + function colorDiffText(diff) { + const objects = map(diff, function (part) { + let text = part.value; + if (part.added) { + text = color.green(text); + } else if (part.removed) { + text = color.red(text); + } + if (diff.length === 2) { + text += " "; // format simple diffs + } + return text; + }); + return join(objects, ""); + } + + function quoteStringValue(value) { + if (typeof value === "string") { + return JSON.stringify(value); } + return value; + } - const originalSetTimeout = _global.setImmediate || _global.setTimeout; + module.exports = { + c: function (spyInstance) { + return timesInWords(spyInstance.callCount); + }, - /** - * @param {Date|number} [start] the system time - non-integer values are floored - * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll() - * @returns {Clock} - */ - function createClock(start, loopLimit) { - // eslint-disable-next-line no-param-reassign - start = Math.floor(getEpoch(start)); - // eslint-disable-next-line no-param-reassign - loopLimit = loopLimit || 1000; - let nanos = 0; - const adjustedSystemTime = [0, 0]; // [millis, nanoremainder] + n: function (spyInstance) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return spyInstance.toString(); + }, - if (NativeDate === undefined) { - throw new Error( - "The global scope doesn't have a `Date` object" + - " (see https://github.com/sinonjs/sinon/issues/1852#issuecomment-419622780)" - ); - } + D: function (spyInstance, args) { + let message = ""; - const clock = { - now: start, - Date: createDate(), - loopLimit: loopLimit, - }; + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + // describe multiple calls + if (l > 1) { + message += `\nCall ${i + 1}:`; + } + const calledArgs = spyInstance.getCall(i).args; + const expectedArgs = slice(args); - clock.Date.clock = clock; + for ( + let j = 0; + j < calledArgs.length || j < expectedArgs.length; + ++j + ) { + let calledArg = calledArgs[j]; + let expectedArg = expectedArgs[j]; + if (calledArg) { + calledArg = quoteStringValue(calledArg); + } - //eslint-disable-next-line jsdoc/require-jsdoc - function getTimeToNextFrame() { - return 16 - ((clock.now - start) % 16); - } + if (expectedArg) { + expectedArg = quoteStringValue(expectedArg); + } - //eslint-disable-next-line jsdoc/require-jsdoc - function hrtime(prev) { - const millisSinceStart = clock.now - adjustedSystemTime[0] - start; - const secsSinceStart = Math.floor(millisSinceStart / 1000); - const remainderInNanos = - (millisSinceStart - secsSinceStart * 1e3) * 1e6 + - nanos - - adjustedSystemTime[1]; + message += "\n"; - if (Array.isArray(prev)) { - if (prev[1] > 1e9) { - throw new TypeError( - "Number of nanoseconds can't exceed a billion" + const calledArgMessage = + j < calledArgs.length ? inspect(calledArg) : ""; + if (match.isMatcher(expectedArg)) { + message += colorSinonMatchText( + expectedArg, + calledArg, + calledArgMessage + ); + } else { + const expectedArgMessage = + j < expectedArgs.length ? inspect(expectedArg) : ""; + const diff = jsDiff.diffJson( + calledArgMessage, + expectedArgMessage ); + message += colorDiffText(diff); } + } + } - const oldSecs = prev[0]; - let nanoDiff = remainderInNanos - prev[1]; - let secDiff = secsSinceStart - oldSecs; + return message; + }, - if (nanoDiff < 0) { - nanoDiff += 1e9; - secDiff -= 1; - } + C: function (spyInstance) { + const calls = []; - return [secDiff, nanoDiff]; + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + let stringifiedCall = ` ${spyInstance.getCall(i).toString()}`; + if (/\n/.test(calls[i - 1])) { + stringifiedCall = `\n${stringifiedCall}`; } - return [secsSinceStart, remainderInNanos]; + push(calls, stringifiedCall); } - function fakePerformanceNow() { - const hrt = hrtime(); - const millis = hrt[0] * 1000 + hrt[1] / 1e6; - return millis; - } + return calls.length > 0 ? `\n${join(calls, "\n")}` : ""; + }, - if (hrtimeBigintPresent) { - hrtime.bigint = function () { - const parts = hrtime(); - return BigInt(parts[0]) * BigInt(1e9) + BigInt(parts[1]); // eslint-disable-line - }; - } + t: function (spyInstance) { + const objects = []; - clock.requestIdleCallback = function requestIdleCallback( - func, - timeout - ) { - let timeToNextIdlePeriod = 0; + for (let i = 0, l = spyInstance.callCount; i < l; ++i) { + push(objects, inspect(spyInstance.thisValues[i])); + } - if (clock.countTimers() > 0) { - timeToNextIdlePeriod = 50; // const for now - } + return join(objects, ", "); + }, - const result = addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 2), - delay: - typeof timeout === "undefined" - ? timeToNextIdlePeriod - : Math.min(timeout, timeToNextIdlePeriod), - idleCallback: true, - }); + "*": function (spyInstance, args) { + return join( + map(args, function (arg) { + return inspect(arg); + }), + ", " + ); + }, + }; - return Number(result); - }; + },{"./color":6,"./util/core/times-in-words":36,"@sinonjs/commons":48,"@sinonjs/samsam":88,"diff":114,"util":113}],21:[function(require,module,exports){ - clock.cancelIdleCallback = function cancelIdleCallback(timerId) { - return clearTimer(clock, timerId, "IdleCallback"); - }; + const arrayProto = require("@sinonjs/commons").prototypes.array; + const createProxy = require("./proxy"); + const extend = require("./util/core/extend"); + const functionName = require("@sinonjs/commons").functionName; + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const deepEqual = require("@sinonjs/samsam").deepEqual; + const isEsModule = require("./util/core/is-es-module"); + const proxyCallUtil = require("./proxy-call-util"); + const walkObject = require("./util/core/walk-object"); + const wrapMethod = require("./util/core/wrap-method"); + const valueToString = require("@sinonjs/commons").valueToString; - clock.setTimeout = function setTimeout(func, timeout) { - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 2), - delay: timeout, - }); - }; - if (typeof _global.Promise !== "undefined" && utilPromisify) { - clock.setTimeout[utilPromisify.custom] = - function promisifiedSetTimeout(timeout, arg) { - return new _global.Promise(function setTimeoutExecutor( - resolve - ) { - addTimer(clock, { - func: resolve, - args: [arg], - delay: timeout, - }); - }); - }; - } + /* cache references to library methods so that they also can be stubbed without problems */ + const forEach = arrayProto.forEach; + const pop = arrayProto.pop; + const push = arrayProto.push; + const slice = arrayProto.slice; + const filter = Array.prototype.filter; - clock.clearTimeout = function clearTimeout(timerId) { - return clearTimer(clock, timerId, "Timeout"); - }; + let uuid = 0; - clock.nextTick = function nextTick(func) { - return enqueueJob(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 1), - error: isNearInfiniteLimit ? new Error() : null, - }); - }; + function matches(fake, args, strict) { + const margs = fake.matchingArguments; + if ( + margs.length <= args.length && + deepEqual(slice(args, 0, margs.length), margs) + ) { + return !strict || margs.length === args.length; + } + return false; + } - clock.queueMicrotask = function queueMicrotask(func) { - return clock.nextTick(func); // explicitly drop additional arguments - }; + // Public API + const spyApi = { + withArgs: function () { + const args = slice(arguments); + const matching = pop(this.matchingFakes(args, true)); + if (matching) { + return matching; + } - clock.setInterval = function setInterval(func, timeout) { - // eslint-disable-next-line no-param-reassign - timeout = parseInt(timeout, 10); - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 2), - delay: timeout, - interval: timeout, - }); - }; + const original = this; + const fake = this.instantiateFake(); + fake.matchingArguments = args; + fake.parent = this; + push(this.fakes, fake); - clock.clearInterval = function clearInterval(timerId) { - return clearTimer(clock, timerId, "Interval"); + fake.withArgs = function () { + return original.withArgs.apply(original, arguments); }; - if (setImmediatePresent) { - clock.setImmediate = function setImmediate(func) { - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 1), - immediate: true, - }); - }; - - if (typeof _global.Promise !== "undefined" && utilPromisify) { - clock.setImmediate[utilPromisify.custom] = - function promisifiedSetImmediate(arg) { - return new _global.Promise( - function setImmediateExecutor(resolve) { - addTimer(clock, { - func: resolve, - args: [arg], - immediate: true, - }); - } - ); - }; + forEach(original.args, function (arg, i) { + if (!matches(fake, arg)) { + return; } - clock.clearImmediate = function clearImmediate(timerId) { - return clearTimer(clock, timerId, "Immediate"); - }; - } + proxyCallUtil.incrementCallCount(fake); + push(fake.thisValues, original.thisValues[i]); + push(fake.args, arg); + push(fake.returnValues, original.returnValues[i]); + push(fake.exceptions, original.exceptions[i]); + push(fake.callIds, original.callIds[i]); + }); - clock.countTimers = function countTimers() { - return ( - Object.keys(clock.timers || {}).length + - (clock.jobs || []).length - ); - }; + proxyCallUtil.createCallProperties(fake); - clock.requestAnimationFrame = function requestAnimationFrame(func) { - const result = addTimer(clock, { - func: func, - delay: getTimeToNextFrame(), - get args() { - return [fakePerformanceNow()]; - }, - animation: true, - }); + return fake; + }, - return Number(result); - }; + // Override proxy default implementation + matchingFakes: function (args, strict) { + return filter.call(this.fakes, function (fake) { + return matches(fake, args, strict); + }); + }, + }; - clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) { - return clearTimer(clock, timerId, "AnimationFrame"); - }; + /* eslint-disable @sinonjs/no-prototype-methods/no-prototype-methods */ + const delegateToCalls = proxyCallUtil.delegateToCalls; + delegateToCalls(spyApi, "callArg", false, "callArgWith", true, function () { + throw new Error( + `${this.toString()} cannot call arg since it was not yet invoked.` + ); + }); + spyApi.callArgWith = spyApi.callArg; + delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", true, function () { + throw new Error( + `${this.toString()} cannot call arg since it was not yet invoked.` + ); + }); + spyApi.callArgOnWith = spyApi.callArgOn; + delegateToCalls(spyApi, "throwArg", false, "throwArg", false, function () { + throw new Error( + `${this.toString()} cannot throw arg since it was not yet invoked.` + ); + }); + delegateToCalls(spyApi, "yield", false, "yield", true, function () { + throw new Error( + `${this.toString()} cannot yield since it was not yet invoked.` + ); + }); + // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. + spyApi.invokeCallback = spyApi.yield; + delegateToCalls(spyApi, "yieldOn", false, "yieldOn", true, function () { + throw new Error( + `${this.toString()} cannot yield since it was not yet invoked.` + ); + }); + delegateToCalls(spyApi, "yieldTo", false, "yieldTo", true, function (property) { + throw new Error( + `${this.toString()} cannot yield to '${valueToString( + property + )}' since it was not yet invoked.` + ); + }); + delegateToCalls( + spyApi, + "yieldToOn", + false, + "yieldToOn", + true, + function (property) { + throw new Error( + `${this.toString()} cannot yield to '${valueToString( + property + )}' since it was not yet invoked.` + ); + } + ); - clock.runMicrotasks = function runMicrotasks() { - runJobs(clock); + function createSpy(func) { + let name; + let funk = func; + + if (typeof funk !== "function") { + funk = function () { + return; }; + } else { + name = functionName(funk); + } - /** - * @param {number|string} tickValue milliseconds or a string parseable by parseTime - * @param {boolean} isAsync - * @param {Function} resolve - * @param {Function} reject - * @returns {number|undefined} will return the new `now` value or nothing for async - */ - function doTick(tickValue, isAsync, resolve, reject) { - const msFloat = - typeof tickValue === "number" - ? tickValue - : parseTime(tickValue); - const ms = Math.floor(msFloat); - const remainder = nanoRemainder(msFloat); - let nanosTotal = nanos + remainder; - let tickTo = clock.now + ms; + const proxy = createProxy(funk, funk); - if (msFloat < 0) { - throw new TypeError("Negative ticks are not supported"); - } + // Inherit spy API: + extend.nonEnum(proxy, spyApi); + extend.nonEnum(proxy, { + displayName: name || "spy", + fakes: [], + instantiateFake: createSpy, + id: `spy#${uuid++}`, + }); + return proxy; + } - // adjust for positive overflow - if (nanosTotal >= 1e6) { - tickTo += 1; - nanosTotal -= 1e6; - } + function spy(object, property, types) { + if (isEsModule(object)) { + throw new TypeError("ES Modules cannot be spied"); + } - nanos = nanosTotal; - let tickFrom = clock.now; - let previous = clock.now; - // ESLint fails to detect this correctly - /* eslint-disable prefer-const */ - let timer, - firstException, - oldNow, - nextPromiseTick, - compensationCheck, - postTimerCall; - /* eslint-enable prefer-const */ + if (!property && typeof object === "function") { + return createSpy(object); + } - clock.duringTick = true; + if (!property && typeof object === "object") { + return walkObject(spy, object); + } - // perform microtasks - oldNow = clock.now; - runJobs(clock); - if (oldNow !== clock.now) { - // compensate for any setSystemTime() call during microtask callback - tickFrom += clock.now - oldNow; - tickTo += clock.now - oldNow; - } + if (!object && !property) { + return createSpy(function () { + return; + }); + } - //eslint-disable-next-line jsdoc/require-jsdoc - function doTickInner() { - // perform each timer in the requested range - timer = firstTimerInRange(clock, tickFrom, tickTo); - // eslint-disable-next-line no-unmodified-loop-condition - while (timer && tickFrom <= tickTo) { - if (clock.timers[timer.id]) { - tickFrom = timer.callAt; - clock.now = timer.callAt; - oldNow = clock.now; - try { - runJobs(clock); - callTimer(clock, timer); - } catch (e) { - firstException = firstException || e; - } - - if (isAsync) { - // finish up after native setImmediate callback to allow - // all native es6 promises to process their callbacks after - // each timer fires. - originalSetTimeout(nextPromiseTick); - return; - } + if (!types) { + return wrapMethod(object, property, createSpy(object[property])); + } - compensationCheck(); - } + const descriptor = {}; + const methodDesc = getPropertyDescriptor(object, property); - postTimerCall(); - } + forEach(types, function (type) { + descriptor[type] = createSpy(methodDesc[type]); + }); - // perform process.nextTick()s again - oldNow = clock.now; - runJobs(clock); - if (oldNow !== clock.now) { - // compensate for any setSystemTime() call during process.nextTick() callback - tickFrom += clock.now - oldNow; - tickTo += clock.now - oldNow; - } - clock.duringTick = false; + return wrapMethod(object, property, descriptor); + } - // corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo] - timer = firstTimerInRange(clock, tickFrom, tickTo); - if (timer) { - try { - clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range - } catch (e) { - firstException = firstException || e; - } - } else { - // no timers remaining in the requested range: move the clock all the way to the end - clock.now = tickTo; + extend(spy, spyApi); + module.exports = spy; - // update nanos - nanos = nanosTotal; - } - if (firstException) { - throw firstException; - } + },{"./proxy":17,"./proxy-call-util":14,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48,"@sinonjs/samsam":88}],22:[function(require,module,exports){ - if (isAsync) { - resolve(clock.now); - } else { - return clock.now; - } - } + const arrayProto = require("@sinonjs/commons").prototypes.array; + const behavior = require("./behavior"); + const behaviors = require("./default-behaviors"); + const createProxy = require("./proxy"); + const functionName = require("@sinonjs/commons").functionName; + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const isNonExistentProperty = require("./util/core/is-non-existent-property"); + const spy = require("./spy"); + const extend = require("./util/core/extend"); + const getPropertyDescriptor = require("./util/core/get-property-descriptor"); + const isEsModule = require("./util/core/is-es-module"); + const sinonType = require("./util/core/sinon-type"); + const wrapMethod = require("./util/core/wrap-method"); + const throwOnFalsyObject = require("./throw-on-falsy-object"); + const valueToString = require("@sinonjs/commons").valueToString; + const walkObject = require("./util/core/walk-object"); - nextPromiseTick = - isAsync && - function () { - try { - compensationCheck(); - postTimerCall(); - doTickInner(); - } catch (e) { - reject(e); - } - }; + const forEach = arrayProto.forEach; + const pop = arrayProto.pop; + const slice = arrayProto.slice; + const sort = arrayProto.sort; - compensationCheck = function () { - // compensate for any setSystemTime() call during timer callback - if (oldNow !== clock.now) { - tickFrom += clock.now - oldNow; - tickTo += clock.now - oldNow; - previous += clock.now - oldNow; - } - }; + let uuid = 0; - postTimerCall = function () { - timer = firstTimerInRange(clock, previous, tickTo); - previous = tickFrom; - }; + function createStub(originalFunc) { + // eslint-disable-next-line prefer-const + let proxy; - return doTickInner(); - } + function functionStub() { + const args = slice(arguments); + const matchings = proxy.matchingFakes(args); - /** - * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" - * @returns {number} will return the new `now` value - */ - clock.tick = function tick(tickValue) { - return doTick(tickValue, false); - }; + const fnStub = + pop( + sort(matchings, function (a, b) { + return ( + a.matchingArguments.length - b.matchingArguments.length + ); + }) + ) || proxy; + return getCurrentBehavior(fnStub).invoke(this, arguments); + } - if (typeof _global.Promise !== "undefined") { - /** - * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" - * @returns {Promise} - */ - clock.tickAsync = function tickAsync(tickValue) { - return new _global.Promise(function (resolve, reject) { - originalSetTimeout(function () { - try { - doTick(tickValue, true, resolve, reject); - } catch (e) { - reject(e); - } - }); - }); - }; - } + proxy = createProxy(functionStub, originalFunc || functionStub); + // Inherit spy API: + extend.nonEnum(proxy, spy); + // Inherit stub API: + extend.nonEnum(proxy, stub); - clock.next = function next() { - runJobs(clock); - const timer = firstTimer(clock); - if (!timer) { - return clock.now; - } + const name = originalFunc ? functionName(originalFunc) : null; + extend.nonEnum(proxy, { + fakes: [], + instantiateFake: createStub, + displayName: name || "stub", + defaultBehavior: null, + behaviors: [], + id: `stub#${uuid++}`, + }); - clock.duringTick = true; - try { - clock.now = timer.callAt; - callTimer(clock, timer); - runJobs(clock); - return clock.now; - } finally { - clock.duringTick = false; - } - }; + sinonType.set(proxy, "stub"); - if (typeof _global.Promise !== "undefined") { - clock.nextAsync = function nextAsync() { - return new _global.Promise(function (resolve, reject) { - originalSetTimeout(function () { - try { - const timer = firstTimer(clock); - if (!timer) { - resolve(clock.now); - return; - } + return proxy; + } - let err; - clock.duringTick = true; - clock.now = timer.callAt; - try { - callTimer(clock, timer); - } catch (e) { - err = e; - } - clock.duringTick = false; + function stub(object, property) { + if (arguments.length > 2) { + throw new TypeError( + "stub(obj, 'meth', fn) has been removed, see documentation" + ); + } - originalSetTimeout(function () { - if (err) { - reject(err); - } else { - resolve(clock.now); - } - }); - } catch (e) { - reject(e); - } - }); - }); - }; - } + if (isEsModule(object)) { + throw new TypeError("ES Modules cannot be stubbed"); + } - clock.runAll = function runAll() { - let numTimers, i; - runJobs(clock); - for (i = 0; i < clock.loopLimit; i++) { - if (!clock.timers) { - resetIsNearInfiniteLimit(); - return clock.now; - } + throwOnFalsyObject.apply(null, arguments); - numTimers = Object.keys(clock.timers).length; - if (numTimers === 0) { - resetIsNearInfiniteLimit(); - return clock.now; - } + if (isNonExistentProperty(object, property)) { + throw new TypeError( + `Cannot stub non-existent property ${valueToString(property)}` + ); + } - clock.next(); - checkIsNearInfiniteLimit(clock, i); - } + const actualDescriptor = getPropertyDescriptor(object, property); - const excessJob = firstTimer(clock); - throw getInfiniteLoopError(clock, excessJob); - }; + assertValidPropertyDescriptor(actualDescriptor, property); - clock.runToFrame = function runToFrame() { - return clock.tick(getTimeToNextFrame()); - }; - - if (typeof _global.Promise !== "undefined") { - clock.runAllAsync = function runAllAsync() { - return new _global.Promise(function (resolve, reject) { - let i = 0; - /** - * - */ - function doRun() { - originalSetTimeout(function () { - try { - let numTimers; - if (i < clock.loopLimit) { - if (!clock.timers) { - resetIsNearInfiniteLimit(); - resolve(clock.now); - return; - } + const isObjectOrFunction = + typeof object === "object" || typeof object === "function"; + const isStubbingEntireObject = + typeof property === "undefined" && isObjectOrFunction; + const isCreatingNewStub = !object && typeof property === "undefined"; + const isStubbingNonFuncProperty = + isObjectOrFunction && + typeof property !== "undefined" && + (typeof actualDescriptor === "undefined" || + typeof actualDescriptor.value !== "function"); - numTimers = Object.keys( - clock.timers - ).length; - if (numTimers === 0) { - resetIsNearInfiniteLimit(); - resolve(clock.now); - return; - } + if (isStubbingEntireObject) { + return walkObject(stub, object); + } - clock.next(); + if (isCreatingNewStub) { + return createStub(); + } - i++; + const func = + typeof actualDescriptor.value === "function" + ? actualDescriptor.value + : null; + const s = createStub(func); - doRun(); - checkIsNearInfiniteLimit(clock, i); - return; - } + extend.nonEnum(s, { + rootObj: object, + propName: property, + shadowsPropOnPrototype: !actualDescriptor.isOwn, + restore: function restore() { + if (actualDescriptor !== undefined && actualDescriptor.isOwn) { + Object.defineProperty(object, property, actualDescriptor); + return; + } - const excessJob = firstTimer(clock); - reject(getInfiniteLoopError(clock, excessJob)); - } catch (e) { - reject(e); - } - }); - } - doRun(); - }); - }; - } + delete object[property]; + }, + }); - clock.runToLast = function runToLast() { - const timer = lastTimer(clock); - if (!timer) { - runJobs(clock); - return clock.now; - } + return isStubbingNonFuncProperty ? s : wrapMethod(object, property, s); + } - return clock.tick(timer.callAt - clock.now); - }; + function assertValidPropertyDescriptor(descriptor, property) { + if (!descriptor || !property) { + return; + } + if (descriptor.isOwn && !descriptor.configurable && !descriptor.writable) { + throw new TypeError( + `Descriptor for property ${property} is non-configurable and non-writable` + ); + } + if ((descriptor.get || descriptor.set) && !descriptor.configurable) { + throw new TypeError( + `Descriptor for accessor property ${property} is non-configurable` + ); + } + if (isDataDescriptor(descriptor) && !descriptor.writable) { + throw new TypeError( + `Descriptor for data property ${property} is non-writable` + ); + } + } - if (typeof _global.Promise !== "undefined") { - clock.runToLastAsync = function runToLastAsync() { - return new _global.Promise(function (resolve, reject) { - originalSetTimeout(function () { - try { - const timer = lastTimer(clock); - if (!timer) { - resolve(clock.now); - } + function isDataDescriptor(descriptor) { + return ( + !descriptor.value && + !descriptor.writable && + !descriptor.set && + !descriptor.get + ); + } - resolve(clock.tickAsync(timer.callAt - clock.now)); - } catch (e) { - reject(e); - } - }); - }); - }; - } + /*eslint-disable no-use-before-define*/ + function getParentBehaviour(stubInstance) { + return stubInstance.parent && getCurrentBehavior(stubInstance.parent); + } - clock.reset = function reset() { - nanos = 0; - clock.timers = {}; - clock.jobs = []; - clock.now = start; - }; + function getDefaultBehavior(stubInstance) { + return ( + stubInstance.defaultBehavior || + getParentBehaviour(stubInstance) || + behavior.create(stubInstance) + ); + } - clock.setSystemTime = function setSystemTime(systemTime) { - // determine time difference - const newNow = getEpoch(systemTime); - const difference = newNow - clock.now; - let id, timer; + function getCurrentBehavior(stubInstance) { + const currentBehavior = stubInstance.behaviors[stubInstance.callCount - 1]; + return currentBehavior && currentBehavior.isPresent() + ? currentBehavior + : getDefaultBehavior(stubInstance); + } + /*eslint-enable no-use-before-define*/ - adjustedSystemTime[0] = adjustedSystemTime[0] + difference; - adjustedSystemTime[1] = adjustedSystemTime[1] + nanos; - // update 'system clock' - clock.now = newNow; - nanos = 0; + const proto = { + resetBehavior: function () { + this.defaultBehavior = null; + this.behaviors = []; - // update timers and intervals to keep them stable - for (id in clock.timers) { - if (clock.timers.hasOwnProperty(id)) { - timer = clock.timers[id]; - timer.createdAt += difference; - timer.callAt += difference; - } - } - }; + delete this.returnValue; + delete this.returnArgAt; + delete this.throwArgAt; + delete this.resolveArgAt; + delete this.fakeFn; + this.returnThis = false; + this.resolveThis = false; - /** - * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" - * @returns {number} will return the new `now` value - */ - clock.jump = function jump(tickValue) { - const msFloat = - typeof tickValue === "number" - ? tickValue - : parseTime(tickValue); - const ms = Math.floor(msFloat); + forEach(this.fakes, function (fake) { + fake.resetBehavior(); + }); + }, - for (const timer of Object.values(clock.timers)) { - if (clock.now + ms > timer.callAt) { - timer.callAt = clock.now + ms; - } - } - clock.tick(ms); - }; + reset: function () { + this.resetHistory(); + this.resetBehavior(); + }, - if (performancePresent) { - clock.performance = Object.create(null); - clock.performance.now = fakePerformanceNow; + onCall: function onCall(index) { + if (!this.behaviors[index]) { + this.behaviors[index] = behavior.create(this); } - if (hrtimePresent) { - clock.hrtime = hrtime; - } + return this.behaviors[index]; + }, - return clock; - } + onFirstCall: function onFirstCall() { + return this.onCall(0); + }, - /* eslint-disable complexity */ + onSecondCall: function onSecondCall() { + return this.onCall(1); + }, - /** - * @param {Config=} [config] Optional config - * @returns {Clock} - */ - function install(config) { - if ( - arguments.length > 1 || - config instanceof Date || - Array.isArray(config) || - typeof config === "number" - ) { - throw new TypeError( - `FakeTimers.install called with ${String( - config - )} install requires an object parameter` - ); - } + onThirdCall: function onThirdCall() { + return this.onCall(2); + }, - if (_global.Date.isFake === true) { - // Timers are already faked; this is a problem. - // Make the user reset timers before continuing. - throw new TypeError( - "Can't install fake timers twice on the same global object." - ); + withArgs: function withArgs() { + const fake = spy.withArgs.apply(this, arguments); + if (this.defaultBehavior && this.defaultBehavior.promiseLibrary) { + fake.defaultBehavior = + fake.defaultBehavior || behavior.create(fake); + fake.defaultBehavior.promiseLibrary = + this.defaultBehavior.promiseLibrary; } + return fake; + }, + }; - // eslint-disable-next-line no-param-reassign - config = typeof config !== "undefined" ? config : {}; - config.shouldAdvanceTime = config.shouldAdvanceTime || false; - config.advanceTimeDelta = config.advanceTimeDelta || 20; - config.shouldClearNativeTimers = - config.shouldClearNativeTimers || false; + forEach(Object.keys(behavior), function (method) { + if ( + hasOwnProperty(behavior, method) && + !hasOwnProperty(proto, method) && + method !== "create" && + method !== "invoke" + ) { + proto[method] = behavior.createBehavior(method); + } + }); - if (config.target) { - throw new TypeError( - "config.target is no longer supported. Use `withGlobal(target)` instead." - ); - } + forEach(Object.keys(behaviors), function (method) { + if (hasOwnProperty(behaviors, method) && !hasOwnProperty(proto, method)) { + behavior.addBehavior(stub, method, behaviors[method]); + } + }); - let i, l; - const clock = createClock(config.now, config.loopLimit); - clock.shouldClearNativeTimers = config.shouldClearNativeTimers; + extend(stub, proto); + module.exports = stub; - clock.uninstall = function () { - return uninstall(clock, config); - }; + },{"./behavior":4,"./default-behaviors":9,"./proxy":17,"./spy":21,"./throw-on-falsy-object":23,"./util/core/extend":26,"./util/core/get-property-descriptor":29,"./util/core/is-es-module":30,"./util/core/is-non-existent-property":31,"./util/core/sinon-type":35,"./util/core/walk-object":38,"./util/core/wrap-method":40,"@sinonjs/commons":48}],23:[function(require,module,exports){ + const valueToString = require("@sinonjs/commons").valueToString; - clock.methods = config.toFake || []; + function throwOnFalsyObject(object, property) { + if (property && !object) { + const type = object === null ? "null" : "undefined"; + throw new Error( + `Trying to stub property '${valueToString(property)}' of ${type}` + ); + } + } - if (clock.methods.length === 0) { - // do not fake nextTick by default - GitHub#126 - clock.methods = Object.keys(timers).filter(function (key) { - return key !== "nextTick" && key !== "queueMicrotask"; - }); - } + module.exports = throwOnFalsyObject; - if (config.shouldAdvanceTime === true) { - const intervalTick = doIntervalTick.bind( - null, - clock, - config.advanceTimeDelta - ); - const intervalId = _global.setInterval( - intervalTick, - config.advanceTimeDelta - ); - clock.attachedInterval = intervalId; - } + },{"@sinonjs/commons":48}],24:[function(require,module,exports){ - if (clock.methods.includes("performance")) { - const proto = (() => { - if (hasPerformancePrototype) { - return _global.Performance.prototype; - } - if (hasPerformanceConstructorPrototype) { - return _global.performance.constructor.prototype; - } - })(); - if (proto) { - Object.getOwnPropertyNames(proto).forEach(function (name) { - if (name !== "now") { - clock.performance[name] = - name.indexOf("getEntries") === 0 - ? NOOP_ARRAY - : NOOP; - } - }); - } else if ((config.toFake || []).includes("performance")) { - // user explicitly tried to fake performance when not present - throw new ReferenceError( - "non-existent performance object cannot be faked" - ); - } - } + module.exports = { + injectInto: null, + properties: [ + "spy", + "stub", + "mock", + "clock", + "server", + "requests", + "fake", + "define", + "replace", + "replaceSetter", + "replaceGetter", + "createStubInstance", + ], + useFakeTimers: true, + useFakeServer: true, + }; - for (i = 0, l = clock.methods.length; i < l; i++) { - const nameOfMethodToReplace = clock.methods[i]; - if (nameOfMethodToReplace === "hrtime") { - if ( - _global.process && - typeof _global.process.hrtime === "function" - ) { - hijackMethod(_global.process, nameOfMethodToReplace, clock); - } - } else if (nameOfMethodToReplace === "nextTick") { - if ( - _global.process && - typeof _global.process.nextTick === "function" - ) { - hijackMethod(_global.process, nameOfMethodToReplace, clock); - } - } else { - hijackMethod(_global, nameOfMethodToReplace, clock); + },{}],25:[function(require,module,exports){ + + const arrayProto = require("@sinonjs/commons").prototypes.array; + const reduce = arrayProto.reduce; + + module.exports = function exportAsyncBehaviors(behaviorMethods) { + return reduce( + Object.keys(behaviorMethods), + function (acc, method) { + // need to avoid creating another async versions of the newly added async methods + if (method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { + acc[`${method}Async`] = function () { + const result = behaviorMethods[method].apply( + this, + arguments + ); + this.callbackAsync = true; + return result; + }; } - } + return acc; + }, + {} + ); + }; - return clock; - } + },{"@sinonjs/commons":48}],26:[function(require,module,exports){ - /* eslint-enable complexity */ + const arrayProto = require("@sinonjs/commons").prototypes.array; + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; - return { - timers: timers, - createClock: createClock, - install: install, - withGlobal: withGlobal, + const join = arrayProto.join; + const push = arrayProto.push; + + // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug + const hasDontEnumBug = (function () { + const obj = { + constructor: function () { + return "0"; + }, + toString: function () { + return "1"; + }, + valueOf: function () { + return "2"; + }, + toLocaleString: function () { + return "3"; + }, + prototype: function () { + return "4"; + }, + isPrototypeOf: function () { + return "5"; + }, + propertyIsEnumerable: function () { + return "6"; + }, + hasOwnProperty: function () { + return "7"; + }, + length: function () { + return "8"; + }, + unique: function () { + return "9"; + }, }; - } + + const result = []; + for (const prop in obj) { + if (hasOwnProperty(obj, prop)) { + push(result, obj[prop]()); + } + } + return join(result, "") !== "0123456789"; + })(); /** - * @typedef {object} FakeTimers - * @property {Timers} timers - * @property {createClock} createClock - * @property {Function} install - * @property {withGlobal} withGlobal + * + * @param target + * @param sources + * @param doCopy + * @returns {*} target */ + function extendCommon(target, sources, doCopy) { + let source, i, prop; - /* eslint-enable complexity */ - - /** @type {FakeTimers} */ - const defaultImplementation = withGlobal(globalObject); - - exports.timers = defaultImplementation.timers; - exports.createClock = defaultImplementation.createClock; - exports.install = defaultImplementation.install; - exports.withGlobal = withGlobal; + for (i = 0; i < sources.length; i++) { + source = sources[i]; - },{"@sinonjs/commons":48,"util":113}],62:[function(require,module,exports){ + for (prop in source) { + if (hasOwnProperty(source, prop)) { + doCopy(target, source, prop); + } + } - var ARRAY_TYPES = [ - Array, - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - ]; - - module.exports = ARRAY_TYPES; - - },{}],63:[function(require,module,exports){ - - var arrayProto = require("@sinonjs/commons").prototypes.array; - var deepEqual = require("./deep-equal").use(createMatcher); // eslint-disable-line no-use-before-define - var every = require("@sinonjs/commons").every; - var functionName = require("@sinonjs/commons").functionName; - var get = require("lodash.get"); - var iterableToString = require("./iterable-to-string"); - var objectProto = require("@sinonjs/commons").prototypes.object; - var typeOf = require("@sinonjs/commons").typeOf; - var valueToString = require("@sinonjs/commons").valueToString; - - var assertMatcher = require("./create-matcher/assert-matcher"); - var assertMethodExists = require("./create-matcher/assert-method-exists"); - var assertType = require("./create-matcher/assert-type"); - var isIterable = require("./create-matcher/is-iterable"); - var isMatcher = require("./create-matcher/is-matcher"); + // Make sure we copy (own) toString method even when in JScript with DontEnum bug + // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug + if ( + hasDontEnumBug && + hasOwnProperty(source, "toString") && + source.toString !== target.toString + ) { + target.toString = source.toString; + } + } - var matcherPrototype = require("./create-matcher/matcher-prototype"); + return target; + } - var arrayIndexOf = arrayProto.indexOf; - var some = arrayProto.some; + /** + * Public: Extend target in place with all (own) properties, except 'name' when [[writable]] is false, + * from sources in-order. Thus, last source will override properties in previous sources. + * + * @param {object} target - The Object to extend + * @param {object[]} sources - Objects to copy properties from. + * @returns {object} the extended target + */ + module.exports = function extend(target, ...sources) { + return extendCommon( + target, + sources, + function copyValue(dest, source, prop) { + const destOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( + dest, + prop + ); + const sourceOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( + source, + prop + ); - var hasOwnProperty = objectProto.hasOwnProperty; - var objectToString = objectProto.toString; + if (prop === "name" && !destOwnPropertyDescriptor.writable) { + return; + } + const descriptors = { + configurable: sourceOwnPropertyDescriptor.configurable, + enumerable: sourceOwnPropertyDescriptor.enumerable, + }; + /* + if the sorce has an Accessor property copy over the accessor functions (get and set) + data properties has writable attribute where as accessor property don't + REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties + */ - var TYPE_MAP = require("./create-matcher/type-map")(createMatcher); // eslint-disable-line no-use-before-define + if (hasOwnProperty(sourceOwnPropertyDescriptor, "writable")) { + descriptors.writable = sourceOwnPropertyDescriptor.writable; + descriptors.value = sourceOwnPropertyDescriptor.value; + } else { + if (sourceOwnPropertyDescriptor.get) { + descriptors.get = + sourceOwnPropertyDescriptor.get.bind(dest); + } + if (sourceOwnPropertyDescriptor.set) { + descriptors.set = + sourceOwnPropertyDescriptor.set.bind(dest); + } + } + Object.defineProperty(dest, prop, descriptors); + } + ); + }; /** - * Creates a matcher object for the passed expectation + * Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will + * override properties in previous sources. Define the properties as non enumerable. * - * @alias module:samsam.createMatcher - * @param {*} expectation An expecttation - * @param {string} message A message for the expectation - * @returns {object} A matcher object + * @param {object} target - The Object to extend + * @param {object[]} sources - Objects to copy properties from. + * @returns {object} the extended target */ - function createMatcher(expectation, message) { - var m = Object.create(matcherPrototype); - var type = typeOf(expectation); + module.exports.nonEnum = function extendNonEnum(target, ...sources) { + return extendCommon( + target, + sources, + function copyProperty(dest, source, prop) { + Object.defineProperty(dest, prop, { + value: source[prop], + enumerable: false, + configurable: true, + writable: true, + }); + } + ); + }; - if (message !== undefined && typeof message !== "string") { - throw new TypeError("Message should be a string"); - } + },{"@sinonjs/commons":48}],27:[function(require,module,exports){ - if (arguments.length > 2) { - throw new TypeError( - `Expected 1 or 2 arguments, received ${arguments.length}` - ); - } + module.exports = function toString() { + let i, prop, thisValue; + if (this.getCall && this.callCount) { + i = this.callCount; - if (type in TYPE_MAP) { - TYPE_MAP[type](m, expectation, message); - } else { - m.test = function (actual) { - return deepEqual(actual, expectation); - }; - } + while (i--) { + thisValue = this.getCall(i).thisValue; - if (!m.message) { - m.message = `match(${valueToString(expectation)})`; + // eslint-disable-next-line guard-for-in + for (prop in thisValue) { + try { + if (thisValue[prop] === this) { + return prop; + } + } catch (e) { + // no-op - accessing props can throw an error, nothing to do here + } + } + } } - // ensure that nothing mutates the exported message value, ref https://github.com/sinonjs/sinon/issues/2502 - Object.defineProperty(m, "message", { - configurable: false, - writable: false, - value: m.message, - }); + return this.displayName || "sinon fake"; + }; - return m; + },{}],28:[function(require,module,exports){ + + /* istanbul ignore next : not testing that setTimeout works */ + function nextTick(callback) { + setTimeout(callback, 0); } - createMatcher.isMatcher = isMatcher; + module.exports = function getNextTick(process, setImmediate) { + if (typeof process === "object" && typeof process.nextTick === "function") { + return process.nextTick; + } - createMatcher.any = createMatcher(function () { - return true; - }, "any"); + if (typeof setImmediate === "function") { + return setImmediate; + } - createMatcher.defined = createMatcher(function (actual) { - return actual !== null && actual !== undefined; - }, "defined"); + return nextTick; + }; - createMatcher.truthy = createMatcher(function (actual) { - return Boolean(actual); - }, "truthy"); + },{}],29:[function(require,module,exports){ - createMatcher.falsy = createMatcher(function (actual) { - return !actual; - }, "falsy"); + /* eslint-disable jsdoc/valid-types */ + /* + * The following type def is strictly an illegal JSDoc, but the expression forms a + * legal Typescript union type and is understood by Visual Studio and the IntelliJ + * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these + * days for that reason (and the fact that JSDoc is essentially unmaintained) + */ - createMatcher.same = function (expectation) { - return createMatcher(function (actual) { - return expectation === actual; - }, `same(${valueToString(expectation)})`); - }; + /** + * @typedef {{isOwn: boolean} & PropertyDescriptor} SinonPropertyDescriptor + * a slightly enriched property descriptor + * @property {boolean} isOwn true if the descriptor is owned by this object, false if it comes from the prototype + */ + /* eslint-enable jsdoc/valid-types */ - createMatcher.in = function (arrayOfExpectations) { - if (typeOf(arrayOfExpectations) !== "array") { - throw new TypeError("array expected"); + /** + * Returns a slightly modified property descriptor that one can tell is from the object or the prototype + * + * @param {*} object + * @param {string} property + * @returns {SinonPropertyDescriptor} + */ + function getPropertyDescriptor(object, property) { + let proto = object; + let descriptor; + const isOwn = Boolean( + object && Object.getOwnPropertyDescriptor(object, property) + ); + + while ( + proto && + !(descriptor = Object.getOwnPropertyDescriptor(proto, property)) + ) { + proto = Object.getPrototypeOf(proto); } - return createMatcher(function (actual) { - return some(arrayOfExpectations, function (expectation) { - return expectation === actual; - }); - }, `in(${valueToString(arrayOfExpectations)})`); - }; + if (descriptor) { + descriptor.isOwn = isOwn; + } - createMatcher.typeOf = function (type) { - assertType(type, "string", "type"); - return createMatcher(function (actual) { - return typeOf(actual) === type; - }, `typeOf("${type}")`); - }; + return descriptor; + } - createMatcher.instanceOf = function (type) { - /* istanbul ignore if */ - if ( - typeof Symbol === "undefined" || - typeof Symbol.hasInstance === "undefined" - ) { - assertType(type, "function", "type"); - } else { - assertMethodExists( - type, - Symbol.hasInstance, - "type", - "[Symbol.hasInstance]" - ); - } - return createMatcher(function (actual) { - return actual instanceof type; - }, `instanceOf(${functionName(type) || objectToString(type)})`); - }; + module.exports = getPropertyDescriptor; + + },{}],30:[function(require,module,exports){ /** - * Creates a property matcher + * Verify if an object is a ECMAScript Module * - * @private - * @param {Function} propertyTest A function to test the property against a value - * @param {string} messagePrefix A prefix to use for messages generated by the matcher - * @returns {object} A matcher + * As the exports from a module is immutable we cannot alter the exports + * using spies or stubs. Let the consumer know this to avoid bug reports + * on weird error messages. + * + * @param {object} object The object to examine + * @returns {boolean} true when the object is a module */ - function createPropertyMatcher(propertyTest, messagePrefix) { - return function (property, value) { - assertType(property, "string", "property"); - var onlyProperty = arguments.length === 1; - var message = `${messagePrefix}("${property}"`; - if (!onlyProperty) { - message += `, ${valueToString(value)}`; - } - message += ")"; - return createMatcher(function (actual) { - if ( - actual === undefined || - actual === null || - !propertyTest(actual, property) - ) { - return false; - } - return onlyProperty || deepEqual(actual[property], value); - }, message); - }; + module.exports = function (object) { + return ( + object && + typeof Symbol !== "undefined" && + object[Symbol.toStringTag] === "Module" && + Object.isSealed(object) + ); + }; + + },{}],31:[function(require,module,exports){ + + /** + * @param {*} object + * @param {string} property + * @returns {boolean} whether a prop exists in the prototype chain + */ + function isNonExistentProperty(object, property) { + return Boolean( + object && typeof property !== "undefined" && !(property in object) + ); } - createMatcher.has = createPropertyMatcher(function (actual, property) { - if (typeof actual === "object") { - return property in actual; - } - return actual[property] !== undefined; - }, "has"); + module.exports = isNonExistentProperty; - createMatcher.hasOwn = createPropertyMatcher(function (actual, property) { - return hasOwnProperty(actual, property); - }, "hasOwn"); + },{}],32:[function(require,module,exports){ - createMatcher.hasNested = function (property, value) { - assertType(property, "string", "property"); - var onlyProperty = arguments.length === 1; - var message = `hasNested("${property}"`; - if (!onlyProperty) { - message += `, ${valueToString(value)}`; - } - message += ")"; - return createMatcher(function (actual) { - if ( - actual === undefined || - actual === null || - get(actual, property) === undefined - ) { - return false; - } - return onlyProperty || deepEqual(get(actual, property), value); - }, message); - }; + const getPropertyDescriptor = require("./get-property-descriptor"); - var jsonParseResultTypes = { - null: true, - boolean: true, - number: true, - string: true, - object: true, - array: true, - }; - createMatcher.json = function (value) { - if (!jsonParseResultTypes[typeOf(value)]) { - throw new TypeError("Value cannot be the result of JSON.parse"); - } - var message = `json(${JSON.stringify(value, null, " ")})`; - return createMatcher(function (actual) { - var parsed; - try { - parsed = JSON.parse(actual); - } catch (e) { - return false; - } - return deepEqual(parsed, value); - }, message); - }; + function isPropertyConfigurable(obj, propName) { + const propertyDescriptor = getPropertyDescriptor(obj, propName); - createMatcher.every = function (predicate) { - assertMatcher(predicate); + return propertyDescriptor ? propertyDescriptor.configurable : true; + } - return createMatcher(function (actual) { - if (typeOf(actual) === "object") { - return every(Object.keys(actual), function (key) { - return predicate.test(actual[key]); - }); - } + module.exports = isPropertyConfigurable; - return ( - isIterable(actual) && - every(actual, function (element) { - return predicate.test(element); - }) - ); - }, `every(${predicate.message})`); - }; + },{"./get-property-descriptor":29}],33:[function(require,module,exports){ - createMatcher.some = function (predicate) { - assertMatcher(predicate); + function isRestorable(obj) { + return ( + typeof obj === "function" && + typeof obj.restore === "function" && + obj.restore.sinon + ); + } - return createMatcher(function (actual) { - if (typeOf(actual) === "object") { - return !every(Object.keys(actual), function (key) { - return !predicate.test(actual[key]); - }); - } + module.exports = isRestorable; - return ( - isIterable(actual) && - !every(actual, function (element) { - return !predicate.test(element); - }) - ); - }, `some(${predicate.message})`); - }; + },{}],34:[function(require,module,exports){ - createMatcher.array = createMatcher.typeOf("array"); + const globalObject = require("@sinonjs/commons").global; + const getNextTick = require("./get-next-tick"); - createMatcher.array.deepEquals = function (expectation) { - return createMatcher(function (actual) { - // Comparing lengths is the fastest way to spot a difference before iterating through every item - var sameLength = actual.length === expectation.length; - return ( - typeOf(actual) === "array" && - sameLength && - every(actual, function (element, index) { - var expected = expectation[index]; - return typeOf(expected) === "array" && - typeOf(element) === "array" - ? createMatcher.array.deepEquals(expected).test(element) - : deepEqual(expected, element); - }) - ); - }, `deepEquals([${iterableToString(expectation)}])`); - }; + module.exports = getNextTick(globalObject.process, globalObject.setImmediate); - createMatcher.array.startsWith = function (expectation) { - return createMatcher(function (actual) { - return ( - typeOf(actual) === "array" && - every(expectation, function (expectedElement, index) { - return actual[index] === expectedElement; - }) - ); - }, `startsWith([${iterableToString(expectation)}])`); - }; + },{"./get-next-tick":28,"@sinonjs/commons":48}],35:[function(require,module,exports){ - createMatcher.array.endsWith = function (expectation) { - return createMatcher(function (actual) { - // This indicates the index in which we should start matching - var offset = actual.length - expectation.length; + const sinonTypeSymbolProperty = Symbol("SinonType"); - return ( - typeOf(actual) === "array" && - every(expectation, function (expectedElement, index) { - return actual[offset + index] === expectedElement; - }) - ); - }, `endsWith([${iterableToString(expectation)}])`); + module.exports = { + /** + * Set the type of a Sinon object to make it possible to identify it later at runtime + * + * @param {object|Function} object object/function to set the type on + * @param {string} type the named type of the object/function + */ + set(object, type) { + Object.defineProperty(object, sinonTypeSymbolProperty, { + value: type, + configurable: false, + enumerable: false, + }); + }, + get(object) { + return object && object[sinonTypeSymbolProperty]; + }, }; - createMatcher.array.contains = function (expectation) { - return createMatcher(function (actual) { - return ( - typeOf(actual) === "array" && - every(expectation, function (expectedElement) { - return arrayIndexOf(actual, expectedElement) !== -1; - }) - ); - }, `contains([${iterableToString(expectation)}])`); + },{}],36:[function(require,module,exports){ + + const array = [null, "once", "twice", "thrice"]; + + module.exports = function timesInWords(count) { + return array[count] || `${count || 0} times`; }; - createMatcher.map = createMatcher.typeOf("map"); + },{}],37:[function(require,module,exports){ - createMatcher.map.deepEquals = function mapDeepEquals(expectation) { - return createMatcher(function (actual) { - // Comparing lengths is the fastest way to spot a difference before iterating through every item - var sameLength = actual.size === expectation.size; - return ( - typeOf(actual) === "map" && - sameLength && - every(actual, function (element, key) { - return expectation.has(key) && expectation.get(key) === element; - }) - ); - }, `deepEquals(Map[${iterableToString(expectation)}])`); - }; + const forEach = Array.prototype.forEach; - createMatcher.map.contains = function mapContains(expectation) { - return createMatcher(function (actual) { - return ( - typeOf(actual) === "map" && - every(expectation, function (element, key) { - return actual.has(key) && actual.get(key) === element; - }) - ); - }, `contains(Map[${iterableToString(expectation)}])`); - }; + function usePromiseLibrary(library, fakes) { + if (typeof library === "undefined") { + return; + } - createMatcher.set = createMatcher.typeOf("set"); + if (Array.isArray(fakes)) { + forEach.call(fakes, usePromiseLibrary.bind(null, library)); - createMatcher.set.deepEquals = function setDeepEquals(expectation) { - return createMatcher(function (actual) { - // Comparing lengths is the fastest way to spot a difference before iterating through every item - var sameLength = actual.size === expectation.size; - return ( - typeOf(actual) === "set" && - sameLength && - every(actual, function (element) { - return expectation.has(element); - }) - ); - }, `deepEquals(Set[${iterableToString(expectation)}])`); - }; + return; + } - createMatcher.set.contains = function setContains(expectation) { - return createMatcher(function (actual) { - return ( - typeOf(actual) === "set" && - every(expectation, function (element) { - return actual.has(element); - }) - ); - }, `contains(Set[${iterableToString(expectation)}])`); - }; + if (typeof fakes.usingPromise === "function") { + fakes.usingPromise(library); + } + } - createMatcher.bool = createMatcher.typeOf("boolean"); - createMatcher.number = createMatcher.typeOf("number"); - createMatcher.string = createMatcher.typeOf("string"); - createMatcher.object = createMatcher.typeOf("object"); - createMatcher.func = createMatcher.typeOf("function"); - createMatcher.regexp = createMatcher.typeOf("regexp"); - createMatcher.date = createMatcher.typeOf("date"); - createMatcher.symbol = createMatcher.typeOf("symbol"); + module.exports = usePromiseLibrary; - module.exports = createMatcher; + },{}],38:[function(require,module,exports){ - },{"./create-matcher/assert-matcher":64,"./create-matcher/assert-method-exists":65,"./create-matcher/assert-type":66,"./create-matcher/is-iterable":67,"./create-matcher/is-matcher":68,"./create-matcher/matcher-prototype":70,"./create-matcher/type-map":71,"./deep-equal":72,"./iterable-to-string":86,"@sinonjs/commons":95,"lodash.get":116}],64:[function(require,module,exports){ + const functionName = require("@sinonjs/commons").functionName; - var isMatcher = require("./is-matcher"); + const getPropertyDescriptor = require("./get-property-descriptor"); + const walk = require("./walk"); /** - * Throws a TypeError when `value` is not a matcher + * A utility that allows traversing an object, applying mutating functions on the properties * - * @private - * @param {*} value The value to examine + * @param {Function} mutator called on each property + * @param {object} object the object we are walking over + * @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property + * @returns {void} nothing */ - function assertMatcher(value) { - if (!isMatcher(value)) { - throw new TypeError("Matcher expected"); - } - } - - module.exports = assertMatcher; - - },{"./is-matcher":68}],65:[function(require,module,exports){ + function walkObject(mutator, object, filter) { + let called = false; + const name = functionName(mutator); - /** - * Throws a TypeError when expected method doesn't exist - * - * @private - * @param {*} value A value to examine - * @param {string} method The name of the method to look for - * @param {name} name A name to use for the error message - * @param {string} methodPath The name of the method to use for error messages - * @throws {TypeError} When the method doesn't exist - */ - function assertMethodExists(value, method, name, methodPath) { - if (value[method] === null || value[method] === undefined) { - throw new TypeError(`Expected ${name} to have method ${methodPath}`); + if (!object) { + throw new Error( + `Trying to ${name} object but received ${String(object)}` + ); } - } - - module.exports = assertMethodExists; - - },{}],66:[function(require,module,exports){ - var typeOf = require("@sinonjs/commons").typeOf; + walk(object, function (prop, propOwner) { + // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object + // is not Object.prototype + if ( + propOwner !== Object.prototype && + prop !== "constructor" && + typeof getPropertyDescriptor(propOwner, prop).value === "function" + ) { + if (filter) { + if (filter(object, prop)) { + called = true; + mutator(object, prop); + } + } else { + called = true; + mutator(object, prop); + } + } + }); - /** - * Ensures that value is of type - * - * @private - * @param {*} value A value to examine - * @param {string} type A basic JavaScript type to compare to, e.g. "object", "string" - * @param {string} name A string to use for the error message - * @throws {TypeError} If value is not of the expected type - * @returns {undefined} - */ - function assertType(value, type, name) { - var actual = typeOf(value); - if (actual !== type) { - throw new TypeError( - `Expected type of ${name} to be ${type}, but was ${actual}` + if (!called) { + throw new Error( + `Found no methods on object to which we could apply mutations` ); } + + return object; } - module.exports = assertType; + module.exports = walkObject; - },{"@sinonjs/commons":95}],67:[function(require,module,exports){ + },{"./get-property-descriptor":29,"./walk":39,"@sinonjs/commons":48}],39:[function(require,module,exports){ - var typeOf = require("@sinonjs/commons").typeOf; + const forEach = require("@sinonjs/commons").prototypes.array.forEach; - /** - * Returns `true` for iterables - * - * @private - * @param {*} value A value to examine - * @returns {boolean} Returns `true` when `value` looks like an iterable - */ - function isIterable(value) { - return Boolean(value) && typeOf(value.forEach) === "function"; - } + function walkInternal(obj, iterator, context, originalObj, seen) { + let prop; + const proto = Object.getPrototypeOf(obj); - module.exports = isIterable; + if (typeof Object.getOwnPropertyNames !== "function") { + // We explicitly want to enumerate through all of the prototype's properties + // in this case, therefore we deliberately leave out an own property check. + /* eslint-disable-next-line guard-for-in */ + for (prop in obj) { + iterator.call(context, obj[prop], prop, obj); + } - },{"@sinonjs/commons":95}],68:[function(require,module,exports){ + return; + } - var isPrototypeOf = require("@sinonjs/commons").prototypes.object.isPrototypeOf; + forEach(Object.getOwnPropertyNames(obj), function (k) { + if (seen[k] !== true) { + seen[k] = true; + const target = + typeof Object.getOwnPropertyDescriptor(obj, k).get === + "function" + ? originalObj + : obj; + iterator.call(context, k, target); + } + }); - var matcherPrototype = require("./matcher-prototype"); + if (proto) { + walkInternal(proto, iterator, context, originalObj, seen); + } + } - /** - * Returns `true` when `object` is a matcher + /* Walks the prototype chain of an object and iterates over every own property + * name encountered. The iterator is called in the same fashion that Array.prototype.forEach + * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional + * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will + * default to using a simple for..in loop. * - * @private - * @param {*} object A value to examine - * @returns {boolean} Returns `true` when `object` is a matcher + * obj - The object to walk the prototype chain for. + * iterator - The function to be called on each pass of the walk. + * context - (Optional) When given, the iterator will be called with this object as the receiver. */ - function isMatcher(object) { - return isPrototypeOf(matcherPrototype, object); - } - - module.exports = isMatcher; + module.exports = function walk(obj, iterator, context) { + return walkInternal(obj, iterator, context, obj, {}); + }; - },{"./matcher-prototype":70,"@sinonjs/commons":95}],69:[function(require,module,exports){ + },{"@sinonjs/commons":48}],40:[function(require,module,exports){ - var every = require("@sinonjs/commons").prototypes.array.every; - var concat = require("@sinonjs/commons").prototypes.array.concat; - var typeOf = require("@sinonjs/commons").typeOf; + // eslint-disable-next-line no-empty-function + const noop = () => {}; + const getPropertyDescriptor = require("./get-property-descriptor"); + const extend = require("./extend"); + const sinonType = require("./sinon-type"); + const hasOwnProperty = + require("@sinonjs/commons").prototypes.object.hasOwnProperty; + const valueToString = require("@sinonjs/commons").valueToString; + const push = require("@sinonjs/commons").prototypes.array.push; - var deepEqualFactory = require("../deep-equal").use; + function isFunction(obj) { + return ( + typeof obj === "function" || + Boolean(obj && obj.constructor && obj.call && obj.apply) + ); + } - var isMatcher = require("./is-matcher"); + function mirrorProperties(target, source) { + for (const prop in source) { + if (!hasOwnProperty(target, prop)) { + target[prop] = source[prop]; + } + } + } - var keys = Object.keys; - var getOwnPropertySymbols = Object.getOwnPropertySymbols; + function getAccessor(object, property, method) { + const accessors = ["get", "set"]; + const descriptor = getPropertyDescriptor(object, property); - /** - * Matches `actual` with `expectation` - * - * @private - * @param {*} actual A value to examine - * @param {object} expectation An object with properties to match on - * @param {object} matcher A matcher to use for comparison - * @returns {boolean} Returns true when `actual` matches all properties in `expectation` - */ - function matchObject(actual, expectation, matcher) { - var deepEqual = deepEqualFactory(matcher); - if (actual === null || actual === undefined) { - return false; + for (let i = 0; i < accessors.length; i++) { + if ( + descriptor[accessors[i]] && + descriptor[accessors[i]].name === method.name + ) { + return accessors[i]; + } } + return null; + } - var expectedKeys = keys(expectation); - /* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */ - if (typeOf(getOwnPropertySymbols) === "function") { - expectedKeys = concat(expectedKeys, getOwnPropertySymbols(expectation)); + // Cheap way to detect if we have ES5 support. + const hasES5Support = "keys" in Object; + + module.exports = function wrapMethod(object, property, method) { + if (!object) { + throw new TypeError("Should wrap property of object"); } - return every(expectedKeys, function (key) { - var exp = expectation[key]; - var act = actual[key]; + if (typeof method !== "function" && typeof method !== "object") { + throw new TypeError( + "Method wrapper should be a function or a property descriptor" + ); + } - if (isMatcher(exp)) { - if (!exp.test(act)) { - return false; - } - } else if (typeOf(exp) === "object") { - if (!matchObject(act, exp, matcher)) { - return false; + function checkWrappedMethod(wrappedMethod) { + let error; + + if (!isFunction(wrappedMethod)) { + error = new TypeError( + `Attempted to wrap ${typeof wrappedMethod} property ${valueToString( + property + )} as function` + ); + } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) { + error = new TypeError( + `Attempted to wrap ${valueToString( + property + )} which is already wrapped` + ); + } else if (wrappedMethod.calledBefore) { + const verb = wrappedMethod.returns ? "stubbed" : "spied on"; + error = new TypeError( + `Attempted to wrap ${valueToString( + property + )} which is already ${verb}` + ); + } + + if (error) { + if (wrappedMethod && wrappedMethod.stackTraceError) { + error.stack += `\n--------------\n${wrappedMethod.stackTraceError.stack}`; } - } else if (!deepEqual(act, exp)) { - return false; + throw error; } + } - return true; - }); - } + let error, wrappedMethod, i, wrappedMethodDesc, target, accessor; - module.exports = matchObject; + const wrappedMethods = []; - },{"../deep-equal":72,"./is-matcher":68,"@sinonjs/commons":95}],70:[function(require,module,exports){ + function simplePropertyAssignment() { + wrappedMethod = object[property]; + checkWrappedMethod(wrappedMethod); + object[property] = method; + method.displayName = property; + } - var matcherPrototype = { - toString: function () { - return this.message; - }, - }; + // Firefox has a problem when using hasOwn.call on objects from other frames. + const owned = object.hasOwnProperty + ? object.hasOwnProperty(property) // eslint-disable-line @sinonjs/no-prototype-methods/no-prototype-methods + : hasOwnProperty(object, property); - matcherPrototype.or = function (valueOrMatcher) { - var createMatcher = require("../create-matcher"); - var isMatcher = createMatcher.isMatcher; + if (hasES5Support) { + const methodDesc = + typeof method === "function" ? { value: method } : method; + wrappedMethodDesc = getPropertyDescriptor(object, property); - if (!arguments.length) { - throw new TypeError("Matcher expected"); - } + if (!wrappedMethodDesc) { + error = new TypeError( + `Attempted to wrap ${typeof wrappedMethod} property ${property} as function` + ); + } else if ( + wrappedMethodDesc.restore && + wrappedMethodDesc.restore.sinon + ) { + error = new TypeError( + `Attempted to wrap ${property} which is already wrapped` + ); + } + if (error) { + if (wrappedMethodDesc && wrappedMethodDesc.stackTraceError) { + error.stack += `\n--------------\n${wrappedMethodDesc.stackTraceError.stack}`; + } + throw error; + } - var m2 = isMatcher(valueOrMatcher) - ? valueOrMatcher - : createMatcher(valueOrMatcher); - var m1 = this; - var or = Object.create(matcherPrototype); - or.test = function (actual) { - return m1.test(actual) || m2.test(actual); - }; - or.message = `${m1.message}.or(${m2.message})`; - return or; - }; + const types = Object.keys(methodDesc); + for (i = 0; i < types.length; i++) { + wrappedMethod = wrappedMethodDesc[types[i]]; + checkWrappedMethod(wrappedMethod); + push(wrappedMethods, wrappedMethod); + } - matcherPrototype.and = function (valueOrMatcher) { - var createMatcher = require("../create-matcher"); - var isMatcher = createMatcher.isMatcher; + mirrorProperties(methodDesc, wrappedMethodDesc); + for (i = 0; i < types.length; i++) { + mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]); + } - if (!arguments.length) { - throw new TypeError("Matcher expected"); - } + // you are not allowed to flip the configurable prop on an + // existing descriptor to anything but false (#2514) + if (!owned) { + methodDesc.configurable = true; + } - var m2 = isMatcher(valueOrMatcher) - ? valueOrMatcher - : createMatcher(valueOrMatcher); - var m1 = this; - var and = Object.create(matcherPrototype); - and.test = function (actual) { - return m1.test(actual) && m2.test(actual); - }; - and.message = `${m1.message}.and(${m2.message})`; - return and; - }; + Object.defineProperty(object, property, methodDesc); - module.exports = matcherPrototype; + // catch failing assignment + // this is the converse of the check in `.restore` below + if (typeof method === "function" && object[property] !== method) { + // correct any wrongdoings caused by the defineProperty call above, + // such as adding new items (if object was a Storage object) + delete object[property]; + simplePropertyAssignment(); + } + } else { + simplePropertyAssignment(); + } - },{"../create-matcher":63}],71:[function(require,module,exports){ + extendObjectWithWrappedMethods(); - var functionName = require("@sinonjs/commons").functionName; - var join = require("@sinonjs/commons").prototypes.array.join; - var map = require("@sinonjs/commons").prototypes.array.map; - var stringIndexOf = require("@sinonjs/commons").prototypes.string.indexOf; - var valueToString = require("@sinonjs/commons").valueToString; + function extendObjectWithWrappedMethods() { + for (i = 0; i < wrappedMethods.length; i++) { + accessor = getAccessor(object, property, wrappedMethods[i]); + target = accessor ? method[accessor] : method; + extend.nonEnum(target, { + displayName: property, + wrappedMethod: wrappedMethods[i], - var matchObject = require("./match-object"); + // Set up an Error object for a stack trace which can be used later to find what line of + // code the original method was created on. + stackTraceError: new Error("Stack Trace for original"), - var createTypeMap = function (match) { - return { - function: function (m, expectation, message) { - m.test = expectation; - m.message = message || `match(${functionName(expectation)})`; - }, - number: function (m, expectation) { - m.test = function (actual) { - // we need type coercion here - return expectation == actual; // eslint-disable-line eqeqeq - }; - }, - object: function (m, expectation) { - var array = []; + restore: restore, + }); - if (typeof expectation.test === "function") { - m.test = function (actual) { - return expectation.test(actual) === true; - }; - m.message = `match(${functionName(expectation.test)})`; - return m; + target.restore.sinon = true; + if (!hasES5Support) { + mirrorProperties(target, wrappedMethod); } + } + } - array = map(Object.keys(expectation), function (key) { - return `${key}: ${valueToString(expectation[key])}`; - }); - - m.test = function (actual) { - return matchObject(actual, expectation, match); - }; - m.message = `match(${join(array, ", ")})`; + function restore() { + accessor = getAccessor(object, property, this.wrappedMethod); + let descriptor; + // For prototype properties try to reset by delete first. + // If this fails (ex: localStorage on mobile safari) then force a reset + // via direct assignment. + if (accessor) { + if (!owned) { + try { + // In some cases `delete` may throw an error + delete object[property][accessor]; + } catch (e) {} // eslint-disable-line no-empty + // For native code functions `delete` fails without throwing an error + // on Chrome < 43, PhantomJS, etc. + } else if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + descriptor[accessor] = wrappedMethodDesc[accessor]; + Object.defineProperty(object, property, descriptor); + } - return m; - }, - regexp: function (m, expectation) { - m.test = function (actual) { - return typeof actual === "string" && expectation.test(actual); - }; - }, - string: function (m, expectation) { - m.test = function (actual) { - return ( - typeof actual === "string" && - stringIndexOf(actual, expectation) !== -1 - ); - }; - m.message = `match("${expectation}")`; - }, - }; - }; - - module.exports = createTypeMap; - - },{"./match-object":69,"@sinonjs/commons":95}],72:[function(require,module,exports){ + if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + if (descriptor && descriptor.value === target) { + object[property][accessor] = this.wrappedMethod; + } + } else { + // Use strict equality comparison to check failures then force a reset + // via direct assignment. + if (object[property][accessor] === target) { + object[property][accessor] = this.wrappedMethod; + } + } + } else { + if (!owned) { + try { + delete object[property]; + } catch (e) {} // eslint-disable-line no-empty + } else if (hasES5Support) { + Object.defineProperty(object, property, wrappedMethodDesc); + } - var valueToString = require("@sinonjs/commons").valueToString; - var className = require("@sinonjs/commons").className; - var typeOf = require("@sinonjs/commons").typeOf; - var arrayProto = require("@sinonjs/commons").prototypes.array; - var objectProto = require("@sinonjs/commons").prototypes.object; - var mapForEach = require("@sinonjs/commons").prototypes.map.forEach; + if (hasES5Support) { + descriptor = getPropertyDescriptor(object, property); + if (descriptor && descriptor.value === target) { + object[property] = this.wrappedMethod; + } + } else { + if (object[property] === target) { + object[property] = this.wrappedMethod; + } + } + } + if (sinonType.get(object) === "stub-instance") { + // this is simply to avoid errors after restoring if something should + // traverse the object in a cleanup phase, ref #2477 + object[property] = noop; + } + } - var getClass = require("./get-class"); - var identical = require("./identical"); - var isArguments = require("./is-arguments"); - var isArrayType = require("./is-array-type"); - var isDate = require("./is-date"); - var isElement = require("./is-element"); - var isIterable = require("./is-iterable"); - var isMap = require("./is-map"); - var isNaN = require("./is-nan"); - var isObject = require("./is-object"); - var isSet = require("./is-set"); - var isSubset = require("./is-subset"); + return method; + }; - var concat = arrayProto.concat; - var every = arrayProto.every; - var push = arrayProto.push; + },{"./extend":26,"./get-property-descriptor":29,"./sinon-type":35,"@sinonjs/commons":48}],41:[function(require,module,exports){ - var getTime = Date.prototype.getTime; - var hasOwnProperty = objectProto.hasOwnProperty; - var indexOf = arrayProto.indexOf; - var keys = Object.keys; - var getOwnPropertySymbols = Object.getOwnPropertySymbols; + const extend = require("./core/extend"); + const FakeTimers = require("@sinonjs/fake-timers"); + const globalObject = require("@sinonjs/commons").global; /** - * Deep equal comparison. Two values are "deep equal" when: - * - * - They are equal, according to samsam.identical - * - They are both date objects representing the same time - * - They are both arrays containing elements that are all deepEqual - * - They are objects with the same set of properties, and each property - * in ``actual`` is deepEqual to the corresponding property in ``expectation`` * - * Supports cyclic objects. + * @param config + * @param globalCtx + */ + function createClock(config, globalCtx) { + let FakeTimersCtx = FakeTimers; + if (globalCtx !== null && typeof globalCtx === "object") { + FakeTimersCtx = FakeTimers.withGlobal(globalCtx); + } + const clock = FakeTimersCtx.install(config); + clock.restore = clock.uninstall; + return clock; + } + + /** * - * @alias module:samsam.deepEqual - * @param {*} actual The object to examine - * @param {*} expectation The object actual is expected to be equal to - * @param {object} match A value to match on - * @returns {boolean} Returns true when actual and expectation are considered equal + * @param obj + * @param globalPropName */ - function deepEqualCyclic(actual, expectation, match) { - // used for cyclic comparison - // contain already visited objects - var actualObjects = []; - var expectationObjects = []; - // contain pathes (position in the object structure) - // of the already visited objects - // indexes same as in objects arrays - var actualPaths = []; - var expectationPaths = []; - // contains combinations of already compared objects - // in the manner: { "$1['ref']$2['ref']": true } - var compared = {}; + function addIfDefined(obj, globalPropName) { + const globalProp = globalObject[globalPropName]; + if (typeof globalProp !== "undefined") { + obj[globalPropName] = globalProp; + } + } - // does the recursion for the deep equal check - // eslint-disable-next-line complexity - return (function deepEqual( - actualObj, - expectationObj, - actualPath, - expectationPath - ) { - // If both are matchers they must be the same instance in order to be - // considered equal If we didn't do that we would end up running one - // matcher against the other - if (match && match.isMatcher(expectationObj)) { - if (match.isMatcher(actualObj)) { - return actualObj === expectationObj; - } - return expectationObj.test(actualObj); - } + /** + * @param {number|Date|object} dateOrConfig The unix epoch value to install with (default 0) + * @returns {object} Returns a lolex clock instance + */ + exports.useFakeTimers = function (dateOrConfig) { + const hasArguments = typeof dateOrConfig !== "undefined"; + const argumentIsDateLike = + (typeof dateOrConfig === "number" || dateOrConfig instanceof Date) && + arguments.length === 1; + const argumentIsObject = + dateOrConfig !== null && + typeof dateOrConfig === "object" && + arguments.length === 1; - var actualType = typeof actualObj; - var expectationType = typeof expectationObj; + if (!hasArguments) { + return createClock({ + now: 0, + }); + } - if ( - actualObj === expectationObj || - isNaN(actualObj) || - isNaN(expectationObj) || - actualObj === null || - expectationObj === null || - actualObj === undefined || - expectationObj === undefined || - actualType !== "object" || - expectationType !== "object" - ) { - return identical(actualObj, expectationObj); - } + if (argumentIsDateLike) { + return createClock({ + now: dateOrConfig, + }); + } - // Elements are only equal if identical(expected, actual) - if (isElement(actualObj) || isElement(expectationObj)) { - return false; - } + if (argumentIsObject) { + const config = extend.nonEnum({}, dateOrConfig); + const globalCtx = config.global; + delete config.global; + return createClock(config, globalCtx); + } - var isActualDate = isDate(actualObj); - var isExpectationDate = isDate(expectationObj); - if (isActualDate || isExpectationDate) { - if ( - !isActualDate || - !isExpectationDate || - getTime.call(actualObj) !== getTime.call(expectationObj) - ) { - return false; - } - } + throw new TypeError( + "useFakeTimers expected epoch or config object. See https://github.com/sinonjs/sinon" + ); + }; - if (actualObj instanceof RegExp && expectationObj instanceof RegExp) { - if (valueToString(actualObj) !== valueToString(expectationObj)) { - return false; - } - } + exports.clock = { + create: function (now) { + return FakeTimers.createClock(now); + }, + }; - if (actualObj instanceof Promise && expectationObj instanceof Promise) { - return actualObj === expectationObj; - } + const timers = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval, + Date: Date, + }; + addIfDefined(timers, "setImmediate"); + addIfDefined(timers, "clearImmediate"); - if (actualObj instanceof Error && expectationObj instanceof Error) { - return actualObj === expectationObj; - } + exports.timers = timers; - var actualClass = getClass(actualObj); - var expectationClass = getClass(expectationObj); - var actualKeys = keys(actualObj); - var expectationKeys = keys(expectationObj); - var actualName = className(actualObj); - var expectationName = className(expectationObj); - var expectationSymbols = - typeOf(getOwnPropertySymbols) === "function" - ? getOwnPropertySymbols(expectationObj) - : /* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */ - []; - var expectationKeysAndSymbols = concat( - expectationKeys, - expectationSymbols - ); + },{"./core/extend":26,"@sinonjs/commons":48,"@sinonjs/fake-timers":61}],42:[function(require,module,exports){ - if (isArguments(actualObj) || isArguments(expectationObj)) { - if (actualObj.length !== expectationObj.length) { - return false; - } - } else { - if ( - actualType !== expectationType || - actualClass !== expectationClass || - actualKeys.length !== expectationKeys.length || - (actualName && - expectationName && - actualName !== expectationName) - ) { - return false; - } - } - - if (isSet(actualObj) || isSet(expectationObj)) { - if ( - !isSet(actualObj) || - !isSet(expectationObj) || - actualObj.size !== expectationObj.size - ) { - return false; - } - - return isSubset(actualObj, expectationObj, deepEqual); - } - - if (isMap(actualObj) || isMap(expectationObj)) { - if ( - !isMap(actualObj) || - !isMap(expectationObj) || - actualObj.size !== expectationObj.size - ) { - return false; - } - - var mapsDeeplyEqual = true; - mapForEach(actualObj, function (value, key) { - mapsDeeplyEqual = - mapsDeeplyEqual && - deepEqualCyclic(value, expectationObj.get(key)); - }); - - return mapsDeeplyEqual; - } - - // jQuery objects have iteration protocols - // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols - // But, they don't work well with the implementation concerning iterables below, - // so we will detect them and use jQuery's own equality function - /* istanbul ignore next -- this can only be tested in the `test-headless` script */ - if ( - actualObj.constructor && - actualObj.constructor.name === "jQuery" && - typeof actualObj.is === "function" - ) { - return actualObj.is(expectationObj); - } - - var isActualNonArrayIterable = - isIterable(actualObj) && - !isArrayType(actualObj) && - !isArguments(actualObj); - var isExpectationNonArrayIterable = - isIterable(expectationObj) && - !isArrayType(expectationObj) && - !isArguments(expectationObj); - if (isActualNonArrayIterable || isExpectationNonArrayIterable) { - var actualArray = Array.from(actualObj); - var expectationArray = Array.from(expectationObj); - if (actualArray.length !== expectationArray.length) { - return false; - } - - var arrayDeeplyEquals = true; - every(actualArray, function (key) { - arrayDeeplyEquals = - arrayDeeplyEquals && - deepEqualCyclic(actualArray[key], expectationArray[key]); - }); - - return arrayDeeplyEquals; - } - - return every(expectationKeysAndSymbols, function (key) { - if (!hasOwnProperty(actualObj, key)) { - return false; - } - - var actualValue = actualObj[key]; - var expectationValue = expectationObj[key]; - var actualObject = isObject(actualValue); - var expectationObject = isObject(expectationValue); - // determines, if the objects were already visited - // (it's faster to check for isObject first, than to - // get -1 from getIndex for non objects) - var actualIndex = actualObject - ? indexOf(actualObjects, actualValue) - : -1; - var expectationIndex = expectationObject - ? indexOf(expectationObjects, expectationValue) - : -1; - // determines the new paths of the objects - // - for non cyclic objects the current path will be extended - // by current property name - // - for cyclic objects the stored path is taken - var newActualPath = - actualIndex !== -1 - ? actualPaths[actualIndex] - : `${actualPath}[${JSON.stringify(key)}]`; - var newExpectationPath = - expectationIndex !== -1 - ? expectationPaths[expectationIndex] - : `${expectationPath}[${JSON.stringify(key)}]`; - var combinedPath = newActualPath + newExpectationPath; - - // stop recursion if current objects are already compared - if (compared[combinedPath]) { - return true; - } - - // remember the current objects and their paths - if (actualIndex === -1 && actualObject) { - push(actualObjects, actualValue); - push(actualPaths, newActualPath); - } - if (expectationIndex === -1 && expectationObject) { - push(expectationObjects, expectationValue); - push(expectationPaths, newExpectationPath); - } - - // remember that the current objects are already compared - if (actualObject && expectationObject) { - compared[combinedPath] = true; - } + var every = require("./prototypes/array").every; - // End of cyclic logic + /** + * @private + */ + function hasCallsLeft(callMap, spy) { + if (callMap[spy.id] === undefined) { + callMap[spy.id] = 0; + } - // neither actualValue nor expectationValue is a cycle - // continue with next level - return deepEqual( - actualValue, - expectationValue, - newActualPath, - newExpectationPath - ); - }); - })(actual, expectation, "$1", "$2"); + return callMap[spy.id] < spy.callCount; } - deepEqualCyclic.use = function (match) { - return function deepEqual(a, b) { - return deepEqualCyclic(a, b, match); - }; - }; - - module.exports = deepEqualCyclic; - - },{"./get-class":73,"./identical":74,"./is-arguments":75,"./is-array-type":76,"./is-date":77,"./is-element":78,"./is-iterable":79,"./is-map":80,"./is-nan":81,"./is-object":83,"./is-set":84,"./is-subset":85,"@sinonjs/commons":95}],73:[function(require,module,exports){ - - var toString = require("@sinonjs/commons").prototypes.object.toString; - /** - * Returns the internal `Class` by calling `Object.prototype.toString` - * with the provided value as `this`. Return value is a `String`, naming the - * internal class, e.g. "Array" - * * @private - * @param {*} value - Any value - * @returns {string} - A string representation of the `Class` of `value` */ - function getClass(value) { - return toString(value).split(/[ \]]/)[1]; - } + function checkAdjacentCalls(callMap, spy, index, spies) { + var calledBeforeNext = true; - module.exports = getClass; + if (index !== spies.length - 1) { + calledBeforeNext = spy.calledBefore(spies[index + 1]); + } - },{"@sinonjs/commons":95}],74:[function(require,module,exports){ + if (hasCallsLeft(callMap, spy) && calledBeforeNext) { + callMap[spy.id] += 1; + return true; + } - var isNaN = require("./is-nan"); - var isNegZero = require("./is-neg-zero"); + return false; + } /** - * Strict equality check according to EcmaScript Harmony's `egal`. - * - * **From the Harmony wiki:** - * > An `egal` function simply makes available the internal `SameValue` function - * > from section 9.12 of the ES5 spec. If two values are egal, then they are not - * > observably distinguishable. + * A Sinon proxy object (fake, spy, stub) * - * `identical` returns `true` when `===` is `true`, except for `-0` and - * `+0`, where it returns `false`. Additionally, it returns `true` when - * `NaN` is compared to itself. + * @typedef {object} SinonProxy + * @property {Function} calledBefore - A method that determines if this proxy was called before another one + * @property {string} id - Some id + * @property {number} callCount - Number of times this proxy has been called + */ + + /** + * Returns true when the spies have been called in the order they were supplied in * - * @alias module:samsam.identical - * @param {*} obj1 The first value to compare - * @param {*} obj2 The second value to compare - * @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise + * @param {SinonProxy[] | SinonProxy} spies An array of proxies, or several proxies as arguments + * @returns {boolean} true when spies are called in order, false otherwise */ - function identical(obj1, obj2) { - if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { - return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); - } + function calledInOrder(spies) { + var callMap = {}; + // eslint-disable-next-line no-underscore-dangle + var _spies = arguments.length > 1 ? arguments : spies; - return false; + return every(_spies, checkAdjacentCalls.bind(null, callMap)); } - module.exports = identical; + module.exports = calledInOrder; - },{"./is-nan":81,"./is-neg-zero":82}],75:[function(require,module,exports){ + },{"./prototypes/array":50}],43:[function(require,module,exports){ - var getClass = require("./get-class"); + var functionName = require("./function-name"); /** - * Returns `true` when `object` is an `arguments` object, `false` otherwise + * Returns a display name for a value from a constructor * - * @alias module:samsam.isArguments - * @param {*} object - The object to examine - * @returns {boolean} `true` when `object` is an `arguments` object + * @param {object} value A value to examine + * @returns {(string|null)} A string or null */ - function isArguments(object) { - return getClass(object) === "Arguments"; + function className(value) { + return ( + (value.constructor && value.constructor.name) || + // The next branch is for IE11 support only: + // Because the name property is not set on the prototype + // of the Function object, we finally try to grab the + // name from its definition. This will never be reached + // in node, so we are not able to test this properly. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + (typeof value.constructor === "function" && + /* istanbul ignore next */ + functionName(value.constructor)) || + null + ); } - module.exports = isArguments; - - },{"./get-class":73}],76:[function(require,module,exports){ + module.exports = className; - var functionName = require("@sinonjs/commons").functionName; - var indexOf = require("@sinonjs/commons").prototypes.array.indexOf; - var map = require("@sinonjs/commons").prototypes.array.map; - var ARRAY_TYPES = require("./array-types"); - var type = require("type-detect"); + },{"./function-name":46}],44:[function(require,module,exports){ /** - * Returns `true` when `object` is an array type, `false` otherwise + * Returns a function that will invoke the supplied function and print a + * deprecation warning to the console each time it is called. * - * @param {*} object - The object to examine - * @returns {boolean} `true` when `object` is an array type - * @private + * @param {Function} func + * @param {string} msg + * @returns {Function} */ - function isArrayType(object) { - return indexOf(map(ARRAY_TYPES, functionName), type(object)) !== -1; - } - - module.exports = isArrayType; - - },{"./array-types":62,"@sinonjs/commons":95,"type-detect":151}],77:[function(require,module,exports){ + exports.wrap = function (func, msg) { + var wrapped = function () { + exports.printWarning(msg); + return func.apply(this, arguments); + }; + if (func.prototype) { + wrapped.prototype = func.prototype; + } + return wrapped; + }; /** - * Returns `true` when `value` is an instance of Date + * Returns a string which can be supplied to `wrap()` to notify the user that a + * particular part of the sinon API has been deprecated. * - * @private - * @param {Date} value The value to examine - * @returns {boolean} `true` when `value` is an instance of Date + * @param {string} packageName + * @param {string} funcName + * @returns {string} */ - function isDate(value) { - return value instanceof Date; - } - - module.exports = isDate; + exports.defaultMsg = function (packageName, funcName) { + return `${packageName}.${funcName} is deprecated and will be removed from the public API in a future version of ${packageName}.`; + }; - },{}],78:[function(require,module,exports){ + /** + * Prints a warning on the console, when it exists + * + * @param {string} msg + * @returns {undefined} + */ + exports.printWarning = function (msg) { + /* istanbul ignore next */ + if (typeof process === "object" && process.emitWarning) { + // Emit Warnings in Node + process.emitWarning(msg); + } else if (console.info) { + console.info(msg); + } else { + console.log(msg); + } + }; - var div = typeof document !== "undefined" && document.createElement("div"); + },{}],45:[function(require,module,exports){ /** - * Returns `true` when `object` is a DOM element node. - * - * Unlike Underscore.js/lodash, this function will return `false` if `object` - * is an *element-like* object, i.e. a regular object with a `nodeType` - * property that holds the value `1`. + * Returns true when fn returns true for all members of obj. + * This is an every implementation that works for all iterables * - * @alias module:samsam.isElement - * @param {object} object The object to examine - * @returns {boolean} Returns `true` for DOM element nodes + * @param {object} obj + * @param {Function} fn + * @returns {boolean} */ - function isElement(object) { - if (!object || object.nodeType !== 1 || !div) { - return false; - } + module.exports = function every(obj, fn) { + var pass = true; + try { - object.appendChild(div); - object.removeChild(div); + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + obj.forEach(function () { + if (!fn.apply(this, arguments)) { + // Throwing an error is the only way to break `forEach` + throw new Error(); + } + }); } catch (e) { - return false; + pass = false; } - return true; - } - module.exports = isElement; + return pass; + }; - },{}],79:[function(require,module,exports){ + },{}],46:[function(require,module,exports){ /** - * Returns `true` when the argument is an iterable, `false` otherwise + * Returns a display name for a function * - * @alias module:samsam.isIterable - * @param {*} val - A value to examine - * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise + * @param {Function} func + * @returns {string} */ - function isIterable(val) { - // checks for null and undefined - if (typeof val !== "object") { - return false; + module.exports = function functionName(func) { + if (!func) { + return ""; } - return typeof val[Symbol.iterator] === "function"; - } - module.exports = isIterable; + try { + return ( + func.displayName || + func.name || + // Use function decomposition as a last resort to get function + // name. Does not rely on function decomposition to work - if it + // doesn't debugging will be slightly less informative + // (i.e. toString will say 'spy' rather than 'myFunc'). + (String(func).match(/function ([^\s(]+)/) || [])[1] + ); + } catch (e) { + // Stringify may fail and we might get an exception, as a last-last + // resort fall back to empty string. + return ""; + } + }; - },{}],80:[function(require,module,exports){ + },{}],47:[function(require,module,exports){ /** - * Returns `true` when `value` is a Map + * A reference to the global object * - * @param {*} value A value to examine - * @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise - * @private + * @type {object} globalObject */ - function isMap(value) { - return typeof Map !== "undefined" && value instanceof Map; + var globalObject; + + /* istanbul ignore else */ + if (typeof global !== "undefined") { + // Node + globalObject = global; + } else if (typeof window !== "undefined") { + // Browser + globalObject = window; + } else { + // WebWorker + globalObject = self; } - module.exports = isMap; + module.exports = globalObject; - },{}],81:[function(require,module,exports){ + },{}],48:[function(require,module,exports){ + + module.exports = { + global: require("./global"), + calledInOrder: require("./called-in-order"), + className: require("./class-name"), + deprecated: require("./deprecated"), + every: require("./every"), + functionName: require("./function-name"), + orderByFirstCall: require("./order-by-first-call"), + prototypes: require("./prototypes"), + typeOf: require("./type-of"), + valueToString: require("./value-to-string"), + }; + + },{"./called-in-order":42,"./class-name":43,"./deprecated":44,"./every":45,"./function-name":46,"./global":47,"./order-by-first-call":49,"./prototypes":53,"./type-of":59,"./value-to-string":60}],49:[function(require,module,exports){ + + var sort = require("./prototypes/array").sort; + var slice = require("./prototypes/array").slice; /** - * Compares a `value` to `NaN` - * * @private - * @param {*} value A value to examine - * @returns {boolean} Returns `true` when `value` is `NaN` */ - function isNaN(value) { - // Unlike global `isNaN`, this function avoids type coercion - // `typeof` check avoids IE host object issues, hat tip to - // lodash + function comparator(a, b) { + // uuid, won't ever be equal + var aCall = a.getCall(0); + var bCall = b.getCall(0); + var aId = (aCall && aCall.callId) || -1; + var bId = (bCall && bCall.callId) || -1; - // eslint-disable-next-line no-self-compare - return typeof value === "number" && value !== value; + return aId < bId ? -1 : 1; } - module.exports = isNaN; - - },{}],82:[function(require,module,exports){ - /** - * Returns `true` when `value` is `-0` + * A Sinon proxy object (fake, spy, stub) * - * @alias module:samsam.isNegZero - * @param {*} value A value to examine - * @returns {boolean} Returns `true` when `value` is `-0` + * @typedef {object} SinonProxy + * @property {Function} getCall - A method that can return the first call */ - function isNegZero(value) { - return value === 0 && 1 / value === -Infinity; - } - - module.exports = isNegZero; - - },{}],83:[function(require,module,exports){ /** - * Returns `true` when the value is a regular Object and not a specialized Object - * - * This helps speed up deepEqual cyclic checks - * - * The premise is that only Objects are stored in the visited array. - * So if this function returns false, we don't have to do the - * expensive operation of searching for the value in the the array of already - * visited objects + * Sorts an array of SinonProxy instances (fake, spy, stub) by their first call * - * @private - * @param {object} value The object to examine - * @returns {boolean} `true` when the object is a non-specialised object + * @param {SinonProxy[] | SinonProxy} spies + * @returns {SinonProxy[]} */ - function isObject(value) { - return ( - typeof value === "object" && - value !== null && - // none of these are collection objects, so we can return false - !(value instanceof Boolean) && - !(value instanceof Date) && - !(value instanceof Error) && - !(value instanceof Number) && - !(value instanceof RegExp) && - !(value instanceof String) - ); + function orderByFirstCall(spies) { + return sort(slice(spies), comparator); } - module.exports = isObject; + module.exports = orderByFirstCall; - },{}],84:[function(require,module,exports){ + },{"./prototypes/array":50}],50:[function(require,module,exports){ - /** - * Returns `true` when the argument is an instance of Set, `false` otherwise - * - * @alias module:samsam.isSet - * @param {*} val - A value to examine - * @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise - */ - function isSet(val) { - return (typeof Set !== "undefined" && val instanceof Set) || false; - } + var copyPrototype = require("./copy-prototype-methods"); - module.exports = isSet; + module.exports = copyPrototype(Array.prototype); - },{}],85:[function(require,module,exports){ + },{"./copy-prototype-methods":51}],51:[function(require,module,exports){ - var forEach = require("@sinonjs/commons").prototypes.set.forEach; + var call = Function.call; + var throwsOnProto = require("./throws-on-proto"); - /** - * Returns `true` when `s1` is a subset of `s2`, `false` otherwise - * - * @private - * @param {Array|Set} s1 The target value - * @param {Array|Set} s2 The containing value - * @param {Function} compare A comparison function, should return `true` when - * values are considered equal - * @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise - */ - function isSubset(s1, s2, compare) { - var allContained = true; - forEach(s1, function (v1) { - var includes = false; - forEach(s2, function (v2) { - if (compare(v2, v1)) { - includes = true; - } - }); - allContained = allContained && includes; - }); + var disallowedProperties = [ + // ignore size because it throws from Map + "size", + "caller", + "callee", + "arguments", + ]; - return allContained; + // This branch is covered when tests are run with `--disable-proto=throw`, + // however we can test both branches at the same time, so this is ignored + /* istanbul ignore next */ + if (throwsOnProto) { + disallowedProperties.push("__proto__"); } - module.exports = isSubset; + module.exports = function copyPrototypeMethods(prototype) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return Object.getOwnPropertyNames(prototype).reduce(function ( + result, + name + ) { + if (disallowedProperties.includes(name)) { + return result; + } - },{"@sinonjs/commons":95}],86:[function(require,module,exports){ + if (typeof prototype[name] !== "function") { + return result; + } - var slice = require("@sinonjs/commons").prototypes.string.slice; - var typeOf = require("@sinonjs/commons").typeOf; - var valueToString = require("@sinonjs/commons").valueToString; + result[name] = call.bind(prototype[name]); - /** - * Creates a string represenation of an iterable object - * - * @private - * @param {object} obj The iterable object to stringify - * @returns {string} A string representation - */ - function iterableToString(obj) { - if (typeOf(obj) === "map") { - return mapToString(obj); - } + return result; + }, + Object.create(null)); + }; - return genericIterableToString(obj); - } + },{"./throws-on-proto":58}],52:[function(require,module,exports){ - /** - * Creates a string representation of a Map - * - * @private - * @param {Map} map The map to stringify - * @returns {string} A string representation - */ - function mapToString(map) { - var representation = ""; + var copyPrototype = require("./copy-prototype-methods"); - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - map.forEach(function (value, key) { - representation += `[${stringify(key)},${stringify(value)}],`; - }); + module.exports = copyPrototype(Function.prototype); - representation = slice(representation, 0, -1); - return representation; - } + },{"./copy-prototype-methods":51}],53:[function(require,module,exports){ - /** - * Create a string represenation for an iterable - * - * @private - * @param {object} iterable The iterable to stringify - * @returns {string} A string representation - */ - function genericIterableToString(iterable) { - var representation = ""; + module.exports = { + array: require("./array"), + function: require("./function"), + map: require("./map"), + object: require("./object"), + set: require("./set"), + string: require("./string"), + }; - // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods - iterable.forEach(function (value) { - representation += `${stringify(value)},`; - }); + },{"./array":50,"./function":52,"./map":54,"./object":55,"./set":56,"./string":57}],54:[function(require,module,exports){ - representation = slice(representation, 0, -1); - return representation; - } + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Map.prototype); + + },{"./copy-prototype-methods":51}],55:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Object.prototype); + + },{"./copy-prototype-methods":51}],56:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(Set.prototype); + + },{"./copy-prototype-methods":51}],57:[function(require,module,exports){ + + var copyPrototype = require("./copy-prototype-methods"); + + module.exports = copyPrototype(String.prototype); + + },{"./copy-prototype-methods":51}],58:[function(require,module,exports){ /** - * Creates a string representation of the passed `item` + * Is true when the environment causes an error to be thrown for accessing the + * __proto__ property. * - * @private - * @param {object} item The item to stringify - * @returns {string} A string representation of `item` + * This is necessary in order to support `node --disable-proto=throw`. + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto + * + * @type {boolean} */ - function stringify(item) { - return typeof item === "string" ? `'${item}'` : valueToString(item); + let throwsOnProto; + try { + const object = {}; + // eslint-disable-next-line no-proto, no-unused-expressions + object.__proto__; + throwsOnProto = false; + } catch (_) { + // This branch is covered when tests are run with `--disable-proto=throw`, + // however we can test both branches at the same time, so this is ignored + /* istanbul ignore next */ + throwsOnProto = true; } - module.exports = iterableToString; + module.exports = throwsOnProto; - },{"@sinonjs/commons":95}],87:[function(require,module,exports){ + },{}],59:[function(require,module,exports){ - var valueToString = require("@sinonjs/commons").valueToString; - var indexOf = require("@sinonjs/commons").prototypes.string.indexOf; - var forEach = require("@sinonjs/commons").prototypes.array.forEach; var type = require("type-detect"); - var engineCanCompareMaps = typeof Array.from === "function"; - var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define - var isArrayType = require("./is-array-type"); - var isSubset = require("./is-subset"); - var createMatcher = require("./create-matcher"); + /** + * Returns the lower-case result of running type from type-detect on the value + * + * @param {*} value + * @returns {string} + */ + module.exports = function typeOf(value) { + return type(value).toLowerCase(); + }; + + },{"type-detect":151}],60:[function(require,module,exports){ /** - * Returns true when `array` contains all of `subset` as defined by the `compare` - * argument + * Returns a string representation of the value * - * @param {Array} array An array to search for a subset - * @param {Array} subset The subset to find in the array - * @param {Function} compare A comparison function - * @returns {boolean} [description] - * @private + * @param {*} value + * @returns {string} */ - function arrayContains(array, subset, compare) { - if (subset.length === 0) { - return true; - } - var i, l, j, k; - for (i = 0, l = array.length; i < l; ++i) { - if (compare(array[i], subset[0])) { - for (j = 0, k = subset.length; j < k; ++j) { - if (i + j >= l) { - return false; - } - if (!compare(array[i + j], subset[j])) { - return false; - } - } - return true; - } + function valueToString(value) { + if (value && value.toString) { + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + return value.toString(); } - return false; + return String(value); } - /* eslint-disable complexity */ + module.exports = valueToString; + + },{}],61:[function(require,module,exports){ + + const globalObject = require("@sinonjs/commons").global; + /** - * Matches an object with a matcher (or value) - * - * @alias module:samsam.match - * @param {object} object The object candidate to match - * @param {object} matcherOrValue A matcher or value to match against - * @returns {boolean} true when `object` matches `matcherOrValue` + * @typedef {object} IdleDeadline + * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout + * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period */ - function match(object, matcherOrValue) { - if (matcherOrValue && typeof matcherOrValue.test === "function") { - return matcherOrValue.test(object); - } - switch (type(matcherOrValue)) { - case "bigint": - case "boolean": - case "number": - case "symbol": - return matcherOrValue === object; - case "function": - return matcherOrValue(object) === true; - case "string": - var notNull = typeof object === "string" || Boolean(object); - return ( - notNull && - indexOf( - valueToString(object).toLowerCase(), - matcherOrValue.toLowerCase() - ) >= 0 - ); - case "null": - return object === null; - case "undefined": - return typeof object === "undefined"; - case "Date": - /* istanbul ignore else */ - if (type(object) === "Date") { - return object.getTime() === matcherOrValue.getTime(); - } - /* istanbul ignore next: this is basically the rest of the function, which is covered */ - break; - case "Array": - case "Int8Array": - case "Uint8Array": - case "Uint8ClampedArray": - case "Int16Array": - case "Uint16Array": - case "Int32Array": - case "Uint32Array": - case "Float32Array": - case "Float64Array": - return ( - isArrayType(matcherOrValue) && - arrayContains(object, matcherOrValue, match) - ); - case "Map": - /* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/ - if (!engineCanCompareMaps) { - throw new Error( - "The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances" - ); - } + /** + * Queues a function to be called during a browser's idle periods + * + * @callback RequestIdleCallback + * @param {function(IdleDeadline)} callback + * @param {{timeout: number}} options - an options object + * @returns {number} the id + */ - return ( - type(object) === "Map" && - arrayContains( - Array.from(object), - Array.from(matcherOrValue), - match - ) - ); - } + /** + * @callback NextTick + * @param {VoidVarArgsFunc} callback - the callback to run + * @param {...*} arguments - optional arguments to call the callback with + * @returns {void} + */ - switch (type(object)) { - case "null": - return false; - case "Set": - return isSubset(matcherOrValue, object, match); - } + /** + * @callback SetImmediate + * @param {VoidVarArgsFunc} callback - the callback to run + * @param {...*} arguments - optional arguments to call the callback with + * @returns {NodeImmediate} + */ - /* istanbul ignore else */ - if (matcherOrValue && typeof matcherOrValue === "object") { - if (matcherOrValue === object) { - return true; - } - if (typeof object !== "object") { - return false; - } - var prop; - // eslint-disable-next-line guard-for-in - for (prop in matcherOrValue) { - var value = object[prop]; - if ( - typeof value === "undefined" && - typeof object.getAttribute === "function" - ) { - value = object.getAttribute(prop); - } - if ( - matcherOrValue[prop] === null || - typeof matcherOrValue[prop] === "undefined" - ) { - if (value !== matcherOrValue[prop]) { - return false; - } - } else if ( - typeof value === "undefined" || - !deepEqual(value, matcherOrValue[prop]) - ) { - return false; - } - } - return true; - } + /** + * @callback VoidVarArgsFunc + * @param {...*} callback - the callback to run + * @returns {void} + */ - /* istanbul ignore next */ - throw new Error("Matcher was an unknown or unsupported type"); - } - /* eslint-enable complexity */ + /** + * @typedef RequestAnimationFrame + * @property {function(number):void} requestAnimationFrame + * @returns {number} - the id + */ - forEach(Object.keys(createMatcher), function (key) { - match[key] = createMatcher[key]; - }); + /** + * @typedef Performance + * @property {function(): number} now + */ - module.exports = match; + /* eslint-disable jsdoc/require-property-description */ + /** + * @typedef {object} Clock + * @property {number} now - the current time + * @property {Date} Date - the Date constructor + * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop + * @property {RequestIdleCallback} requestIdleCallback + * @property {function(number):void} cancelIdleCallback + * @property {setTimeout} setTimeout + * @property {clearTimeout} clearTimeout + * @property {NextTick} nextTick + * @property {queueMicrotask} queueMicrotask + * @property {setInterval} setInterval + * @property {clearInterval} clearInterval + * @property {SetImmediate} setImmediate + * @property {function(NodeImmediate):void} clearImmediate + * @property {function():number} countTimers + * @property {RequestAnimationFrame} requestAnimationFrame + * @property {function(number):void} cancelAnimationFrame + * @property {function():void} runMicrotasks + * @property {function(string | number): number} tick + * @property {function(string | number): Promise} tickAsync + * @property {function(): number} next + * @property {function(): Promise} nextAsync + * @property {function(): number} runAll + * @property {function(): number} runToFrame + * @property {function(): Promise} runAllAsync + * @property {function(): number} runToLast + * @property {function(): Promise} runToLastAsync + * @property {function(): void} reset + * @property {function(number | Date): void} setSystemTime + * @property {function(number): void} jump + * @property {Performance} performance + * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) + * @property {function(): void} uninstall Uninstall the clock. + * @property {Function[]} methods - the methods that are faked + * @property {boolean} [shouldClearNativeTimers] inherited from config + */ + /* eslint-enable jsdoc/require-property-description */ - },{"./create-matcher":63,"./deep-equal":72,"./is-array-type":76,"./is-subset":85,"@sinonjs/commons":95,"type-detect":151}],88:[function(require,module,exports){ + /** + * Configuration object for the `install` method. + * + * @typedef {object} Config + * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) + * @property {string[]} [toFake] names of the methods that should be faked. + * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() + * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) + * @property {number} [advanceTimeDelta] increment mocked time every <> ms (default: 20ms) + * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) + */ + /* eslint-disable jsdoc/require-property-description */ /** - * @module samsam + * The internal structure to describe a scheduled fake timer + * + * @typedef {object} Timer + * @property {Function} func + * @property {*[]} args + * @property {number} delay + * @property {number} callAt + * @property {number} createdAt + * @property {boolean} immediate + * @property {number} id + * @property {Error} [error] */ - var identical = require("./identical"); - var isArguments = require("./is-arguments"); - var isElement = require("./is-element"); - var isNegZero = require("./is-neg-zero"); - var isSet = require("./is-set"); - var isMap = require("./is-map"); - var match = require("./match"); - var deepEqualCyclic = require("./deep-equal").use(match); - var createMatcher = require("./create-matcher"); - module.exports = { - createMatcher: createMatcher, - deepEqual: deepEqualCyclic, - identical: identical, - isArguments: isArguments, - isElement: isElement, - isMap: isMap, - isNegZero: isNegZero, - isSet: isSet, - match: match, - }; + /** + * A Node timer + * + * @typedef {object} NodeImmediate + * @property {function(): boolean} hasRef + * @property {function(): NodeImmediate} ref + * @property {function(): NodeImmediate} unref + */ + /* eslint-enable jsdoc/require-property-description */ - },{"./create-matcher":63,"./deep-equal":72,"./identical":74,"./is-arguments":75,"./is-element":78,"./is-map":80,"./is-neg-zero":82,"./is-set":84,"./match":87}],89:[function(require,module,exports){ - arguments[4][42][0].apply(exports,arguments); - },{"./prototypes/array":97,"dup":42}],90:[function(require,module,exports){ - arguments[4][43][0].apply(exports,arguments); - },{"./function-name":93,"dup":43}],91:[function(require,module,exports){ - arguments[4][44][0].apply(exports,arguments); - },{"dup":44}],92:[function(require,module,exports){ - arguments[4][45][0].apply(exports,arguments); - },{"dup":45}],93:[function(require,module,exports){ - arguments[4][46][0].apply(exports,arguments); - },{"dup":46}],94:[function(require,module,exports){ - arguments[4][47][0].apply(exports,arguments); - },{"dup":47}],95:[function(require,module,exports){ - arguments[4][48][0].apply(exports,arguments); - },{"./called-in-order":89,"./class-name":90,"./deprecated":91,"./every":92,"./function-name":93,"./global":94,"./order-by-first-call":96,"./prototypes":100,"./type-of":106,"./value-to-string":107,"dup":48}],96:[function(require,module,exports){ - arguments[4][49][0].apply(exports,arguments); - },{"./prototypes/array":97,"dup":49}],97:[function(require,module,exports){ - arguments[4][50][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":50}],98:[function(require,module,exports){ - arguments[4][51][0].apply(exports,arguments); - },{"./throws-on-proto":105,"dup":51}],99:[function(require,module,exports){ - arguments[4][52][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":52}],100:[function(require,module,exports){ - arguments[4][53][0].apply(exports,arguments); - },{"./array":97,"./function":99,"./map":101,"./object":102,"./set":103,"./string":104,"dup":53}],101:[function(require,module,exports){ - arguments[4][54][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":54}],102:[function(require,module,exports){ - arguments[4][55][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":55}],103:[function(require,module,exports){ - arguments[4][56][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":56}],104:[function(require,module,exports){ - arguments[4][57][0].apply(exports,arguments); - },{"./copy-prototype-methods":98,"dup":57}],105:[function(require,module,exports){ - arguments[4][58][0].apply(exports,arguments); - },{"dup":58}],106:[function(require,module,exports){ - arguments[4][59][0].apply(exports,arguments); - },{"dup":59,"type-detect":151}],107:[function(require,module,exports){ - arguments[4][60][0].apply(exports,arguments); - },{"dup":60}],108:[function(require,module,exports){ - // This is free and unencumbered software released into the public domain. - // See LICENSE.md for more information. - - var encoding = require("./lib/encoding.js"); - - module.exports = { - TextEncoder: encoding.TextEncoder, - TextDecoder: encoding.TextDecoder, - }; - - },{"./lib/encoding.js":110}],109:[function(require,module,exports){ - (function(global) { - - if (typeof module !== "undefined" && module.exports) { - module.exports = global; - } - - global["encoding-indexes"] = - { - "big5":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,17392,19506,17923,17830,17784,160359,19831,17843,162993,19682,163013,15253,18230,18244,19527,19520,148159,144919,160594,159371,159954,19543,172881,18255,17882,19589,162924,19719,19108,18081,158499,29221,154196,137827,146950,147297,26189,22267,null,32149,22813,166841,15860,38708,162799,23515,138590,23204,13861,171696,23249,23479,23804,26478,34195,170309,29793,29853,14453,138579,145054,155681,16108,153822,15093,31484,40855,147809,166157,143850,133770,143966,17162,33924,40854,37935,18736,34323,22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,36934,13542,29636,155065,29894,40903,22451,18735,21580,16689,145038,22552,31346,162661,35727,18094,159368,16769,155033,31662,140476,40904,140481,140489,140492,40905,34052,144827,16564,40906,17633,175615,25281,28782,40907,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,12736,12737,12738,12739,12740,131340,12741,131281,131277,12742,12743,131275,139240,12744,131274,12745,12746,12747,12748,131342,12749,12750,256,193,461,192,274,201,282,200,332,211,465,210,null,7870,null,7872,202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,null,7871,null,7873,234,609,9178,9179,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,172969,135493,null,25866,null,null,20029,28381,40270,37343,null,null,161589,25745,20250,20264,20392,20822,20852,20892,20964,21153,21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,36711,36718,29713,31996,32205,26950,31433,21031,null,null,null,null,37260,30904,37214,32956,null,36107,33014,133607,null,null,32927,40647,19661,40393,40460,19518,171510,159758,40458,172339,13761,null,28314,33342,29977,null,18705,39532,39567,40857,31111,164972,138698,132560,142054,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,163204,21797,null,134210,134421,151851,21904,142534,14828,131905,36422,150968,169189,16467,164030,30586,142392,14900,18389,164189,158194,151018,25821,134524,135092,134357,135412,25741,36478,134806,134155,135012,142505,164438,148691,null,134470,170573,164073,18420,151207,142530,39602,14951,169460,16365,13574,152263,169940,161992,142660,40302,38933,null,17369,155813,25780,21731,142668,142282,135287,14843,135279,157402,157462,162208,25834,151634,134211,36456,139681,166732,132913,null,18443,131497,16378,22643,142733,null,148936,132348,155799,134988,134550,21881,16571,17338,null,19124,141926,135325,33194,39157,134556,25465,14846,141173,36288,22177,25724,15939,null,173569,134665,142031,142537,null,135368,145858,14738,14854,164507,13688,155209,139463,22098,134961,142514,169760,13500,27709,151099,null,null,161140,142987,139784,173659,167117,134778,134196,157724,32659,135375,141315,141625,13819,152035,134796,135053,134826,16275,134960,134471,135503,134732,null,134827,134057,134472,135360,135485,16377,140950,25650,135085,144372,161337,142286,134526,134527,142417,142421,14872,134808,135367,134958,173618,158544,167122,167321,167114,38314,21708,33476,21945,null,171715,39974,39606,161630,142830,28992,33133,33004,23580,157042,33076,14231,21343,164029,37302,134906,134671,134775,134907,13789,151019,13833,134358,22191,141237,135369,134672,134776,135288,135496,164359,136277,134777,151120,142756,23124,135197,135198,135413,135414,22428,134673,161428,164557,135093,134779,151934,14083,135094,135552,152280,172733,149978,137274,147831,164476,22681,21096,13850,153405,31666,23400,18432,19244,40743,18919,39967,39821,154484,143677,22011,13810,22153,20008,22786,138177,194680,38737,131206,20059,20155,13630,23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,149737,32594,31035,31993,32595,156266,13505,null,156491,32770,32896,157202,158033,21341,34916,35265,161970,35744,36125,38021,38264,38271,38376,167439,38886,39029,39118,39134,39267,170000,40060,40479,40644,27503,63751,20023,131207,38429,25143,38050,null,20539,28158,171123,40870,15817,34959,147790,28791,23797,19232,152013,13657,154928,24866,166450,36775,37366,29073,26393,29626,144001,172295,15499,137600,19216,30948,29698,20910,165647,16393,27235,172730,16931,34319,133743,31274,170311,166634,38741,28749,21284,139390,37876,30425,166371,40871,30685,20131,20464,20668,20015,20247,40872,21556,32139,22674,22736,138678,24210,24217,24514,141074,25995,144377,26905,27203,146531,27903,null,29184,148741,29580,16091,150035,23317,29881,35715,154788,153237,31379,31724,31939,32364,33528,34199,40873,34960,40874,36537,40875,36815,34143,39392,37409,40876,167353,136255,16497,17058,23066,null,null,null,39016,26475,17014,22333,null,34262,149883,33471,160013,19585,159092,23931,158485,159678,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,143958,141206,17306,17718,null,23765,146202,35577,23672,15634,144721,23928,40882,29015,17752,147692,138787,19575,14712,13386,131492,158785,35532,20404,131641,22975,33132,38998,170234,24379,134047,null,139713,166253,16642,18107,168057,16135,40883,172469,16632,14294,18167,158790,16764,165554,160767,17773,14548,152730,17761,17691,19849,19579,19830,17898,16328,150287,13921,17630,17597,16877,23870,23880,23894,15868,14351,23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,26111,26195,15090,26258,15138,26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,28033,15599,28068,28081,28181,28184,28201,28294,166336,28347,28386,28378,40831,28392,28393,28452,28468,15686,147265,28545,28606,15722,15733,29111,23705,15754,28716,15761,28752,28756,28783,28799,28809,131877,17345,13809,134872,147159,22462,159443,28990,153568,13902,27042,166889,23412,31305,153825,169177,31333,31357,154028,31419,31408,31426,31427,29137,156813,16842,31450,31453,31466,16879,21682,154625,31499,31573,31529,152334,154878,31650,31599,33692,154548,158847,31696,33825,31634,31672,154912,15789,154725,33938,31738,31750,31797,154817,31812,31875,149634,31910,26237,148856,31945,31943,31974,31860,31987,31989,31950,32359,17693,159300,32093,159446,29837,32137,32171,28981,32179,32210,147543,155689,32228,15635,32245,137209,32229,164717,32285,155937,155994,32366,32402,17195,37996,32295,32576,32577,32583,31030,156368,39393,32663,156497,32675,136801,131176,17756,145254,17667,164666,32762,156809,32773,32776,32797,32808,32815,172167,158915,32827,32828,32865,141076,18825,157222,146915,157416,26405,32935,166472,33031,33050,22704,141046,27775,156824,151480,25831,136330,33304,137310,27219,150117,150165,17530,33321,133901,158290,146814,20473,136445,34018,33634,158474,149927,144688,137075,146936,33450,26907,194964,16859,34123,33488,33562,134678,137140,14017,143741,144730,33403,33506,33560,147083,159139,158469,158615,144846,15807,33565,21996,33669,17675,159141,33708,33729,33747,13438,159444,27223,34138,13462,159298,143087,33880,154596,33905,15827,17636,27303,33866,146613,31064,33960,158614,159351,159299,34014,33807,33681,17568,33939,34020,154769,16960,154816,17731,34100,23282,159385,17703,34163,17686,26559,34326,165413,165435,34241,159880,34306,136578,159949,194994,17770,34344,13896,137378,21495,160666,34430,34673,172280,34798,142375,34737,34778,34831,22113,34412,26710,17935,34885,34886,161248,146873,161252,34910,34972,18011,34996,34997,25537,35013,30583,161551,35207,35210,35238,35241,35239,35260,166437,35303,162084,162493,35484,30611,37374,35472,162393,31465,162618,147343,18195,162616,29052,35596,35615,152624,152933,35647,35660,35661,35497,150138,35728,35739,35503,136927,17941,34895,35995,163156,163215,195028,14117,163155,36054,163224,163261,36114,36099,137488,36059,28764,36113,150729,16080,36215,36265,163842,135188,149898,15228,164284,160012,31463,36525,36534,36547,37588,36633,36653,164709,164882,36773,37635,172703,133712,36787,18730,166366,165181,146875,24312,143970,36857,172052,165564,165121,140069,14720,159447,36919,165180,162494,36961,165228,165387,37032,165651,37060,165606,37038,37117,37223,15088,37289,37316,31916,166195,138889,37390,27807,37441,37474,153017,37561,166598,146587,166668,153051,134449,37676,37739,166625,166891,28815,23235,166626,166629,18789,37444,166892,166969,166911,37747,37979,36540,38277,38310,37926,38304,28662,17081,140922,165592,135804,146990,18911,27676,38523,38550,16748,38563,159445,25050,38582,30965,166624,38589,21452,18849,158904,131700,156688,168111,168165,150225,137493,144138,38705,34370,38710,18959,17725,17797,150249,28789,23361,38683,38748,168405,38743,23370,168427,38751,37925,20688,143543,143548,38793,38815,38833,38846,38848,38866,38880,152684,38894,29724,169011,38911,38901,168989,162170,19153,38964,38963,38987,39014,15118,160117,15697,132656,147804,153350,39114,39095,39112,39111,19199,159015,136915,21936,39137,39142,39148,37752,39225,150057,19314,170071,170245,39413,39436,39483,39440,39512,153381,14020,168113,170965,39648,39650,170757,39668,19470,39700,39725,165376,20532,39732,158120,14531,143485,39760,39744,171326,23109,137315,39822,148043,39938,39935,39948,171624,40404,171959,172434,172459,172257,172323,172511,40318,40323,172340,40462,26760,40388,139611,172435,172576,137531,172595,40249,172217,172724,40592,40597,40606,40610,19764,40618,40623,148324,40641,15200,14821,15645,20274,14270,166955,40706,40712,19350,37924,159138,40727,40726,40761,22175,22154,40773,39352,168075,38898,33919,40802,40809,31452,40846,29206,19390,149877,149947,29047,150008,148296,150097,29598,166874,137466,31135,166270,167478,37737,37875,166468,37612,37761,37835,166252,148665,29207,16107,30578,31299,28880,148595,148472,29054,137199,28835,137406,144793,16071,137349,152623,137208,14114,136955,137273,14049,137076,137425,155467,14115,136896,22363,150053,136190,135848,136134,136374,34051,145062,34051,33877,149908,160101,146993,152924,147195,159826,17652,145134,170397,159526,26617,14131,15381,15847,22636,137506,26640,16471,145215,147681,147595,147727,158753,21707,22174,157361,22162,135135,134056,134669,37830,166675,37788,20216,20779,14361,148534,20156,132197,131967,20299,20362,153169,23144,131499,132043,14745,131850,132116,13365,20265,131776,167603,131701,35546,131596,20120,20685,20749,20386,20227,150030,147082,20290,20526,20588,20609,20428,20453,20568,20732,20825,20827,20829,20830,28278,144789,147001,147135,28018,137348,147081,20904,20931,132576,17629,132259,132242,132241,36218,166556,132878,21081,21156,133235,21217,37742,18042,29068,148364,134176,149932,135396,27089,134685,29817,16094,29849,29716,29782,29592,19342,150204,147597,21456,13700,29199,147657,21940,131909,21709,134086,22301,37469,38644,37734,22493,22413,22399,13886,22731,23193,166470,136954,137071,136976,23084,22968,37519,23166,23247,23058,153926,137715,137313,148117,14069,27909,29763,23073,155267,23169,166871,132115,37856,29836,135939,28933,18802,37896,166395,37821,14240,23582,23710,24158,24136,137622,137596,146158,24269,23375,137475,137476,14081,137376,14045,136958,14035,33066,166471,138682,144498,166312,24332,24334,137511,137131,23147,137019,23364,34324,161277,34912,24702,141408,140843,24539,16056,140719,140734,168072,159603,25024,131134,131142,140827,24985,24984,24693,142491,142599,149204,168269,25713,149093,142186,14889,142114,144464,170218,142968,25399,173147,25782,25393,25553,149987,142695,25252,142497,25659,25963,26994,15348,143502,144045,149897,144043,21773,144096,137433,169023,26318,144009,143795,15072,16784,152964,166690,152975,136956,152923,152613,30958,143619,137258,143924,13412,143887,143746,148169,26254,159012,26219,19347,26160,161904,138731,26211,144082,144097,26142,153714,14545,145466,145340,15257,145314,144382,29904,15254,26511,149034,26806,26654,15300,27326,14435,145365,148615,27187,27218,27337,27397,137490,25873,26776,27212,15319,27258,27479,147392,146586,37792,37618,166890,166603,37513,163870,166364,37991,28069,28427,149996,28007,147327,15759,28164,147516,23101,28170,22599,27940,30786,28987,148250,148086,28913,29264,29319,29332,149391,149285,20857,150180,132587,29818,147192,144991,150090,149783,155617,16134,16049,150239,166947,147253,24743,16115,29900,29756,37767,29751,17567,159210,17745,30083,16227,150745,150790,16216,30037,30323,173510,15129,29800,166604,149931,149902,15099,15821,150094,16127,149957,149747,37370,22322,37698,166627,137316,20703,152097,152039,30584,143922,30478,30479,30587,149143,145281,14942,149744,29752,29851,16063,150202,150215,16584,150166,156078,37639,152961,30750,30861,30856,30930,29648,31065,161601,153315,16654,31131,33942,31141,27181,147194,31290,31220,16750,136934,16690,37429,31217,134476,149900,131737,146874,137070,13719,21867,13680,13994,131540,134157,31458,23129,141045,154287,154268,23053,131675,30960,23082,154566,31486,16889,31837,31853,16913,154547,155324,155302,31949,150009,137136,31886,31868,31918,27314,32220,32263,32211,32590,156257,155996,162632,32151,155266,17002,158581,133398,26582,131150,144847,22468,156690,156664,149858,32733,31527,133164,154345,154947,31500,155150,39398,34373,39523,27164,144447,14818,150007,157101,39455,157088,33920,160039,158929,17642,33079,17410,32966,33033,33090,157620,39107,158274,33378,33381,158289,33875,159143,34320,160283,23174,16767,137280,23339,137377,23268,137432,34464,195004,146831,34861,160802,23042,34926,20293,34951,35007,35046,35173,35149,153219,35156,161669,161668,166901,166873,166812,166393,16045,33955,18165,18127,14322,35389,35356,169032,24397,37419,148100,26068,28969,28868,137285,40301,35999,36073,163292,22938,30659,23024,17262,14036,36394,36519,150537,36656,36682,17140,27736,28603,140065,18587,28537,28299,137178,39913,14005,149807,37051,37015,21873,18694,37307,37892,166475,16482,166652,37927,166941,166971,34021,35371,38297,38311,38295,38294,167220,29765,16066,149759,150082,148458,16103,143909,38543,167655,167526,167525,16076,149997,150136,147438,29714,29803,16124,38721,168112,26695,18973,168083,153567,38749,37736,166281,166950,166703,156606,37562,23313,35689,18748,29689,147995,38811,38769,39224,134950,24001,166853,150194,38943,169178,37622,169431,37349,17600,166736,150119,166756,39132,166469,16128,37418,18725,33812,39227,39245,162566,15869,39323,19311,39338,39516,166757,153800,27279,39457,23294,39471,170225,19344,170312,39356,19389,19351,37757,22642,135938,22562,149944,136424,30788,141087,146872,26821,15741,37976,14631,24912,141185,141675,24839,40015,40019,40059,39989,39952,39807,39887,171565,39839,172533,172286,40225,19630,147716,40472,19632,40204,172468,172269,172275,170287,40357,33981,159250,159711,158594,34300,17715,159140,159364,159216,33824,34286,159232,145367,155748,31202,144796,144960,18733,149982,15714,37851,37566,37704,131775,30905,37495,37965,20452,13376,36964,152925,30781,30804,30902,30795,137047,143817,149825,13978,20338,28634,28633,28702,28702,21524,147893,22459,22771,22410,40214,22487,28980,13487,147884,29163,158784,151447,23336,137141,166473,24844,23246,23051,17084,148616,14124,19323,166396,37819,37816,137430,134941,33906,158912,136211,148218,142374,148417,22932,146871,157505,32168,155995,155812,149945,149899,166394,37605,29666,16105,29876,166755,137375,16097,150195,27352,29683,29691,16086,150078,150164,137177,150118,132007,136228,149989,29768,149782,28837,149878,37508,29670,37727,132350,37681,166606,166422,37766,166887,153045,18741,166530,29035,149827,134399,22180,132634,134123,134328,21762,31172,137210,32254,136898,150096,137298,17710,37889,14090,166592,149933,22960,137407,137347,160900,23201,14050,146779,14000,37471,23161,166529,137314,37748,15565,133812,19094,14730,20724,15721,15692,136092,29045,17147,164376,28175,168164,17643,27991,163407,28775,27823,15574,147437,146989,28162,28428,15727,132085,30033,14012,13512,18048,16090,18545,22980,37486,18750,36673,166940,158656,22546,22472,14038,136274,28926,148322,150129,143331,135856,140221,26809,26983,136088,144613,162804,145119,166531,145366,144378,150687,27162,145069,158903,33854,17631,17614,159014,159057,158850,159710,28439,160009,33597,137018,33773,158848,159827,137179,22921,23170,137139,23137,23153,137477,147964,14125,23023,137020,14023,29070,37776,26266,148133,23150,23083,148115,27179,147193,161590,148571,148170,28957,148057,166369,20400,159016,23746,148686,163405,148413,27148,148054,135940,28838,28979,148457,15781,27871,194597,150095,32357,23019,23855,15859,24412,150109,137183,32164,33830,21637,146170,144128,131604,22398,133333,132633,16357,139166,172726,28675,168283,23920,29583,31955,166489,168992,20424,32743,29389,29456,162548,29496,29497,153334,29505,29512,16041,162584,36972,29173,149746,29665,33270,16074,30476,16081,27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,151388,29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,23646,30654,30667,22770,30744,28857,30748,16552,30777,30791,30801,30822,33864,152885,31027,26627,31026,16643,16649,31121,31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,31981,36755,28864,134351,32207,32212,32208,32253,32686,32692,29343,17303,32800,32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,38469,34699,17926,17943,34990,35071,35108,35143,35217,162151,35369,35384,35476,35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,39809,39901,39921,39924,19565,39968,14191,138178,40265,39994,40702,22096,40339,40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,40696,31432,40772,131220,131767,132000,26906,38083,22956,132311,22592,38081,14265,132565,132629,132726,136890,22359,29043,133826,133837,134079,21610,194619,134091,21662,134139,134203,134227,134245,134268,24807,134285,22138,134325,134365,134381,134511,134578,134600,26965,39983,34725,134660,134670,134871,135056,134957,134771,23584,135100,24075,135260,135247,135286,26398,135291,135304,135318,13895,135359,135379,135471,135483,21348,33965,135907,136053,135990,35713,136567,136729,137155,137159,20088,28859,137261,137578,137773,137797,138282,138352,138412,138952,25283,138965,139029,29080,26709,139333,27113,14024,139900,140247,140282,141098,141425,141647,33533,141671,141715,142037,35237,142056,36768,142094,38840,142143,38983,39613,142412,null,142472,142519,154600,142600,142610,142775,142741,142914,143220,143308,143411,143462,144159,144350,24497,26184,26303,162425,144743,144883,29185,149946,30679,144922,145174,32391,131910,22709,26382,26904,146087,161367,155618,146961,147129,161278,139418,18640,19128,147737,166554,148206,148237,147515,148276,148374,150085,132554,20946,132625,22943,138920,15294,146687,148484,148694,22408,149108,14747,149295,165352,170441,14178,139715,35678,166734,39382,149522,149755,150037,29193,150208,134264,22885,151205,151430,132985,36570,151596,21135,22335,29041,152217,152601,147274,150183,21948,152646,152686,158546,37332,13427,152895,161330,152926,18200,152930,152934,153543,149823,153693,20582,13563,144332,24798,153859,18300,166216,154286,154505,154630,138640,22433,29009,28598,155906,162834,36950,156082,151450,35682,156674,156746,23899,158711,36662,156804,137500,35562,150006,156808,147439,156946,19392,157119,157365,141083,37989,153569,24981,23079,194765,20411,22201,148769,157436,20074,149812,38486,28047,158909,13848,35191,157593,157806,156689,157790,29151,157895,31554,168128,133649,157990,37124,158009,31301,40432,158202,39462,158253,13919,156777,131105,31107,158260,158555,23852,144665,33743,158621,18128,158884,30011,34917,159150,22710,14108,140685,159819,160205,15444,160384,160389,37505,139642,160395,37680,160486,149968,27705,38047,160848,134904,34855,35061,141606,164979,137137,28344,150058,137248,14756,14009,23568,31203,17727,26294,171181,170148,35139,161740,161880,22230,16607,136714,14753,145199,164072,136133,29101,33638,162269,168360,23143,19639,159919,166315,162301,162314,162571,163174,147834,31555,31102,163849,28597,172767,27139,164632,21410,159239,37823,26678,38749,164207,163875,158133,136173,143919,163912,23941,166960,163971,22293,38947,166217,23979,149896,26046,27093,21458,150181,147329,15377,26422,163984,164084,164142,139169,164175,164233,164271,164378,164614,164655,164746,13770,164968,165546,18682,25574,166230,30728,37461,166328,17394,166375,17375,166376,166726,166868,23032,166921,36619,167877,168172,31569,168208,168252,15863,168286,150218,36816,29327,22155,169191,169449,169392,169400,169778,170193,170313,170346,170435,170536,170766,171354,171419,32415,171768,171811,19620,38215,172691,29090,172799,19857,36882,173515,19868,134300,36798,21953,36794,140464,36793,150163,17673,32383,28502,27313,20202,13540,166700,161949,14138,36480,137205,163876,166764,166809,162366,157359,15851,161365,146615,153141,153942,20122,155265,156248,22207,134765,36366,23405,147080,150686,25566,25296,137206,137339,25904,22061,154698,21530,152337,15814,171416,19581,22050,22046,32585,155352,22901,146752,34672,19996,135146,134473,145082,33047,40286,36120,30267,40005,30286,30649,37701,21554,33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,134813,13774,22021,22001,26353,164578,13869,30004,22000,21946,21655,21874,134209,134294,24272,151880,134774,142434,134818,40619,32090,21982,135285,25245,38765,21652,36045,29174,37238,25596,25529,25598,21865,142147,40050,143027,20890,13535,134567,20903,21581,21790,21779,30310,36397,157834,30129,32950,34820,34694,35015,33206,33820,135361,17644,29444,149254,23440,33547,157843,22139,141044,163119,147875,163187,159440,160438,37232,135641,37384,146684,173737,134828,134905,29286,138402,18254,151490,163833,135147,16634,40029,25887,142752,18675,149472,171388,135148,134666,24674,161187,135149,null,155720,135559,29091,32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,149016,22682,150382,33325,21579,22442,154261,133497,null,14930,140389,29556,171692,19721,39917,146686,171824,19547,151465,169374,171998,33884,146870,160434,157619,145184,25390,32037,147191,146988,14890,36872,21196,15988,13946,17897,132238,30272,23280,134838,30842,163630,22695,16575,22140,39819,23924,30292,173108,40581,19681,30201,14331,24857,143578,148466,null,22109,135849,22439,149859,171526,21044,159918,13741,27722,40316,31830,39737,22494,137068,23635,25811,169168,156469,160100,34477,134440,159010,150242,134513,null,20990,139023,23950,38659,138705,40577,36940,31519,39682,23761,31651,25192,25397,39679,31695,39722,31870,39726,31810,31878,39957,31740,39689,40727,39963,149822,40794,21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,38465,27008,20646,30022,137069,39386,21107,null,37209,38529,37212,null,37201,167575,25471,159011,27338,22033,37262,30074,25221,132092,29519,31856,154657,146685,null,149785,30422,39837,20010,134356,33726,34882,null,23626,27072,20717,22394,21023,24053,20174,27697,131570,20281,21660,21722,21146,36226,13822,24332,13811,null,27474,37244,40869,39831,38958,39092,39610,40616,40580,29050,31508,null,27642,34840,32632,null,22048,173642,36471,40787,null,36308,36431,40476,36353,25218,164733,36392,36469,31443,150135,31294,30936,27882,35431,30215,166490,40742,27854,34774,30147,172722,30803,194624,36108,29410,29553,35629,29442,29937,36075,150203,34351,24506,34976,17591,null,137275,159237,null,35454,140571,null,24829,30311,39639,40260,37742,39823,34805,null,34831,36087,29484,38689,39856,13782,29362,19463,31825,39242,155993,24921,19460,40598,24957,null,22367,24943,25254,25145,25294,14940,25058,21418,144373,25444,26626,13778,23895,166850,36826,167481,null,20697,138566,30982,21298,38456,134971,16485,null,30718,null,31938,155418,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,160902,32859,29936,33027,30500,35209,157644,30035,159441,34729,34766,33224,34700,35401,36013,35651,30507,29944,34010,13877,27058,36262,null,35241,29800,28089,34753,147473,29927,15835,29046,24740,24988,15569,29026,24695,null,32625,166701,29264,24809,19326,21024,15384,146631,155351,161366,152881,137540,135934,170243,159196,159917,23745,156077,166415,145015,131310,157766,151310,17762,23327,156492,40784,40614,156267,12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,12321,12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19968,20057,19969,19971,20035,20061,20102,20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,20800,20995,21242,21315,21449,21475,22303,22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,20887,20982,20998,20999,21000,21243,21246,21247,21270,21305,21320,21319,21317,21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,29916,29926,29976,29983,29992,29993,30000,30001,30002,30003,30091,30333,30382,30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,20073,20121,20132,20134,20133,20223,20233,20249,20234,20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,22930,22952,22942,22947,22937,22934,22925,22948,22931,22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,21658,21602,21608,21643,21629,21646,22266,22403,22391,22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,32937,32948,32938,32943,33253,33278,33293,33459,33437,33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,22865,22863,22862,22864,23004,23000,23039,23011,23016,23043,23013,23018,23002,23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,27954,27946,27969,27941,27916,27953,27934,27927,27963,27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,31361,31487,31485,31869,32002,32005,32000,32009,32007,32004,32006,32568,32654,32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,35331,35998,36000,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,21769,21742,21738,21734,21799,21767,21757,21775,22275,22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,32020,32016,32021,32026,32028,32013,32025,32027,32570,32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,24246,24245,24254,24373,24375,24407,24428,24425,24427,24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,33333,33335,33334,33337,33678,33694,33688,33656,33698,33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,25954,25955,26001,26000,26031,26222,26224,26228,26230,26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,36024,36234,36229,36225,36302,36317,36299,36314,36305,36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,28998,29032,29014,29242,29266,29495,29509,29503,29502,29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,39156,39165,39166,39347,39345,39348,39649,40169,40578,40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,32862,32858,32903,33104,33152,33167,33160,33162,33151,33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,26292,26289,27171,27167,27112,27137,27166,27161,27133,27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,39389,39376,39391,39387,39377,39381,39378,39385,39607,39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,36986,37172,37266,37664,37686,37624,37683,37679,37666,37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,35140,35128,35133,35244,35598,35607,35609,35611,35594,35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37000,37291,37292,37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,40672,40725,40748,20787,22181,22750,22751,22754,23541,40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,38876,38907,39006,39000,39003,39100,39237,39241,39446,39449,39693,39912,39911,39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,25885,25884,26005,26345,27387,27396,27386,27570,28748,29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,38002,38000,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,24027,12083,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,710,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,65339,65341,10045,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8679,8632,8633,12751,131276,20058,131210,20994,17553,40880,20872,40881,161287,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,12003,null,null,null,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,32917,32921,32912,32914,32924,33424,33423,33413,33422,33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,27842,27834,27843,27846,27885,27890,27858,27869,27828,27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,24631,24633,24660,24690,24670,24645,24659,24647,24649,24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,32969,32975,32983,32998,32973,33279,33313,33428,33497,33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,26702,26692,26676,26653,26642,26644,26662,26664,26670,26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28000,28055,28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,33607,33605,33612,33619,33566,33580,33611,33575,33608,34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,24720,24710,24766,24752,24762,24787,24788,24783,24804,24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,31531,31533,31535,31538,31544,31514,31523,31892,31896,31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,21902,22284,22569,22583,22553,22558,22567,22563,22568,22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,28252,28257,28209,28200,28256,28273,28267,28217,28194,28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,35000,35008,35006,34998,35004,34999,35005,34994,35073,35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,24886,24882,24878,24902,24879,24911,24873,24896,25120,37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,27002,26952,26953,26933,26988,26931,26941,26981,26864,27000,26932,26985,26944,26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,30873,30848,30870,30843,31100,31106,31101,31097,31249,31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,37470,37507,37422,37450,37446,37485,37484,37455,37472,37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,27050,27041,27038,27097,27031,27024,27074,27061,27045,27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,33972,33985,33997,33962,33946,33969,34000,33949,33959,33979,33954,33940,33991,33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,34587,34627,34604,34625,34622,34630,34592,34610,34602,34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,25005,24991,24978,25002,24993,24973,24934,25011,25133,25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,33362,33360,33358,33361,34084,34107,34063,34048,34089,34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,39382,39384,39371,39383,39372,39603,39660,39659,39667,39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,24296,24293,24395,24508,24989,25000,24982,25029,25012,25030,25025,25036,25018,25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,30261,30258,30256,30395,30438,30618,30621,30625,30620,30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,37634,37668,37631,37673,37689,37685,37674,37652,37644,37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,31730,31744,31743,31739,31758,31732,31755,31731,31746,31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,39421,39422,39420,39427,39614,39678,39677,39681,39676,39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,22169,22896,23356,23657,23658,24000,24173,24174,25048,25055,25069,25070,25073,25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,35621,35639,35622,35638,35630,35620,35643,35645,35642,35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,31788,31803,31980,31978,32374,32373,32376,32368,32375,32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,26079,26344,26339,26340,27379,27376,27370,27368,27385,27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,40000,39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,28740,28746,28744,28745,28741,28742,29213,29210,29209,29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,39502,39507,39508,39500,39503,39496,39498,39497,39506,39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,31990,32410,32408,32411,32409,33248,33249,34374,34375,34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,9584,9583,65517,132423,37595,132575,147397,34124,17077,29679,20917,13897,149826,166372,37700,137691,33518,146632,30780,26436,25311,149811,166314,131744,158643,135941,20395,140525,20488,159017,162436,144896,150193,140563,20521,131966,24484,131968,131911,28379,132127,20605,20737,13434,20750,39020,14147,33814,149924,132231,20832,144308,20842,134143,139516,131813,140592,132494,143923,137603,23426,34685,132531,146585,20914,20920,40244,20937,20943,20945,15580,20947,150182,20915,20962,21314,20973,33741,26942,145197,24443,21003,21030,21052,21173,21079,21140,21177,21189,31765,34114,21216,34317,158483,21253,166622,21833,28377,147328,133460,147436,21299,21316,134114,27851,136998,26651,29653,24650,16042,14540,136936,29149,17570,21357,21364,165547,21374,21375,136598,136723,30694,21395,166555,21408,21419,21422,29607,153458,16217,29596,21441,21445,27721,20041,22526,21465,15019,134031,21472,147435,142755,21494,134263,21523,28793,21803,26199,27995,21613,158547,134516,21853,21647,21668,18342,136973,134877,15796,134477,166332,140952,21831,19693,21551,29719,21894,21929,22021,137431,147514,17746,148533,26291,135348,22071,26317,144010,26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,166758,13859,135759,22342,147877,27758,28811,22338,14001,158846,22502,136214,22531,136276,148323,22566,150517,22620,22698,13665,22752,22748,135740,22779,23551,22339,172368,148088,37843,13729,22815,26790,14019,28249,136766,23076,21843,136850,34053,22985,134478,158849,159018,137180,23001,137211,137138,159142,28017,137256,136917,23033,159301,23211,23139,14054,149929,23159,14088,23190,29797,23251,159649,140628,15749,137489,14130,136888,24195,21200,23414,25992,23420,162318,16388,18525,131588,23509,24928,137780,154060,132517,23539,23453,19728,23557,138052,23571,29646,23572,138405,158504,23625,18653,23685,23785,23791,23947,138745,138807,23824,23832,23878,138916,23738,24023,33532,14381,149761,139337,139635,33415,14390,15298,24110,27274,24181,24186,148668,134355,21414,20151,24272,21416,137073,24073,24308,164994,24313,24315,14496,24316,26686,37915,24333,131521,194708,15070,18606,135994,24378,157832,140240,24408,140401,24419,38845,159342,24434,37696,166454,24487,23990,15711,152144,139114,159992,140904,37334,131742,166441,24625,26245,137335,14691,15815,13881,22416,141236,31089,15936,24734,24740,24755,149890,149903,162387,29860,20705,23200,24932,33828,24898,194726,159442,24961,20980,132694,24967,23466,147383,141407,25043,166813,170333,25040,14642,141696,141505,24611,24924,25886,25483,131352,25285,137072,25301,142861,25452,149983,14871,25656,25592,136078,137212,25744,28554,142902,38932,147596,153373,25825,25829,38011,14950,25658,14935,25933,28438,150056,150051,25989,25965,25951,143486,26037,149824,19255,26065,16600,137257,26080,26083,24543,144384,26136,143863,143864,26180,143780,143781,26187,134773,26215,152038,26227,26228,138813,143921,165364,143816,152339,30661,141559,39332,26370,148380,150049,15147,27130,145346,26462,26471,26466,147917,168173,26583,17641,26658,28240,37436,26625,144358,159136,26717,144495,27105,27147,166623,26995,26819,144845,26881,26880,15666,14849,144956,15232,26540,26977,166474,17148,26934,27032,15265,132041,33635,20624,27129,144985,139562,27205,145155,27293,15347,26545,27336,168348,15373,27421,133411,24798,27445,27508,141261,28341,146139,132021,137560,14144,21537,146266,27617,147196,27612,27703,140427,149745,158545,27738,33318,27769,146876,17605,146877,147876,149772,149760,146633,14053,15595,134450,39811,143865,140433,32655,26679,159013,159137,159211,28054,27996,28284,28420,149887,147589,159346,34099,159604,20935,27804,28189,33838,166689,28207,146991,29779,147330,31180,28239,23185,143435,28664,14093,28573,146992,28410,136343,147517,17749,37872,28484,28508,15694,28532,168304,15675,28575,147780,28627,147601,147797,147513,147440,147380,147775,20959,147798,147799,147776,156125,28747,28798,28839,28801,28876,28885,28886,28895,16644,15848,29108,29078,148087,28971,28997,23176,29002,29038,23708,148325,29007,37730,148161,28972,148570,150055,150050,29114,166888,28861,29198,37954,29205,22801,37955,29220,37697,153093,29230,29248,149876,26813,29269,29271,15957,143428,26637,28477,29314,29482,29483,149539,165931,18669,165892,29480,29486,29647,29610,134202,158254,29641,29769,147938,136935,150052,26147,14021,149943,149901,150011,29687,29717,26883,150054,29753,132547,16087,29788,141485,29792,167602,29767,29668,29814,33721,29804,14128,29812,37873,27180,29826,18771,150156,147807,150137,166799,23366,166915,137374,29896,137608,29966,29929,29982,167641,137803,23511,167596,37765,30029,30026,30055,30062,151426,16132,150803,30094,29789,30110,30132,30210,30252,30289,30287,30319,30326,156661,30352,33263,14328,157969,157966,30369,30373,30391,30412,159647,33890,151709,151933,138780,30494,30502,30528,25775,152096,30552,144044,30639,166244,166248,136897,30708,30729,136054,150034,26826,30895,30919,30931,38565,31022,153056,30935,31028,30897,161292,36792,34948,166699,155779,140828,31110,35072,26882,31104,153687,31133,162617,31036,31145,28202,160038,16040,31174,168205,31188], - "euc-kr":[44034,44035,44037,44038,44043,44044,44045,44046,44047,44056,44062,44063,44065,44066,44067,44069,44070,44071,44072,44073,44074,44075,44078,44082,44083,44084,null,null,null,null,null,null,44085,44086,44087,44090,44091,44093,44094,44095,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44108,44110,44111,44112,44113,44114,44115,44117,null,null,null,null,null,null,44118,44119,44121,44122,44123,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44146,44147,44149,44150,44153,44155,44156,44157,44158,44159,44162,44167,44168,44173,44174,44175,44177,44178,44179,44181,44182,44183,44184,44185,44186,44187,44190,44194,44195,44196,44197,44198,44199,44203,44205,44206,44209,44210,44211,44212,44213,44214,44215,44218,44222,44223,44224,44226,44227,44229,44230,44231,44233,44234,44235,44237,44238,44239,44240,44241,44242,44243,44244,44246,44248,44249,44250,44251,44252,44253,44254,44255,44258,44259,44261,44262,44265,44267,44269,44270,44274,44276,44279,44280,44281,44282,44283,44286,44287,44289,44290,44291,44293,44295,44296,44297,44298,44299,44302,44304,44306,44307,44308,44309,44310,44311,44313,44314,44315,44317,44318,44319,44321,44322,44323,44324,44325,44326,44327,44328,44330,44331,44334,44335,44336,44337,44338,44339,null,null,null,null,null,null,44342,44343,44345,44346,44347,44349,44350,44351,44352,44353,44354,44355,44358,44360,44362,44363,44364,44365,44366,44367,44369,44370,44371,44373,44374,44375,null,null,null,null,null,null,44377,44378,44379,44380,44381,44382,44383,44384,44386,44388,44389,44390,44391,44392,44393,44394,44395,44398,44399,44401,44402,44407,44408,44409,44410,44414,44416,44419,44420,44421,44422,44423,44426,44427,44429,44430,44431,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44446,44447,44448,44449,44450,44451,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44472,44473,44474,44475,44476,44477,44478,44479,44482,44483,44485,44486,44487,44489,44490,44491,44492,44493,44494,44495,44498,44500,44501,44502,44503,44504,44505,44506,44507,44509,44510,44511,44513,44514,44515,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44538,44539,44541,44542,44546,44547,44548,44549,44550,44551,44554,44556,44558,44559,44560,44561,44562,44563,44565,44566,44567,44568,44569,44570,44571,44572,null,null,null,null,null,null,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44594,44595,44597,44598,44601,44603,44604,null,null,null,null,null,null,44605,44606,44607,44610,44612,44615,44616,44617,44619,44623,44625,44626,44627,44629,44631,44632,44633,44634,44635,44638,44642,44643,44644,44646,44647,44650,44651,44653,44654,44655,44657,44658,44659,44660,44661,44662,44663,44666,44670,44671,44672,44673,44674,44675,44678,44679,44680,44681,44682,44683,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44735,44737,44738,44739,44741,44742,44743,44744,44745,44746,44747,44750,44754,44755,44756,44757,44758,44759,44762,44763,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44777,44778,44780,44782,44783,44784,44785,44786,44787,44789,44790,44791,44793,44794,44795,44797,44798,44799,44800,44801,44802,44803,44804,44805,null,null,null,null,null,null,44806,44809,44810,44811,44812,44814,44815,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,null,null,null,null,null,null,44836,44837,44838,44839,44840,44841,44842,44843,44846,44847,44849,44851,44853,44854,44855,44856,44857,44858,44859,44862,44864,44868,44869,44870,44871,44874,44875,44876,44877,44878,44879,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44894,44895,44896,44897,44898,44899,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44922,44923,44924,44925,44926,44927,44929,44930,44931,44933,44934,44935,44937,44938,44939,44940,44941,44942,44943,44946,44947,44948,44950,44951,44952,44953,44954,44955,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44986,44987,44989,44990,44991,44993,44994,44995,44996,44997,44998,45002,45004,45007,45008,45009,45010,45011,45013,45014,45015,45016,45017,45018,45019,45021,45022,45023,45024,45025,null,null,null,null,null,null,45026,45027,45028,45029,45030,45031,45034,45035,45036,45037,45038,45039,45042,45043,45045,45046,45047,45049,45050,45051,45052,45053,45054,45055,45058,45059,null,null,null,null,null,null,45061,45062,45063,45064,45065,45066,45067,45069,45070,45071,45073,45074,45075,45077,45078,45079,45080,45081,45082,45083,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45126,45127,45129,45131,45133,45135,45136,45137,45138,45142,45144,45146,45147,45148,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45182,45183,45185,45186,45187,45189,45190,45191,45192,45193,45194,45195,45198,45200,45202,45203,45204,45205,45206,45207,45211,45213,45214,45219,45220,45221,45222,45223,45226,45232,45234,45238,45239,45241,45242,45243,45245,45246,45247,45248,45249,45250,45251,45254,45258,45259,45260,45261,45262,45263,45266,null,null,null,null,null,null,45267,45269,45270,45271,45273,45274,45275,45276,45277,45278,45279,45281,45282,45283,45284,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,null,null,null,null,null,null,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45322,45325,45326,45327,45329,45332,45333,45334,45335,45338,45342,45343,45344,45345,45346,45350,45351,45353,45354,45355,45357,45358,45359,45360,45361,45362,45363,45366,45370,45371,45372,45373,45374,45375,45378,45379,45381,45382,45383,45385,45386,45387,45388,45389,45390,45391,45394,45395,45398,45399,45401,45402,45403,45405,45406,45407,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45434,45435,45437,45438,45439,45441,45443,45444,45445,45446,45447,45450,45452,45454,45455,45456,45457,45461,45462,45463,45465,45466,45467,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,null,null,null,null,null,null,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45517,45518,45519,45521,45522,45523,45525,null,null,null,null,null,null,45526,45527,45528,45529,45530,45531,45534,45536,45537,45538,45539,45540,45541,45542,45543,45546,45547,45549,45550,45551,45553,45554,45555,45556,45557,45558,45559,45560,45562,45564,45566,45567,45568,45569,45570,45571,45574,45575,45577,45578,45581,45582,45583,45584,45585,45586,45587,45590,45592,45594,45595,45596,45597,45598,45599,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45621,45622,45623,45624,45625,45626,45627,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45657,45658,45659,45661,45662,45663,45665,45666,45667,45668,45669,45670,45671,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45686,45687,45688,45689,45690,45691,45693,45694,45695,45696,45697,45698,45699,45702,45703,45704,45706,45707,45708,45709,45710,null,null,null,null,null,null,45711,45714,45715,45717,45718,45719,45723,45724,45725,45726,45727,45730,45732,45735,45736,45737,45739,45741,45742,45743,45745,45746,45747,45749,45750,45751,null,null,null,null,null,null,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45770,45771,45773,45774,45775,45777,45779,45780,45781,45782,45783,45786,45788,45790,45791,45792,45793,45795,45799,45801,45802,45808,45809,45810,45814,45820,45821,45822,45826,45827,45829,45830,45831,45833,45834,45835,45836,45837,45838,45839,45842,45846,45847,45848,45849,45850,45851,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45911,45913,45914,45917,45920,45921,45922,45923,45926,45928,45930,45932,45933,45935,45938,45939,45941,45942,45943,45945,45946,45947,45948,45949,45950,45951,45954,45958,45959,45960,45961,45962,45963,45965,null,null,null,null,null,null,45966,45967,45969,45970,45971,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45986,45987,45988,45989,45990,45991,45993,45994,45995,45997,null,null,null,null,null,null,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46022,46023,46025,46026,46029,46031,46033,46034,46035,46038,46040,46042,46044,46046,46047,46049,46050,46051,46053,46054,46055,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46097,46098,46099,46100,46101,46102,46103,46105,46106,46107,46109,46110,46111,46113,46114,46115,46116,46117,46118,46119,46122,46124,46125,46126,46127,46128,46129,46130,46131,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46162,46163,46165,46166,46167,46169,46170,46171,46172,46173,46174,46175,46178,46180,46182,null,null,null,null,null,null,46183,46184,46185,46186,46187,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46209,46210,null,null,null,null,null,null,46211,46212,46213,46214,46215,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46238,46239,46240,46241,46242,46243,46245,46246,46247,46249,46250,46251,46253,46254,46255,46256,46257,46258,46259,46260,46262,46264,46266,46267,46268,46269,46270,46271,46273,46274,46275,46277,46278,46279,46281,46282,46283,46284,46285,46286,46287,46289,46290,46291,46292,46294,46295,46296,46297,46298,46299,46302,46303,46305,46306,46309,46311,46312,46313,46314,46315,46318,46320,46322,46323,46324,46325,46326,46327,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46358,46359,46361,46362,46365,46366,46367,46368,46369,46370,46371,46374,46379,46380,46381,46382,46383,46386,46387,46389,46390,46391,46393,46394,46395,46396,46397,46398,46399,46402,46406,null,null,null,null,null,null,46407,46408,46409,46410,46414,46415,46417,46418,46419,46421,46422,46423,46424,46425,46426,46427,46430,46434,46435,46436,46437,46438,46439,46440,46441,46442,null,null,null,null,null,null,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46498,46499,46501,46502,46503,46505,46508,46509,46510,46511,46514,46518,46519,46520,46521,46522,46526,46527,46529,46530,46531,46533,46534,46535,46536,46537,46538,46539,46542,46546,46547,46548,46549,46550,46551,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46610,46611,46613,46614,46615,46617,46618,46619,46620,46621,null,null,null,null,null,null,46622,46623,46624,46625,46626,46627,46628,46630,46631,46632,46633,46634,46635,46637,46638,46639,46640,46641,46642,46643,46645,46646,46647,46648,46649,46650,null,null,null,null,null,null,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46693,46694,46695,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46750,46751,46753,46754,46755,46757,46758,46759,46760,46761,46762,46765,46766,46767,46768,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46805,46806,46807,46808,46809,46810,46811,46812,46813,null,null,null,null,null,null,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46833,46834,46835,46837,46838,46839,46841,46842,null,null,null,null,null,null,46843,46844,46845,46846,46847,46850,46851,46852,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46890,46891,46893,46894,46897,46898,46899,46900,46901,46902,46903,46906,46908,46909,46910,46911,46912,46913,46914,46915,46917,46918,46919,46921,46922,46923,46925,46926,46927,46928,46929,46930,46931,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46945,46946,46947,46949,46950,46951,46953,46954,46955,46956,46957,46958,46959,46962,46964,46966,46967,46968,46969,46970,46971,46974,46975,46977,46978,46979,46981,46982,46983,46984,46985,46986,46987,46990,46995,46996,46997,47002,47003,47005,47006,47007,47009,47010,47011,47012,47013,47014,47015,47018,47022,47023,47024,47025,47026,47027,47030,47031,47033,47034,47035,47036,47037,47038,47039,47040,47041,null,null,null,null,null,null,47042,47043,47044,47045,47046,47048,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,null,null,null,null,null,null,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47086,47087,47089,47090,47091,47093,47094,47095,47096,47097,47098,47099,47102,47106,47107,47108,47109,47110,47114,47115,47117,47118,47119,47121,47122,47123,47124,47125,47126,47127,47130,47132,47134,47135,47136,47137,47138,47139,47142,47143,47145,47146,47147,47149,47150,47151,47152,47153,47154,47155,47158,47162,47163,47164,47165,47166,47167,47169,47170,47171,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47186,47188,47189,47190,47191,47192,47193,47194,47195,47198,47199,47201,47202,47203,47205,47206,47207,47208,47209,47210,47211,47214,47216,47218,47219,47220,47221,47222,47223,47225,47226,47227,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,null,null,null,null,null,null,47264,47265,47266,47267,47268,47269,47270,47271,47273,47274,47275,47276,47277,47278,47279,47281,47282,47283,47285,47286,47287,47289,47290,47291,47292,47293,null,null,null,null,null,null,47294,47295,47298,47300,47302,47303,47304,47305,47306,47307,47309,47310,47311,47313,47314,47315,47317,47318,47319,47320,47321,47322,47323,47324,47326,47328,47330,47331,47332,47333,47334,47335,47338,47339,47341,47342,47343,47345,47346,47347,47348,47349,47350,47351,47354,47356,47358,47359,47360,47361,47362,47363,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47385,47386,47387,47388,47389,47390,47391,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47422,47423,47425,47426,47427,47429,47430,47431,47432,47433,47434,47435,47437,47438,47440,47442,47443,47444,47445,47446,47447,47450,47451,47453,47454,47455,47457,47458,47459,47460,47461,47462,47463,47466,47468,47470,47471,47472,47473,47474,47475,47478,47479,47481,47482,47483,47485,null,null,null,null,null,null,47486,47487,47488,47489,47490,47491,47494,47496,47499,47500,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,null,null,null,null,null,null,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47534,47535,47537,47538,47539,47541,47542,47543,47544,47545,47546,47547,47550,47552,47554,47555,47556,47557,47558,47559,47562,47563,47565,47571,47572,47573,47574,47575,47578,47580,47583,47584,47586,47590,47591,47593,47594,47595,47597,47598,47599,47600,47601,47602,47603,47606,47611,47612,47613,47614,47615,47618,47619,47620,47621,47622,47623,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47674,47675,47677,47678,47679,47681,47683,47684,47685,47686,47687,47690,47692,47695,47696,47697,47698,47702,47703,47705,47706,47707,47709,47710,47711,47712,47713,47714,47715,47718,47722,47723,47724,47725,47726,47727,null,null,null,null,null,null,47730,47731,47733,47734,47735,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47750,47752,47753,47754,47755,47757,47758,47759,47760,47761,47762,null,null,null,null,null,null,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47786,47789,47790,47791,47793,47795,47796,47797,47798,47799,47802,47804,47806,47807,47808,47809,47810,47811,47813,47814,47815,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47869,47870,47871,47873,47874,47875,47877,47878,47879,47880,47881,47882,47883,47884,47886,47888,47890,47891,47892,47893,47894,47895,47897,47898,47899,47901,47902,47903,47905,47906,47907,47908,47909,47910,47911,47912,47914,47916,47917,47918,47919,47920,47921,47922,47923,47927,47929,47930,47935,47936,47937,47938,47939,47942,47944,47946,47947,47948,47950,47953,47954,null,null,null,null,null,null,47955,47957,47958,47959,47961,47962,47963,47964,47965,47966,47967,47968,47970,47972,47973,47974,47975,47976,47977,47978,47979,47981,47982,47983,47984,47985,null,null,null,null,null,null,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48009,48010,48011,48013,48014,48015,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48037,48038,48039,48041,48042,48043,48045,48046,48047,48048,48049,48050,48051,48053,48054,48056,48057,48058,48059,48060,48061,48062,48063,48065,48066,48067,48069,48070,48071,48073,48074,48075,48076,48077,48078,48079,48081,48082,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48122,48123,48125,48126,48129,48131,48132,48133,48134,48135,48138,48142,48144,48146,48147,48153,48154,48160,48161,48162,48163,48166,48168,48170,48171,48172,48174,48175,48178,48179,48181,null,null,null,null,null,null,48182,48183,48185,48186,48187,48188,48189,48190,48191,48194,48198,48199,48200,48202,48203,48206,48207,48209,48210,48211,48212,48213,48214,48215,48216,48217,null,null,null,null,null,null,48218,48219,48220,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48262,48263,48265,48266,48269,48271,48272,48273,48274,48275,48278,48280,48283,48284,48285,48286,48287,48290,48291,48293,48294,48297,48298,48299,48300,48301,48302,48303,48306,48310,48311,48312,48313,48314,48315,48318,48319,48321,48322,48323,48325,48326,48327,48328,48329,48330,48331,48332,48334,48338,48339,48340,48342,48343,48345,48346,48347,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48375,48377,48378,48379,48381,48382,48383,48384,48385,48386,48387,48390,48392,48394,48395,48396,48397,48398,48399,48401,48402,48403,48405,48406,48407,48408,48409,48410,48411,48412,48413,null,null,null,null,null,null,48414,48415,48416,48417,48418,48419,48421,48422,48423,48424,48425,48426,48427,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,null,null,null,null,null,null,48442,48443,48444,48445,48446,48447,48449,48450,48451,48452,48453,48454,48455,48458,48459,48461,48462,48463,48465,48466,48467,48468,48469,48470,48471,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48485,48486,48487,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48514,48515,48517,48518,48523,48524,48525,48526,48527,48530,48532,48534,48535,48536,48539,48541,48542,48543,48544,48545,48546,48547,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48561,48562,48563,48564,48565,48566,48567,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48598,48599,48601,48602,48603,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48618,48619,48620,48621,48622,48623,48625,null,null,null,null,null,null,48626,48627,48629,48630,48631,48633,48634,48635,48636,48637,48638,48639,48641,48642,48644,48646,48647,48648,48649,48650,48651,48654,48655,48657,48658,48659,null,null,null,null,null,null,48661,48662,48663,48664,48665,48666,48667,48670,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48710,48711,48713,48714,48715,48717,48719,48720,48721,48722,48723,48726,48728,48732,48733,48734,48735,48738,48739,48741,48742,48743,48745,48747,48748,48749,48750,48751,48754,48758,48759,48760,48761,48762,48766,48767,48769,48770,48771,48773,48774,48775,48776,48777,48778,48779,48782,48786,48787,48788,48789,48790,48791,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48850,48851,null,null,null,null,null,null,48853,48854,48857,48858,48859,48860,48861,48862,48863,48865,48866,48870,48871,48872,48873,48874,48875,48877,48878,48879,48880,48881,48882,48883,48884,48885,null,null,null,null,null,null,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48898,48899,48900,48901,48902,48903,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48922,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48962,48963,48965,48966,48967,48969,48970,48971,48972,48973,48974,48975,48978,48979,48980,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49045,49046,49047,49048,49049,49050,49051,49052,49053,null,null,null,null,null,null,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49073,49074,49075,49076,49077,49078,49079,49080,null,null,null,null,null,null,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49094,49095,49096,49097,49098,49099,49102,49103,49105,49106,49107,49109,49110,49111,49112,49113,49114,49115,49117,49118,49120,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49234,49235,49236,49237,49238,49239,49241,49242,49243,null,null,null,null,null,null,49245,49246,49247,49249,49250,49251,49252,49253,49254,49255,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,null,null,null,null,null,null,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49298,49299,49301,49302,49303,49305,49306,49307,49308,49309,49310,49311,49314,49316,49318,49319,49320,49321,49322,49323,49326,49329,49330,49335,49336,49337,49338,49339,49342,49346,49347,49348,49350,49351,49354,49355,49357,49358,49359,49361,49362,49363,49364,49365,49366,49367,49370,49374,49375,49376,49377,49378,49379,49382,49383,49385,49386,49387,49389,49390,49391,49392,49393,49394,49395,49398,49400,49402,49403,49404,49405,49406,49407,49409,49410,49411,49413,49414,49415,49417,49418,49419,49420,49421,49422,49423,49425,49426,49427,49428,49430,49431,49432,49433,49434,49435,49441,49442,49445,49448,49449,49450,49451,49454,49458,49459,49460,49461,49463,49466,49467,49469,49470,49471,49473,49474,49475,49476,49477,49478,49479,49482,49486,49487,49488,49489,49490,49491,49494,49495,null,null,null,null,null,null,49497,49498,49499,49501,49502,49503,49504,49505,49506,49507,49510,49514,49515,49516,49517,49518,49519,49521,49522,49523,49525,49526,49527,49529,49530,49531,null,null,null,null,null,null,49532,49533,49534,49535,49536,49537,49538,49539,49540,49542,49543,49544,49545,49546,49547,49551,49553,49554,49555,49557,49559,49560,49561,49562,49563,49566,49568,49570,49571,49572,49574,49575,49578,49579,49581,49582,49583,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49598,49599,49600,49601,49602,49603,49605,49606,49607,49609,49610,49611,49613,49614,49615,49616,49617,49618,49619,49621,49622,49625,49626,49627,49628,49629,49630,49631,49633,49634,49635,49637,49638,49639,49641,49642,49643,49644,49645,49646,49647,49650,49652,49653,49654,49655,49656,49657,49658,49659,49662,49663,49665,49666,49667,49669,49670,49671,49672,49673,49674,49675,49678,49680,49682,49683,49684,49685,49686,49687,49690,49691,49693,49694,49697,49698,49699,49700,49701,49702,49703,49706,49708,49710,49712,49715,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,null,null,null,null,null,null,49734,49735,49737,49738,49739,49740,49741,49742,49743,49746,49747,49749,49750,49751,49753,49754,49755,49756,49757,49758,49759,49761,49762,49763,49764,49766,null,null,null,null,null,null,49767,49768,49769,49770,49771,49774,49775,49777,49778,49779,49781,49782,49783,49784,49785,49786,49787,49790,49792,49794,49795,49796,49797,49798,49799,49802,49803,49804,49805,49806,49807,49809,49810,49811,49812,49813,49814,49815,49817,49818,49820,49822,49823,49824,49825,49826,49827,49830,49831,49833,49834,49835,49838,49839,49840,49841,49842,49843,49846,49848,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49886,49887,49889,49890,49893,49894,49895,49896,49897,49898,49902,49904,49906,49907,49908,49909,49911,49914,49917,49918,49919,49921,49922,49923,49924,49925,49926,49927,49930,49931,49934,49935,49936,49937,49938,49942,49943,49945,49946,49947,49949,49950,49951,49952,49953,49954,49955,49958,49959,49962,49963,49964,49965,49966,49967,49968,49969,49970,null,null,null,null,null,null,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49990,49991,49992,49993,49994,49995,49996,49997,null,null,null,null,null,null,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50026,50027,50029,50030,50031,50033,50035,50036,50037,50038,50039,50042,50043,50046,50047,50048,50049,50050,50051,50053,50054,50055,50057,50058,50059,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50138,50139,50141,50142,50145,50147,50148,50149,50150,50151,50154,50155,50156,50158,50159,50160,50161,50162,50163,50166,50167,50169,50170,50171,50172,50173,50174,null,null,null,null,null,null,50175,50176,50177,50178,50179,50180,50181,50182,50183,50185,50186,50187,50188,50189,50190,50191,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,null,null,null,null,null,null,50203,50204,50205,50206,50207,50208,50209,50210,50211,50213,50214,50215,50216,50217,50218,50219,50221,50222,50223,50225,50226,50227,50229,50230,50231,50232,50233,50234,50235,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50278,50279,50281,50282,50283,50285,50286,50287,50288,50289,50290,50291,50294,50295,50296,50298,50299,50300,50301,50302,50303,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50325,50326,50327,50328,50329,50330,50331,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50361,50362,50363,50365,50366,50367,50368,50369,50370,50371,50372,50373,null,null,null,null,null,null,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,null,null,null,null,null,null,50400,50401,50402,50403,50404,50405,50406,50407,50408,50410,50411,50412,50413,50414,50415,50418,50419,50421,50422,50423,50425,50427,50428,50429,50430,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50445,50446,50447,50449,50450,50451,50453,50454,50455,50456,50457,50458,50459,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50474,50475,50477,50478,50479,50481,50482,50483,50484,50485,50486,50487,50490,50492,50494,50495,50496,50497,50498,50499,50502,50503,50507,50511,50512,50513,50514,50518,50522,50523,50524,50527,50530,50531,50533,50534,50535,50537,50538,50539,50540,50541,50542,50543,50546,50550,50551,50552,50553,50554,50555,50558,50559,50561,50562,50563,50565,50566,50568,50569,50570,50571,50574,50576,50578,50579,50580,50582,50585,50586,50587,50589,50590,50591,50593,50594,50595,50596,50597,50598,50599,50600,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50614,null,null,null,null,null,null,50615,50618,50623,50624,50625,50626,50627,50635,50637,50639,50642,50643,50645,50646,50647,50649,50650,50651,50652,50653,50654,50655,50658,50660,50662,50663,null,null,null,null,null,null,50664,50665,50666,50667,50671,50673,50674,50675,50677,50680,50681,50682,50683,50690,50691,50692,50697,50698,50699,50701,50702,50703,50705,50706,50707,50708,50709,50710,50711,50714,50717,50718,50719,50720,50721,50722,50723,50726,50727,50729,50730,50731,50735,50737,50738,50742,50744,50746,50748,50749,50750,50751,50754,50755,50757,50758,50759,50761,50762,50763,50764,50765,50766,50767,50770,50774,50775,50776,50777,50778,50779,50782,50783,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50797,50798,50800,50802,50803,50804,50805,50806,50807,50810,50811,50813,50814,50815,50817,50818,50819,50820,50821,50822,50823,50826,50828,50830,50831,50832,50833,50834,50835,50838,50839,50841,50842,50843,50845,50846,50847,50848,50849,50850,50851,50854,50856,50858,50859,50860,50861,50862,50863,50866,50867,50869,50870,50871,50875,50876,50877,50878,50879,50882,50884,50886,50887,50888,50889,50890,50891,50894,null,null,null,null,null,null,50895,50897,50898,50899,50901,50902,50903,50904,50905,50906,50907,50910,50911,50914,50915,50916,50917,50918,50919,50922,50923,50925,50926,50927,50929,50930,null,null,null,null,null,null,50931,50932,50933,50934,50935,50938,50939,50940,50942,50943,50944,50945,50946,50947,50950,50951,50953,50954,50955,50957,50958,50959,50960,50961,50962,50963,50966,50968,50970,50971,50972,50973,50974,50975,50978,50979,50981,50982,50983,50985,50986,50987,50988,50989,50990,50991,50994,50996,50998,51000,51001,51002,51003,51006,51007,51009,51010,51011,51013,51014,51015,51016,51017,51019,51022,51024,51033,51034,51035,51037,51038,51039,51041,51042,51043,51044,51045,51046,51047,51049,51050,51052,51053,51054,51055,51056,51057,51058,51059,51062,51063,51065,51066,51067,51071,51072,51073,51074,51078,51083,51084,51085,51087,51090,51091,51093,51097,51099,51100,51101,51102,51103,51106,51111,51112,51113,51114,51115,51118,51119,51121,51122,51123,51125,51126,51127,51128,51129,51130,51131,51134,51138,51139,51140,51141,51142,51143,51146,51147,51149,51151,51153,51154,51155,51156,51157,51158,51159,51161,51162,51163,51164,null,null,null,null,null,null,51166,51167,51168,51169,51170,51171,51173,51174,51175,51177,51178,51179,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,null,null,null,null,null,null,51195,51196,51197,51198,51199,51202,51203,51205,51206,51207,51209,51211,51212,51213,51214,51215,51218,51220,51223,51224,51225,51226,51227,51230,51231,51233,51234,51235,51237,51238,51239,51240,51241,51242,51243,51246,51248,51250,51251,51252,51253,51254,51255,51257,51258,51259,51261,51262,51263,51265,51266,51267,51268,51269,51270,51271,51274,51275,51278,51279,51280,51281,51282,51283,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51314,51315,51317,51318,51319,51321,51323,51324,51325,51326,51327,51330,51332,51336,51337,51338,51342,51343,51344,51345,51346,51347,51349,51350,51351,51352,51353,51354,51355,51356,51358,51360,51362,51363,51364,51365,51366,51367,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51390,51391,51392,51393,null,null,null,null,null,null,51394,51395,51397,51398,51399,51401,51402,51403,51405,51406,51407,51408,51409,51410,51411,51414,51416,51418,51419,51420,51421,51422,51423,51426,51427,51429,null,null,null,null,null,null,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51446,51447,51448,51449,51450,51451,51454,51455,51457,51458,51459,51463,51464,51465,51466,51467,51470,12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,8835,8746,8745,8743,8744,65506,51472,51474,51475,51476,51477,51478,51479,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,null,null,null,null,null,null,51501,51502,51503,51504,51505,51506,51507,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,null,null,null,null,null,null,51528,51529,51530,51531,51532,51533,51534,51535,51538,51539,51541,51542,51543,51545,51546,51547,51548,51549,51550,51551,51554,51556,51557,51558,51559,51560,51561,51562,51563,51565,51566,51567,8658,8660,8704,8707,180,65374,711,728,733,730,729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51569,51570,51571,51573,51574,51575,51576,51577,51578,51579,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51594,51595,51597,51598,51599,null,null,null,null,null,null,51601,51602,51603,51604,51605,51606,51607,51610,51612,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,null,null,null,null,null,null,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51650,51651,51653,51654,51657,51659,51660,51661,51662,51663,51666,51668,51671,51672,51675,65281,65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,51678,51679,51681,51683,51685,51686,51688,51689,51690,51691,51694,51698,51699,51700,51701,51702,51703,51706,51707,51709,51710,51711,51713,51714,51715,51716,null,null,null,null,null,null,51717,51718,51719,51722,51726,51727,51728,51729,51730,51731,51733,51734,51735,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,null,null,null,null,null,null,51750,51751,51752,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,51783,51784,51785,51786,51787,51790,51791,51793,51794,51795,51797,51798,51799,51800,51801,51802,51803,51806,51810,51811,51812,51813,51814,51815,51817,51818,null,null,null,null,null,null,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51838,51839,51840,51841,51842,51843,51845,51846,null,null,null,null,null,null,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,null,null,null,null,null,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51902,51903,51905,51906,51907,51909,null,null,null,null,null,null,51910,51911,51912,51913,51914,51915,51918,51920,51922,51924,51925,51926,51927,51930,51931,51932,51933,51934,51935,51937,51938,51939,51940,51941,51942,51943,null,null,null,null,null,null,51944,51945,51946,51947,51949,51950,51951,51952,51953,51954,51955,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51977,51978,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51979,51980,51981,51982,51983,51985,51986,51987,51989,51990,51991,51993,51994,51995,51996,51997,51998,51999,52002,52003,52004,52005,52006,52007,52008,52009,null,null,null,null,null,null,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52034,52035,52036,null,null,null,null,null,null,52037,52038,52039,52042,52043,52045,52046,52047,52049,52050,52051,52052,52053,52054,52055,52058,52059,52060,52062,52063,52064,52065,52066,52067,52069,52070,52071,52072,52073,52074,52075,52076,13205,13206,13207,8467,13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,null,null,null,null,null,null,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52125,52126,52127,52128,52129,52130,52131,null,null,null,null,null,null,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,198,208,170,294,null,306,null,319,321,216,338,186,222,358,330,null,12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,190,8539,8540,8541,8542,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,null,null,null,null,null,null,52192,52193,52194,52195,52197,52198,52200,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,null,null,null,null,null,null,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52238,52239,52241,52242,52243,52245,52246,52247,52248,52249,52250,52251,52254,52255,52256,52259,52260,230,273,240,295,305,307,312,320,322,248,339,223,254,359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,185,178,179,8308,8319,8321,8322,8323,8324,52261,52262,52266,52267,52269,52271,52273,52274,52275,52276,52277,52278,52279,52282,52287,52288,52289,52290,52291,52294,52295,52297,52298,52299,52301,52302,null,null,null,null,null,null,52303,52304,52305,52306,52307,52310,52314,52315,52316,52317,52318,52319,52321,52322,52323,52325,52327,52329,52330,52331,52332,52333,52334,52335,52337,52338,null,null,null,null,null,null,52339,52340,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,52372,52373,52374,52375,52378,52379,52381,52382,52383,52385,52386,52387,52388,52389,52390,52391,52394,52398,52399,52400,52401,52402,52403,52406,52407,52409,null,null,null,null,null,null,52410,52411,52413,52414,52415,52416,52417,52418,52419,52422,52424,52426,52427,52428,52429,52430,52431,52433,52434,52435,52437,52438,52439,52440,52441,52442,null,null,null,null,null,null,52443,52444,52445,52446,52447,52448,52449,52450,52451,52453,52454,52455,52456,52457,52458,52459,52461,52462,52463,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,52478,52479,52480,52482,52483,52484,52485,52486,52487,52490,52491,52493,52494,52495,52497,52498,52499,52500,52501,52502,52503,52506,52508,52510,52511,52512,null,null,null,null,null,null,52513,52514,52515,52517,52518,52519,52521,52522,52523,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52538,52539,52540,52541,52542,null,null,null,null,null,null,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52573,52574,52575,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,52577,52578,52579,52581,52582,52583,52584,52585,52586,52587,52590,52592,52594,52595,52596,52597,52598,52599,52601,52602,52603,52604,52605,52606,52607,52608,null,null,null,null,null,null,52609,52610,52611,52612,52613,52614,52615,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52630,52631,52633,52634,52635,52637,52638,52639,null,null,null,null,null,null,52640,52641,52642,52643,52646,52648,52650,52651,52652,52653,52654,52655,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52677,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52678,52679,52680,52681,52682,52683,52685,52686,52687,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,null,null,null,null,null,null,52706,52707,52708,52709,52710,52711,52713,52714,52715,52717,52718,52719,52721,52722,52723,52724,52725,52726,52727,52730,52732,52734,52735,52736,52737,52738,null,null,null,null,null,null,52739,52741,52742,52743,52745,52746,52747,52749,52750,52751,52752,52753,52754,52755,52757,52758,52759,52760,52762,52763,52764,52765,52766,52767,52770,52771,52773,52774,52775,52777,52778,52779,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52780,52781,52782,52783,52786,52788,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,null,null,null,null,null,null,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52826,52827,52829,52830,52834,52835,52836,52837,52838,52839,52842,52844,null,null,null,null,null,null,52846,52847,52848,52849,52850,52851,52854,52855,52857,52858,52859,52861,52862,52863,52864,52865,52866,52867,52870,52872,52874,52875,52876,52877,52878,52879,52882,52883,52885,52886,52887,52889,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52890,52891,52892,52893,52894,52895,52898,52902,52903,52904,52905,52906,52907,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,null,null,null,null,null,null,52923,52924,52925,52926,52927,52928,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,null,null,null,null,null,null,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52966,52967,52969,52970,52973,52974,52975,52976,52977,52978,52979,52982,52986,52987,52988,52989,52990,52991,44032,44033,44036,44039,44040,44041,44042,44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,44273,44275,44277,44278,44284,44285,44288,44292,44294,52994,52995,52997,52998,52999,53001,53002,53003,53004,53005,53006,53007,53010,53012,53014,53015,53016,53017,53018,53019,53021,53022,53023,53025,53026,53027,null,null,null,null,null,null,53029,53030,53031,53032,53033,53034,53035,53038,53042,53043,53044,53045,53046,53047,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,null,null,null,null,null,null,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53078,53079,53081,53082,53083,53085,53086,53087,53088,53089,53090,53091,53094,53096,53098,53099,53100,44300,44301,44303,44305,44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,53101,53102,53103,53106,53107,53109,53110,53111,53113,53114,53115,53116,53117,53118,53119,53121,53122,53123,53124,53126,53127,53128,53129,53130,53131,53133,null,null,null,null,null,null,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53154,53155,53156,53157,53158,53159,53161,null,null,null,null,null,null,53162,53163,53164,53165,53166,53167,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53189,53190,53191,53192,53193,53194,53195,44665,44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,44945,44949,44956,44984,44985,44988,44992,44999,45000,45001,45003,45005,45006,45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,45143,45145,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53218,53219,53221,53222,53223,53225,null,null,null,null,null,null,53226,53227,53228,53229,53230,53231,53234,53236,53238,53239,53240,53241,53242,53243,53245,53246,53247,53249,53250,53251,53253,53254,53255,53256,53257,53258,null,null,null,null,null,null,53259,53260,53261,53262,53263,53264,53266,53267,53268,53269,53270,53271,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,45516,45520,45524,45532,45533,53294,53295,53296,53297,53298,53299,53302,53303,53305,53306,53307,53309,53310,53311,53312,53313,53314,53315,53318,53320,53322,53323,53324,53325,53326,53327,null,null,null,null,null,null,53329,53330,53331,53333,53334,53335,53337,53338,53339,53340,53341,53342,53343,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53358,53359,null,null,null,null,null,null,53361,53362,53363,53365,53366,53367,53368,53369,53370,53371,53374,53375,53376,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,45535,45544,45545,45548,45552,45561,45563,45565,45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,45910,45912,45915,45916,45918,45919,45924,45925,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53414,53415,53417,53418,53419,53421,53422,53423,53424,53425,53426,null,null,null,null,null,null,53427,53430,53432,53434,53435,53436,53437,53438,53439,53442,53443,53445,53446,53447,53450,53451,53452,53453,53454,53455,53458,53462,53463,53464,53465,53466,null,null,null,null,null,null,53467,53470,53471,53473,53474,53475,53477,53478,53479,53480,53481,53482,53483,53486,53490,53491,53492,53493,53494,53495,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,45927,45929,45931,45934,45936,45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,53509,53510,53511,53512,53513,53514,53515,53516,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,null,null,null,null,null,null,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53554,53555,53557,53558,53559,53561,53563,53564,53565,53566,null,null,null,null,null,null,53567,53570,53574,53575,53576,53577,53578,53579,53582,53583,53585,53586,53587,53589,53590,53591,53592,53593,53594,53595,53598,53600,53602,53603,53604,53605,53606,53607,53609,53610,53611,53613,46400,46401,46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,46999,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53629,53630,53631,53632,53633,53634,53635,53637,53638,53639,53641,53642,null,null,null,null,null,null,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53666,53667,53669,53670,53671,null,null,null,null,null,null,53673,53674,53675,53676,53677,53678,53679,53682,53684,53686,53687,53688,53689,53691,53693,53694,53695,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,47000,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,47452,47456,47464,47465,53712,53713,53714,53715,53716,53717,53718,53719,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,null,null,null,null,null,null,53739,53740,53741,53742,53743,53744,53745,53746,53747,53749,53750,53751,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,null,null,null,null,null,null,53768,53770,53771,53772,53773,53774,53775,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,47467,47469,47476,47477,47480,47484,47492,47493,47495,47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,47803,47805,47812,47816,47832,47833,47868,53802,53803,53806,53807,53809,53810,53811,53813,53814,53815,53816,53817,53818,53819,53822,53824,53826,53827,53828,53829,53830,53831,53833,53834,53835,53836,null,null,null,null,null,null,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53853,53854,53855,53856,53857,53858,53859,53861,53862,53863,53864,null,null,null,null,null,null,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53890,53891,53893,53894,53895,53897,53898,53899,53900,47872,47876,47885,47887,47889,47896,47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,53901,53902,53903,53906,53907,53908,53910,53911,53912,53913,53914,53915,53917,53918,53919,53921,53922,53923,53925,53926,53927,53928,53929,53930,53931,53933,null,null,null,null,null,null,53934,53935,53936,53938,53939,53940,53941,53942,53943,53946,53947,53949,53950,53953,53955,53956,53957,53958,53959,53962,53964,53965,53966,53967,53968,53969,null,null,null,null,null,null,53970,53971,53973,53974,53975,53977,53978,53979,53981,53982,53983,53984,53985,53986,53987,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54002,54003,54005,54006,54007,54009,54010,48281,48282,48288,48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,54011,54012,54013,54014,54015,54018,54020,54022,54023,54024,54025,54026,54027,54031,54033,54034,54035,54037,54039,54040,54041,54042,54043,54046,54050,54051,null,null,null,null,null,null,54052,54054,54055,54058,54059,54061,54062,54063,54065,54066,54067,54068,54069,54070,54071,54074,54078,54079,54080,54081,54082,54083,54086,54087,54088,54089,null,null,null,null,null,null,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,49372,49373,49380,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54142,54143,54145,54146,54147,54149,54150,54151,null,null,null,null,null,null,54152,54153,54154,54155,54158,54162,54163,54164,54165,54166,54167,54170,54171,54173,54174,54175,54177,54178,54179,54180,54181,54182,54183,54186,54188,54190,null,null,null,null,null,null,54191,54192,54193,54194,54195,54197,54198,54199,54201,54202,54203,54205,54206,54207,54208,54209,54210,54211,54214,54215,54218,54219,54220,54221,54222,54223,54225,54226,54227,54228,54229,54230,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,49695,49696,49704,49705,49707,49709,54231,54233,54234,54235,54236,54237,54238,54239,54240,54242,54244,54245,54246,54247,54248,54249,54250,54251,54254,54255,54257,54258,54259,54261,54262,54263,null,null,null,null,null,null,54264,54265,54266,54267,54270,54272,54274,54275,54276,54277,54278,54279,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,null,null,null,null,null,null,54295,54296,54297,54298,54299,54300,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,49711,49713,49714,49716,49736,49744,49745,49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,50157,50164,50165,50168,50184,50192,50212,50220,50224,54328,54329,54330,54331,54332,54333,54334,54335,54337,54338,54339,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,null,null,null,null,null,null,54356,54357,54358,54359,54360,54361,54362,54363,54365,54366,54367,54369,54370,54371,54373,54374,54375,54376,54377,54378,54379,54380,54382,54384,54385,54386,null,null,null,null,null,null,54387,54388,54389,54390,54391,54394,54395,54397,54398,54401,54403,54404,54405,54406,54407,54410,54412,54414,54415,54416,54417,54418,54419,54421,54422,54423,54424,54425,54426,54427,54428,54429,50228,50236,50237,50248,50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,null,null,null,null,null,null,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54477,54478,54479,54481,54482,54483,54485,null,null,null,null,null,null,54486,54487,54488,54489,54490,54491,54493,54494,54496,54497,54498,54499,54500,54501,54502,54503,54505,54506,54507,54509,54510,54511,54513,54514,54515,54516,54517,54518,54519,54521,54522,54524,50640,50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,50913,50920,54526,54527,54528,54529,54530,54531,54533,54534,54535,54537,54538,54539,54541,54542,54543,54544,54545,54546,54547,54550,54552,54553,54554,54555,54556,54557,null,null,null,null,null,null,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,null,null,null,null,null,null,54584,54585,54586,54587,54590,54591,54593,54594,54595,54597,54598,54599,54600,54601,54602,54603,54606,54608,54610,54611,54612,54613,54614,54615,54618,54619,54621,54622,54623,54625,54626,54627,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,51200,51201,51204,51208,51210,54628,54630,54631,54634,54636,54638,54639,54640,54641,54642,54643,54646,54647,54649,54650,54651,54653,54654,54655,54656,54657,54658,54659,54662,54666,54667,null,null,null,null,null,null,54668,54669,54670,54671,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54694,54695,null,null,null,null,null,null,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,51216,51217,51219,51221,51222,51228,51229,51232,51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,51649,51652,51655,51656,51658,51664,51665,51667,54730,54731,54733,54734,54735,54737,54739,54740,54741,54742,54743,54746,54748,54750,54751,54752,54753,54754,54755,54758,54759,54761,54762,54763,54765,54766,null,null,null,null,null,null,54767,54768,54769,54770,54771,54774,54776,54778,54779,54780,54781,54782,54783,54786,54787,54789,54790,54791,54793,54794,54795,54796,54797,54798,54799,54802,null,null,null,null,null,null,54806,54807,54808,54809,54810,54811,54813,54814,54815,54817,54818,54819,54821,54822,54823,54824,54825,54826,54827,54828,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54842,54843,51669,51670,51673,51674,51676,51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,51992,52000,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,54845,54846,54847,54849,54850,54851,54852,54854,54855,54858,54860,54862,54863,54864,54866,54867,54870,54871,54873,54874,54875,54877,54878,54879,54880,54881,null,null,null,null,null,null,54882,54883,54884,54885,54886,54888,54890,54891,54892,54893,54894,54895,54898,54899,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,null,null,null,null,null,null,54913,54914,54916,54918,54919,54920,54921,54922,54923,54926,54927,54929,54930,54931,54933,54934,54935,54936,54937,54938,54939,54940,54942,54944,54946,54947,54948,54949,54950,54951,54953,54954,52284,52285,52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,52789,54955,54957,54958,54959,54961,54962,54963,54964,54965,54966,54967,54968,54970,54972,54973,54974,54975,54976,54977,54978,54979,54982,54983,54985,54986,54987,null,null,null,null,null,null,54989,54990,54991,54992,54994,54995,54997,54998,55000,55002,55003,55004,55005,55006,55007,55009,55010,55011,55013,55014,55015,55017,55018,55019,55020,55021,null,null,null,null,null,null,55022,55023,55025,55026,55027,55028,55030,55031,55032,55033,55034,55035,55038,55039,55041,55042,55043,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55058,55059,55060,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,52984,52985,52992,52993,52996,53000,53008,53009,53011,53013,53020,53024,53028,53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,53300,53301,53304,53308,55061,55062,55063,55066,55067,55069,55070,55071,55073,55074,55075,55076,55077,55078,55079,55082,55084,55086,55087,55088,55089,55090,55091,55094,55095,55097,null,null,null,null,null,null,55098,55099,55101,55102,55103,55104,55105,55106,55107,55109,55110,55112,55114,55115,55116,55117,55118,55119,55122,55123,55125,55130,55131,55132,55133,55134,null,null,null,null,null,null,55135,55138,55140,55142,55143,55144,55146,55147,55149,55150,55151,55153,55154,55155,55157,55158,55159,55160,55161,55162,55163,55166,55167,55168,55170,55171,55172,55173,55174,55175,55178,55179,53316,53317,53319,53321,53328,53332,53336,53344,53356,53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,53812,53820,53821,53823,53825,53832,53852,55181,55182,55183,55185,55186,55187,55188,55189,55190,55191,55194,55196,55198,55199,55200,55201,55202,55203,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,53860,53888,53889,53892,53896,53904,53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,53960,53961,53963,53972,53976,53980,53988,53989,54000,54001,54004,54008,54016,54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54280,54301,54336,54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,55193,55195,55197,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20285,20339,20551,20729,21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21283,23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,21138,27298,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,23622,24760,25106,26690,26800,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26856,28330,30028,30328,30926,31293,31995,32363,32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,34467,36002,38799,20018,23521,25096,26524,29916,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31185,33747,35463,35506,36328,36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21312,21475,21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,36020,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,24524,25216,26071,26083,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26398,26399,26462,26827,26820,27231,27450,27683,27773,27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,31048,31098,31637,32000,32186,32648,32774,32813,32908,35352,35663,35912,36215,37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,26976,28275,63778,30007,63779,63780,63781,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32013,63782,63783,34930,22218,23064,63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20025,20150,20294,21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,63835,30313,32645,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,36706,38722,24976,25088,25891,28451,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29001,29833,32244,32879,34030,36646,36899,37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,20698,23534,24278,26009,29134,30274,30637,32842,34044,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36988,39719,40845,22744,23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31435,31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,33180,33707,37000,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,40629,28357,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,20497,21006,21563,21839,25991,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27766,32010,32011,32862,34442,38272,38639,21247,27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,36820,38930,39151,21187,25300,25765,28196,28497,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30332,36299,37297,37474,39662,39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30887,34327,38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,23142,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,31807,32566,33104,33105,33178,33344,33433,33705,35331,36000,36070,36091,36212,36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26000,26503,27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,31875,32203,32737,32933,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,33086,33218,33778,34586,35048,35513,35692,36027,37145,38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,39164,39391,40605,21066,63849,26388,63850,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20632,21034,23665,25955,27733,29642,29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32997,33298,34223,35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,23744,24101,24833,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,25100,34899,36848,37477,23815,23847,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23913,29791,33181,34664,28629,25342,32722,35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,36805,22833,23460,23526,24713,23529,23563,24515,27777,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63858,28145,28683,29978,33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27387,32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,22914,63874,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,28814,28976,29744,33398,33490,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63910,38331,39653,40573,26308,63911,29121,33865,63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,63924,20034,20522,63925,21000,21473,26355,27757,28618,29450,30591,31330,33454,34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,63929,25034,25942,26111,26212,26791,27738,28595,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28879,29100,29522,31613,34568,35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31368,31407,32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,34131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,29232,29503,29783,33489,34945,36677,36960,63942,38498,39000,40219,26376,36234,37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,27943,63946,28216,63947,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28641,29494,29495,63948,29788,30001,63949,30290,63950,63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,30691,32681,33380,34191,34811,34915,35516,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,35696,37291,20108,20197,20234,63965,63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63991,63992,63993,20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,27583,27656,28593,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29006,29728,30000,30008,30033,30322,31564,31627,31661,31686,32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,37336,37478,37580,37664,38662,38742,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38748,38914,40718,21046,21137,21884,22564,24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,24939,26837,28121,29742,31278,32066,32156,32305,33131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36394,36405,37758,37912,20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21675,22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,32221,36655,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,37319,37365,20874,26613,31574,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36012,20932,22971,24765,34389,20508,63999,21076,23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,33729,35531,38737,39894,64000,21059,26367,28053,28399,32224,35558,36910,36958,39636,21021,21119,21736,24980,25220,25307,26786,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26898,26970,27189,28818,28966,30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,22684,25277,25512,26894,27000,27166,28267,30394,31179,33467,33833,35535,36264,36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36101,21462,21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,35351,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,29923,36009,36774,37393,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38442,20843,21485,25420,20329,21764,24726,25943,27803,28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,29922,31080,34920,35961,39111,39108,39491,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21697,31263,26963,35575,35914,39080,39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,64008,64009,38917,20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,27194,28779,30069,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,25928,25989,26313,26783,28045,28102,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29243,32948,37237,39501,20399,20505,21402,21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,26342,29081,29113,29114,29351,31143,31232,32690,35440,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], - "gb18030":[19970,19972,19973,19974,19983,19986,19991,19999,20000,20001,20003,20006,20009,20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,21979,21982,21984,21986,21991,21993,21997,21998,22000,22001,22004,22006,22008,22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24006,24007,24008,24009,24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28998,28999,29000,29001,29003,29005,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,58850,58851,58852,12288,65281,65282,65283,65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,234,593,7743,324,328,505,609,59337,59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,27686,20133,23475,39559,37219,25000,37039,38889,21547,28085,23506,20989,21898,32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,30000,29980,24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,34996,34997,34998,35000,35001,35002,35003,35005,35006,35007,35008,35011,35012,35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,21310,36188,21350,21347,20994,21000,21006,21037,21043,21055,21056,21068,21086,21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34000,34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,28049,28015,28062,28064,27998,28051,28052,27996,28000,28028,28003,28186,28103,28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,26297,36980,36989,36994,37000,36995,37003,24400,24407,24406,24408,23611,21675,23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,23000,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27000,26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,32951,32999,33000,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26000,40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,58000,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565], - "gb18030-ranges":[[0,128],[36,165],[38,169],[45,178],[50,184],[81,216],[89,226],[95,235],[96,238],[100,244],[103,248],[104,251],[105,253],[109,258],[126,276],[133,284],[148,300],[172,325],[175,329],[179,334],[208,364],[306,463],[307,465],[308,467],[309,469],[310,471],[311,473],[312,475],[313,477],[341,506],[428,594],[443,610],[544,712],[545,716],[558,730],[741,930],[742,938],[749,962],[750,970],[805,1026],[819,1104],[820,1106],[7922,8209],[7924,8215],[7925,8218],[7927,8222],[7934,8231],[7943,8241],[7944,8244],[7945,8246],[7950,8252],[8062,8365],[8148,8452],[8149,8454],[8152,8458],[8164,8471],[8174,8482],[8236,8556],[8240,8570],[8262,8596],[8264,8602],[8374,8713],[8380,8720],[8381,8722],[8384,8726],[8388,8731],[8390,8737],[8392,8740],[8393,8742],[8394,8748],[8396,8751],[8401,8760],[8406,8766],[8416,8777],[8419,8781],[8424,8787],[8437,8802],[8439,8808],[8445,8816],[8482,8854],[8485,8858],[8496,8870],[8521,8896],[8603,8979],[8936,9322],[8946,9372],[9046,9548],[9050,9588],[9063,9616],[9066,9622],[9076,9634],[9092,9652],[9100,9662],[9108,9672],[9111,9676],[9113,9680],[9131,9702],[9162,9735],[9164,9738],[9218,9793],[9219,9795],[11329,11906],[11331,11909],[11334,11913],[11336,11917],[11346,11928],[11361,11944],[11363,11947],[11366,11951],[11370,11956],[11372,11960],[11375,11964],[11389,11979],[11682,12284],[11686,12292],[11687,12312],[11692,12319],[11694,12330],[11714,12351],[11716,12436],[11723,12447],[11725,12535],[11730,12543],[11736,12586],[11982,12842],[11989,12850],[12102,12964],[12336,13200],[12348,13215],[12350,13218],[12384,13253],[12393,13263],[12395,13267],[12397,13270],[12510,13384],[12553,13428],[12851,13727],[12962,13839],[12973,13851],[13738,14617],[13823,14703],[13919,14801],[13933,14816],[14080,14964],[14298,15183],[14585,15471],[14698,15585],[15583,16471],[15847,16736],[16318,17208],[16434,17325],[16438,17330],[16481,17374],[16729,17623],[17102,17997],[17122,18018],[17315,18212],[17320,18218],[17402,18301],[17418,18318],[17859,18760],[17909,18811],[17911,18814],[17915,18820],[17916,18823],[17936,18844],[17939,18848],[17961,18872],[18664,19576],[18703,19620],[18814,19738],[18962,19887],[19043,40870],[33469,59244],[33470,59336],[33471,59367],[33484,59413],[33485,59417],[33490,59423],[33497,59431],[33501,59437],[33505,59443],[33513,59452],[33520,59460],[33536,59478],[33550,59493],[37845,63789],[37921,63866],[37948,63894],[38029,63976],[38038,63986],[38064,64016],[38065,64018],[38066,64021],[38069,64025],[38075,64034],[38076,64037],[38078,64042],[39108,65074],[39109,65093],[39113,65107],[39114,65112],[39115,65127],[39116,65132],[39265,65375],[39394,65510],[189000,65536]], - "jis0208":[12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,8213,8208,65295,65340,65374,8741,65372,8230,8229,8216,8217,8220,8221,65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,65291,65293,177,215,247,65309,8800,65308,65310,8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,65504,65505,65285,65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,null,null,null,null,null,null,null,null,null,null,null,8712,8715,8838,8839,8834,8835,8746,8745,null,null,null,null,null,null,null,null,8743,8744,65506,8658,8660,8704,8707,null,null,null,null,null,null,null,null,null,null,null,8736,8869,8978,8706,8711,8801,8786,8810,8811,8730,8765,8733,8757,8747,8748,null,null,null,null,null,null,null,8491,8240,9839,9837,9834,8224,8225,182,null,null,null,null,9711,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,null,null,null,null,null,null,null,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,null,null,null,null,null,null,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,null,null,null,null,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,13129,13076,13090,13133,13080,13095,13059,13110,13137,13143,13069,13094,13091,13099,13130,13115,13212,13213,13214,13198,13199,13252,13217,null,null,null,null,null,null,null,null,13179,12317,12319,8470,13261,8481,12964,12965,12966,12967,12968,12849,12850,12857,13182,13181,13180,8786,8801,8747,8750,8721,8730,8869,8736,8735,8895,8757,8745,8746,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20124,21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21000,33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,23721,32747,36107,38593,38929,38996,39000,20225,20238,21361,21916,22120,22522,22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32000,24509,35215,35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,36578,39003,28857,20253,27583,28593,30000,38651,20814,21520,22581,22615,22956,23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,21329,21542,22915,24199,24444,24754,25161,25209,25259,26000,27604,27852,30130,30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,33178,33433,35676,36000,36070,36212,38428,38468,20398,25771,27494,33310,33889,34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,26906,26915,26913,26822,27001,26999,26972,27000,26987,26964,27006,26990,26937,26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,33983,33951,34009,33997,33979,34010,34000,33985,33990,34006,33953,34081,34047,34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38000,38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,65506,65508,65287,65282,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,65506,65508,65287,65282,12849,8470,8481,8757,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], - "jis0212":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,728,711,184,729,733,175,731,730,65374,900,901,null,null,null,null,null,null,null,null,161,166,191,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,186,170,169,174,8482,164,8470,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,902,904,905,906,938,null,908,null,910,939,null,911,null,null,null,null,940,941,942,943,970,912,972,962,973,971,944,974,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,198,272,null,294,null,306,null,321,319,null,330,216,338,null,358,222,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,230,273,240,295,305,307,312,322,320,329,331,248,339,223,359,254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,193,192,196,194,258,461,256,260,197,195,262,264,268,199,266,270,201,200,203,202,282,278,274,280,null,284,286,290,288,292,205,204,207,206,463,304,298,302,296,308,310,313,317,315,323,327,325,209,211,210,214,212,465,336,332,213,340,344,342,346,348,352,350,356,354,218,217,220,219,364,467,368,362,370,366,360,471,475,473,469,372,221,376,374,377,381,379,null,null,null,null,null,null,null,225,224,228,226,259,462,257,261,229,227,263,265,269,231,267,271,233,232,235,234,283,279,275,281,501,285,287,null,289,293,237,236,239,238,464,null,299,303,297,309,311,314,318,316,324,328,326,241,243,242,246,244,466,337,333,245,341,345,343,347,349,353,351,357,355,250,249,252,251,365,468,369,363,371,367,361,472,476,474,470,373,253,255,375,378,382,380,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19970,19972,19973,19980,19986,19999,20003,20004,20008,20011,20014,20015,20016,20021,20032,20033,20036,20039,20049,20058,20060,20067,20072,20073,20084,20085,20089,20095,20109,20118,20119,20125,20143,20153,20163,20176,20186,20187,20192,20193,20194,20200,20207,20209,20211,20213,20221,20222,20223,20224,20226,20227,20232,20235,20236,20242,20245,20246,20247,20249,20270,20273,20320,20275,20277,20279,20281,20283,20286,20288,20290,20296,20297,20299,20300,20306,20308,20310,20312,20319,20323,20330,20332,20334,20337,20343,20344,20345,20346,20349,20350,20353,20354,20356,20357,20361,20362,20364,20366,20368,20370,20371,20372,20375,20377,20378,20382,20383,20402,20407,20409,20411,20412,20413,20414,20416,20417,20421,20422,20424,20425,20427,20428,20429,20431,20434,20444,20448,20450,20464,20466,20476,20477,20479,20480,20481,20484,20487,20490,20492,20494,20496,20499,20503,20504,20507,20508,20509,20510,20514,20519,20526,20528,20530,20531,20533,20544,20545,20546,20549,20550,20554,20556,20558,20561,20562,20563,20567,20569,20575,20576,20578,20579,20582,20583,20586,20589,20592,20593,20539,20609,20611,20612,20614,20618,20622,20623,20624,20626,20627,20628,20630,20635,20636,20638,20639,20640,20641,20642,20650,20655,20656,20665,20666,20669,20672,20675,20676,20679,20684,20686,20688,20691,20692,20696,20700,20701,20703,20706,20708,20710,20712,20713,20719,20721,20726,20730,20734,20739,20742,20743,20744,20747,20748,20749,20750,20722,20752,20759,20761,20763,20764,20765,20766,20771,20775,20776,20780,20781,20783,20785,20787,20788,20789,20792,20793,20802,20810,20815,20819,20821,20823,20824,20831,20836,20838,20862,20867,20868,20875,20878,20888,20893,20897,20899,20909,20920,20922,20924,20926,20927,20930,20936,20943,20945,20946,20947,20949,20952,20958,20962,20965,20974,20978,20979,20980,20983,20993,20994,20997,21010,21011,21013,21014,21016,21026,21032,21041,21042,21045,21052,21061,21065,21077,21079,21080,21082,21084,21087,21088,21089,21094,21102,21111,21112,21113,21120,21122,21125,21130,21132,21139,21141,21142,21143,21144,21146,21148,21156,21157,21158,21159,21167,21168,21174,21175,21176,21178,21179,21181,21184,21188,21190,21192,21196,21199,21201,21204,21206,21211,21212,21217,21221,21224,21225,21226,21228,21232,21233,21236,21238,21239,21248,21251,21258,21259,21260,21265,21267,21272,21275,21276,21278,21279,21285,21287,21288,21289,21291,21292,21293,21296,21298,21301,21308,21309,21310,21314,21324,21323,21337,21339,21345,21347,21349,21356,21357,21362,21369,21374,21379,21383,21384,21390,21395,21396,21401,21405,21409,21412,21418,21419,21423,21426,21428,21429,21431,21432,21434,21437,21440,21445,21455,21458,21459,21461,21466,21469,21470,21472,21478,21479,21493,21506,21523,21530,21537,21543,21544,21546,21551,21553,21556,21557,21571,21572,21575,21581,21583,21598,21602,21604,21606,21607,21609,21611,21613,21614,21620,21631,21633,21635,21637,21640,21641,21645,21649,21653,21654,21660,21663,21665,21670,21671,21673,21674,21677,21678,21681,21687,21689,21690,21691,21695,21702,21706,21709,21710,21728,21738,21740,21743,21750,21756,21758,21759,21760,21761,21765,21768,21769,21772,21773,21774,21781,21802,21803,21810,21813,21814,21819,21820,21821,21825,21831,21833,21834,21837,21840,21841,21848,21850,21851,21854,21856,21857,21860,21862,21887,21889,21890,21894,21896,21902,21903,21905,21906,21907,21908,21911,21923,21924,21933,21938,21951,21953,21955,21958,21961,21963,21964,21966,21969,21970,21971,21975,21976,21979,21982,21986,21993,22006,22015,22021,22024,22026,22029,22030,22031,22032,22033,22034,22041,22060,22064,22067,22069,22071,22073,22075,22076,22077,22079,22080,22081,22083,22084,22086,22089,22091,22093,22095,22100,22110,22112,22113,22114,22115,22118,22121,22125,22127,22129,22130,22133,22148,22149,22152,22155,22156,22165,22169,22170,22173,22174,22175,22182,22183,22184,22185,22187,22188,22189,22193,22195,22199,22206,22213,22217,22218,22219,22223,22224,22220,22221,22233,22236,22237,22239,22241,22244,22245,22246,22247,22248,22257,22251,22253,22262,22263,22273,22274,22279,22282,22284,22289,22293,22298,22299,22301,22304,22306,22307,22308,22309,22313,22314,22316,22318,22319,22323,22324,22333,22334,22335,22341,22342,22348,22349,22354,22370,22373,22375,22376,22379,22381,22382,22383,22384,22385,22387,22388,22389,22391,22393,22394,22395,22396,22398,22401,22403,22412,22420,22423,22425,22426,22428,22429,22430,22431,22433,22421,22439,22440,22441,22444,22456,22461,22471,22472,22476,22479,22485,22493,22494,22500,22502,22503,22505,22509,22512,22517,22518,22520,22525,22526,22527,22531,22532,22536,22537,22497,22540,22541,22555,22558,22559,22560,22566,22567,22573,22578,22585,22591,22601,22604,22605,22607,22608,22613,22623,22625,22628,22631,22632,22648,22652,22655,22656,22657,22663,22664,22665,22666,22668,22669,22671,22672,22676,22678,22685,22688,22689,22690,22694,22697,22705,22706,22724,22716,22722,22728,22733,22734,22736,22738,22740,22742,22746,22749,22753,22754,22761,22771,22789,22790,22795,22796,22802,22803,22804,34369,22813,22817,22819,22820,22824,22831,22832,22835,22837,22838,22847,22851,22854,22866,22867,22873,22875,22877,22878,22879,22881,22883,22891,22893,22895,22898,22901,22902,22905,22907,22908,22923,22924,22926,22930,22933,22935,22943,22948,22951,22957,22958,22959,22960,22963,22967,22970,22972,22977,22979,22980,22984,22986,22989,22994,23005,23006,23007,23011,23012,23015,23022,23023,23025,23026,23028,23031,23040,23044,23052,23053,23054,23058,23059,23070,23075,23076,23079,23080,23082,23085,23088,23108,23109,23111,23112,23116,23120,23125,23134,23139,23141,23143,23149,23159,23162,23163,23166,23179,23184,23187,23190,23193,23196,23198,23199,23200,23202,23207,23212,23217,23218,23219,23221,23224,23226,23227,23231,23236,23238,23240,23247,23258,23260,23264,23269,23274,23278,23285,23286,23293,23296,23297,23304,23319,23348,23321,23323,23325,23329,23333,23341,23352,23361,23371,23372,23378,23382,23390,23400,23406,23407,23420,23421,23422,23423,23425,23428,23430,23434,23438,23440,23441,23443,23444,23446,23464,23465,23468,23469,23471,23473,23474,23479,23482,23484,23488,23489,23501,23503,23510,23511,23512,23513,23514,23520,23535,23537,23540,23549,23564,23575,23582,23583,23587,23590,23593,23595,23596,23598,23600,23602,23605,23606,23641,23642,23644,23650,23651,23655,23656,23657,23661,23664,23668,23669,23674,23675,23676,23677,23687,23688,23690,23695,23698,23709,23711,23712,23714,23715,23718,23722,23730,23732,23733,23738,23753,23755,23762,23773,23767,23790,23793,23794,23796,23809,23814,23821,23826,23851,23843,23844,23846,23847,23857,23860,23865,23869,23871,23874,23875,23878,23880,23893,23889,23897,23882,23903,23904,23905,23906,23908,23914,23917,23920,23929,23930,23934,23935,23937,23939,23944,23946,23954,23955,23956,23957,23961,23963,23967,23968,23975,23979,23984,23988,23992,23993,24003,24007,24011,24016,24014,24024,24025,24032,24036,24041,24056,24057,24064,24071,24077,24082,24084,24085,24088,24095,24096,24110,24104,24114,24117,24126,24139,24144,24137,24145,24150,24152,24155,24156,24158,24168,24170,24171,24172,24173,24174,24176,24192,24203,24206,24226,24228,24229,24232,24234,24236,24241,24243,24253,24254,24255,24262,24268,24267,24270,24273,24274,24276,24277,24284,24286,24293,24299,24322,24326,24327,24328,24334,24345,24348,24349,24353,24354,24355,24356,24360,24363,24364,24366,24368,24372,24374,24379,24381,24383,24384,24388,24389,24391,24397,24400,24404,24408,24411,24416,24419,24420,24423,24431,24434,24436,24437,24440,24442,24445,24446,24457,24461,24463,24470,24476,24477,24482,24487,24491,24484,24492,24495,24496,24497,24504,24516,24519,24520,24521,24523,24528,24529,24530,24531,24532,24542,24545,24546,24552,24553,24554,24556,24557,24558,24559,24562,24563,24566,24570,24572,24583,24586,24589,24595,24596,24599,24600,24602,24607,24612,24621,24627,24629,24640,24647,24648,24649,24652,24657,24660,24662,24663,24669,24673,24679,24689,24702,24703,24706,24710,24712,24714,24718,24721,24723,24725,24728,24733,24734,24738,24740,24741,24744,24752,24753,24759,24763,24766,24770,24772,24776,24777,24778,24779,24782,24783,24788,24789,24793,24795,24797,24798,24802,24805,24818,24821,24824,24828,24829,24834,24839,24842,24844,24848,24849,24850,24851,24852,24854,24855,24857,24860,24862,24866,24874,24875,24880,24881,24885,24886,24887,24889,24897,24901,24902,24905,24926,24928,24940,24946,24952,24955,24956,24959,24960,24961,24963,24964,24971,24973,24978,24979,24983,24984,24988,24989,24991,24992,24997,25000,25002,25005,25016,25017,25020,25024,25025,25026,25038,25039,25045,25052,25053,25054,25055,25057,25058,25063,25065,25061,25068,25069,25071,25089,25091,25092,25095,25107,25109,25116,25120,25122,25123,25127,25129,25131,25145,25149,25154,25155,25156,25158,25164,25168,25169,25170,25172,25174,25178,25180,25188,25197,25199,25203,25210,25213,25229,25230,25231,25232,25254,25256,25267,25270,25271,25274,25278,25279,25284,25294,25301,25302,25306,25322,25330,25332,25340,25341,25347,25348,25354,25355,25357,25360,25363,25366,25368,25385,25386,25389,25397,25398,25401,25404,25409,25410,25411,25412,25414,25418,25419,25422,25426,25427,25428,25432,25435,25445,25446,25452,25453,25457,25460,25461,25464,25468,25469,25471,25474,25476,25479,25482,25488,25492,25493,25497,25498,25502,25508,25510,25517,25518,25519,25533,25537,25541,25544,25550,25553,25555,25556,25557,25564,25568,25573,25578,25580,25586,25587,25589,25592,25593,25609,25610,25616,25618,25620,25624,25630,25632,25634,25636,25637,25641,25642,25647,25648,25653,25661,25663,25675,25679,25681,25682,25683,25684,25690,25691,25692,25693,25695,25696,25697,25699,25709,25715,25716,25723,25725,25733,25735,25743,25744,25745,25752,25753,25755,25757,25759,25761,25763,25766,25768,25772,25779,25789,25790,25791,25796,25801,25802,25803,25804,25806,25808,25809,25813,25815,25828,25829,25833,25834,25837,25840,25845,25847,25851,25855,25857,25860,25864,25865,25866,25871,25875,25876,25878,25881,25883,25886,25887,25890,25894,25897,25902,25905,25914,25916,25917,25923,25927,25929,25936,25938,25940,25951,25952,25959,25963,25978,25981,25985,25989,25994,26002,26005,26008,26013,26016,26019,26022,26030,26034,26035,26036,26047,26050,26056,26057,26062,26064,26068,26070,26072,26079,26096,26098,26100,26101,26105,26110,26111,26112,26116,26120,26121,26125,26129,26130,26133,26134,26141,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26161,26163,26169,26167,26176,26181,26182,26186,26188,26193,26190,26199,26200,26201,26203,26204,26208,26209,26363,26218,26219,26220,26238,26227,26229,26239,26231,26232,26233,26235,26240,26236,26251,26252,26253,26256,26258,26265,26266,26267,26268,26271,26272,26276,26285,26289,26290,26293,26299,26303,26304,26306,26307,26312,26316,26318,26319,26324,26331,26335,26344,26347,26348,26350,26362,26373,26375,26382,26387,26393,26396,26400,26402,26419,26430,26437,26439,26440,26444,26452,26453,26461,26470,26476,26478,26484,26486,26491,26497,26500,26510,26511,26513,26515,26518,26520,26521,26523,26544,26545,26546,26549,26555,26556,26557,26617,26560,26562,26563,26565,26568,26569,26578,26583,26585,26588,26593,26598,26608,26610,26614,26615,26706,26644,26649,26653,26655,26664,26663,26668,26669,26671,26672,26673,26675,26683,26687,26692,26693,26698,26700,26709,26711,26712,26715,26731,26734,26735,26736,26737,26738,26741,26745,26746,26747,26748,26754,26756,26758,26760,26774,26776,26778,26780,26785,26787,26789,26793,26794,26798,26802,26811,26821,26824,26828,26831,26832,26833,26835,26838,26841,26844,26845,26853,26856,26858,26859,26860,26861,26864,26865,26869,26870,26875,26876,26877,26886,26889,26890,26896,26897,26899,26902,26903,26929,26931,26933,26936,26939,26946,26949,26953,26958,26967,26971,26979,26980,26981,26982,26984,26985,26988,26992,26993,26994,27002,27003,27007,27008,27021,27026,27030,27032,27041,27045,27046,27048,27051,27053,27055,27063,27064,27066,27068,27077,27080,27089,27094,27095,27106,27109,27118,27119,27121,27123,27125,27134,27136,27137,27139,27151,27153,27157,27162,27165,27168,27172,27176,27184,27186,27188,27191,27195,27198,27199,27205,27206,27209,27210,27214,27216,27217,27218,27221,27222,27227,27236,27239,27242,27249,27251,27262,27265,27267,27270,27271,27273,27275,27281,27291,27293,27294,27295,27301,27307,27311,27312,27313,27316,27325,27326,27327,27334,27337,27336,27340,27344,27348,27349,27350,27356,27357,27364,27367,27372,27376,27377,27378,27388,27389,27394,27395,27398,27399,27401,27407,27408,27409,27415,27419,27422,27428,27432,27435,27436,27439,27445,27446,27451,27455,27462,27466,27469,27474,27478,27480,27485,27488,27495,27499,27502,27504,27509,27517,27518,27522,27525,27543,27547,27551,27552,27554,27555,27560,27561,27564,27565,27566,27568,27576,27577,27581,27582,27587,27588,27593,27596,27606,27610,27617,27619,27622,27623,27630,27633,27639,27641,27647,27650,27652,27653,27657,27661,27662,27664,27666,27673,27679,27686,27687,27688,27692,27694,27699,27701,27702,27706,27707,27711,27722,27723,27725,27727,27730,27732,27737,27739,27740,27755,27757,27759,27764,27766,27768,27769,27771,27781,27782,27783,27785,27796,27797,27799,27800,27804,27807,27824,27826,27828,27842,27846,27853,27855,27856,27857,27858,27860,27862,27866,27868,27872,27879,27881,27883,27884,27886,27890,27892,27908,27911,27914,27918,27919,27921,27923,27930,27942,27943,27944,27751,27950,27951,27953,27961,27964,27967,27991,27998,27999,28001,28005,28007,28015,28016,28028,28034,28039,28049,28050,28052,28054,28055,28056,28074,28076,28084,28087,28089,28093,28095,28100,28104,28106,28110,28111,28118,28123,28125,28127,28128,28130,28133,28137,28143,28144,28148,28150,28156,28160,28164,28190,28194,28199,28210,28214,28217,28219,28220,28228,28229,28232,28233,28235,28239,28241,28242,28243,28244,28247,28252,28253,28254,28258,28259,28264,28275,28283,28285,28301,28307,28313,28320,28327,28333,28334,28337,28339,28347,28351,28352,28353,28355,28359,28360,28362,28365,28366,28367,28395,28397,28398,28409,28411,28413,28420,28424,28426,28428,28429,28438,28440,28442,28443,28454,28457,28458,28463,28464,28467,28470,28475,28476,28461,28495,28497,28498,28499,28503,28505,28506,28509,28510,28513,28514,28520,28524,28541,28542,28547,28551,28552,28555,28556,28557,28560,28562,28563,28564,28566,28570,28575,28576,28581,28582,28583,28584,28590,28591,28592,28597,28598,28604,28613,28615,28616,28618,28634,28638,28648,28649,28656,28661,28665,28668,28669,28672,28677,28678,28679,28685,28695,28704,28707,28719,28724,28727,28729,28732,28739,28740,28744,28745,28746,28747,28756,28757,28765,28766,28750,28772,28773,28780,28782,28789,28790,28798,28801,28805,28806,28820,28821,28822,28823,28824,28827,28836,28843,28848,28849,28852,28855,28874,28881,28883,28884,28885,28886,28888,28892,28900,28922,28931,28932,28933,28934,28935,28939,28940,28943,28958,28960,28971,28973,28975,28976,28977,28984,28993,28997,28998,28999,29002,29003,29008,29010,29015,29018,29020,29022,29024,29032,29049,29056,29061,29063,29068,29074,29082,29083,29088,29090,29103,29104,29106,29107,29114,29119,29120,29121,29124,29131,29132,29139,29142,29145,29146,29148,29176,29182,29184,29191,29192,29193,29203,29207,29210,29213,29215,29220,29227,29231,29236,29240,29241,29249,29250,29251,29253,29262,29263,29264,29267,29269,29270,29274,29276,29278,29280,29283,29288,29291,29294,29295,29297,29303,29304,29307,29308,29311,29316,29321,29325,29326,29331,29339,29352,29357,29358,29361,29364,29374,29377,29383,29385,29388,29397,29398,29400,29407,29413,29427,29428,29434,29435,29438,29442,29444,29445,29447,29451,29453,29458,29459,29464,29465,29470,29474,29476,29479,29480,29484,29489,29490,29493,29498,29499,29501,29507,29517,29520,29522,29526,29528,29533,29534,29535,29536,29542,29543,29545,29547,29548,29550,29551,29553,29559,29561,29564,29568,29569,29571,29573,29574,29582,29584,29587,29589,29591,29592,29596,29598,29599,29600,29602,29605,29606,29610,29611,29613,29621,29623,29625,29628,29629,29631,29637,29638,29641,29643,29644,29647,29650,29651,29654,29657,29661,29665,29667,29670,29671,29673,29684,29685,29687,29689,29690,29691,29693,29695,29696,29697,29700,29703,29706,29713,29722,29723,29732,29734,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29753,29760,29763,29764,29766,29767,29771,29773,29777,29778,29783,29789,29794,29798,29799,29800,29803,29805,29806,29809,29810,29824,29825,29829,29830,29831,29833,29839,29840,29841,29842,29848,29849,29850,29852,29855,29856,29857,29859,29862,29864,29865,29866,29867,29870,29871,29873,29874,29877,29881,29883,29887,29896,29897,29900,29904,29907,29912,29914,29915,29918,29919,29924,29928,29930,29931,29935,29940,29946,29947,29948,29951,29958,29970,29974,29975,29984,29985,29988,29991,29993,29994,29999,30006,30009,30013,30014,30015,30016,30019,30023,30024,30030,30032,30034,30039,30046,30047,30049,30063,30065,30073,30074,30075,30076,30077,30078,30081,30085,30096,30098,30099,30101,30105,30108,30114,30116,30132,30138,30143,30144,30145,30148,30150,30156,30158,30159,30167,30172,30175,30176,30177,30180,30183,30188,30190,30191,30193,30201,30208,30210,30211,30212,30215,30216,30218,30220,30223,30226,30227,30229,30230,30233,30235,30236,30237,30238,30243,30245,30246,30249,30253,30258,30259,30261,30264,30265,30266,30268,30282,30272,30273,30275,30276,30277,30281,30283,30293,30297,30303,30308,30309,30317,30318,30319,30321,30324,30337,30341,30348,30349,30357,30363,30364,30365,30367,30368,30370,30371,30372,30373,30374,30375,30376,30378,30381,30397,30401,30405,30409,30411,30412,30414,30420,30425,30432,30438,30440,30444,30448,30449,30454,30457,30460,30464,30470,30474,30478,30482,30484,30485,30487,30489,30490,30492,30498,30504,30509,30510,30511,30516,30517,30518,30521,30525,30526,30530,30533,30534,30538,30541,30542,30543,30546,30550,30551,30556,30558,30559,30560,30562,30564,30567,30570,30572,30576,30578,30579,30580,30586,30589,30592,30596,30604,30605,30612,30613,30614,30618,30623,30626,30631,30634,30638,30639,30641,30645,30654,30659,30665,30673,30674,30677,30681,30686,30687,30688,30692,30694,30698,30700,30704,30705,30708,30712,30715,30725,30726,30729,30733,30734,30737,30749,30753,30754,30755,30765,30766,30768,30773,30775,30787,30788,30791,30792,30796,30798,30802,30812,30814,30816,30817,30819,30820,30824,30826,30830,30842,30846,30858,30863,30868,30872,30881,30877,30878,30879,30884,30888,30892,30893,30896,30897,30898,30899,30907,30909,30911,30919,30920,30921,30924,30926,30930,30931,30933,30934,30948,30939,30943,30944,30945,30950,30954,30962,30963,30976,30966,30967,30970,30971,30975,30982,30988,30992,31002,31004,31006,31007,31008,31013,31015,31017,31021,31025,31028,31029,31035,31037,31039,31044,31045,31046,31050,31051,31055,31057,31060,31064,31067,31068,31079,31081,31083,31090,31097,31099,31100,31102,31115,31116,31121,31123,31124,31125,31126,31128,31131,31132,31137,31144,31145,31147,31151,31153,31156,31160,31163,31170,31172,31175,31176,31178,31183,31188,31190,31194,31197,31198,31200,31202,31205,31210,31211,31213,31217,31224,31228,31234,31235,31239,31241,31242,31244,31249,31253,31259,31262,31265,31271,31275,31277,31279,31280,31284,31285,31288,31289,31290,31300,31301,31303,31304,31308,31317,31318,31321,31324,31325,31327,31328,31333,31335,31338,31341,31349,31352,31358,31360,31362,31365,31366,31370,31371,31376,31377,31380,31390,31392,31395,31404,31411,31413,31417,31419,31420,31430,31433,31436,31438,31441,31451,31464,31465,31467,31468,31473,31476,31483,31485,31486,31495,31508,31519,31523,31527,31529,31530,31531,31533,31534,31535,31536,31537,31540,31549,31551,31552,31553,31559,31566,31573,31584,31588,31590,31593,31594,31597,31599,31602,31603,31607,31620,31625,31630,31632,31633,31638,31643,31646,31648,31653,31660,31663,31664,31666,31669,31670,31674,31675,31676,31677,31682,31685,31688,31690,31700,31702,31703,31705,31706,31707,31720,31722,31730,31732,31733,31736,31737,31738,31740,31742,31745,31746,31747,31748,31750,31753,31755,31756,31758,31759,31769,31771,31776,31781,31782,31784,31788,31793,31795,31796,31798,31801,31802,31814,31818,31829,31825,31826,31827,31833,31834,31835,31836,31837,31838,31841,31843,31847,31849,31853,31854,31856,31858,31865,31868,31869,31878,31879,31887,31892,31902,31904,31910,31920,31926,31927,31930,31931,31932,31935,31940,31943,31944,31945,31949,31951,31955,31956,31957,31959,31961,31962,31965,31974,31977,31979,31989,32003,32007,32008,32009,32015,32017,32018,32019,32022,32029,32030,32035,32038,32042,32045,32049,32060,32061,32062,32064,32065,32071,32072,32077,32081,32083,32087,32089,32090,32092,32093,32101,32103,32106,32112,32120,32122,32123,32127,32129,32130,32131,32133,32134,32136,32139,32140,32141,32145,32150,32151,32157,32158,32166,32167,32170,32179,32182,32183,32185,32194,32195,32196,32197,32198,32204,32205,32206,32215,32217,32256,32226,32229,32230,32234,32235,32237,32241,32245,32246,32249,32250,32264,32272,32273,32277,32279,32284,32285,32288,32295,32296,32300,32301,32303,32307,32310,32319,32324,32325,32327,32334,32336,32338,32344,32351,32353,32354,32357,32363,32366,32367,32371,32376,32382,32385,32390,32391,32394,32397,32401,32405,32408,32410,32413,32414,32572,32571,32573,32574,32575,32579,32580,32583,32591,32594,32595,32603,32604,32605,32609,32611,32612,32613,32614,32621,32625,32637,32638,32639,32640,32651,32653,32655,32656,32657,32662,32663,32668,32673,32674,32678,32682,32685,32692,32700,32703,32704,32707,32712,32718,32719,32731,32735,32739,32741,32744,32748,32750,32751,32754,32762,32765,32766,32767,32775,32776,32778,32781,32782,32783,32785,32787,32788,32790,32797,32798,32799,32800,32804,32806,32812,32814,32816,32820,32821,32823,32825,32826,32828,32830,32832,32836,32864,32868,32870,32877,32881,32885,32897,32904,32910,32924,32926,32934,32935,32939,32952,32953,32968,32973,32975,32978,32980,32981,32983,32984,32992,33005,33006,33008,33010,33011,33014,33017,33018,33022,33027,33035,33046,33047,33048,33052,33054,33056,33060,33063,33068,33072,33077,33082,33084,33093,33095,33098,33100,33106,33111,33120,33121,33127,33128,33129,33133,33135,33143,33153,33168,33156,33157,33158,33163,33166,33174,33176,33179,33182,33186,33198,33202,33204,33211,33227,33219,33221,33226,33230,33231,33237,33239,33243,33245,33246,33249,33252,33259,33260,33264,33265,33266,33269,33270,33272,33273,33277,33279,33280,33283,33295,33299,33300,33305,33306,33309,33313,33314,33320,33330,33332,33338,33347,33348,33349,33350,33355,33358,33359,33361,33366,33372,33376,33379,33383,33389,33396,33403,33405,33407,33408,33409,33411,33412,33415,33417,33418,33422,33425,33428,33430,33432,33434,33435,33440,33441,33443,33444,33447,33448,33449,33450,33454,33456,33458,33460,33463,33466,33468,33470,33471,33478,33488,33493,33498,33504,33506,33508,33512,33514,33517,33519,33526,33527,33533,33534,33536,33537,33543,33544,33546,33547,33620,33563,33565,33566,33567,33569,33570,33580,33581,33582,33584,33587,33591,33594,33596,33597,33602,33603,33604,33607,33613,33614,33617,33621,33622,33623,33648,33656,33661,33663,33664,33666,33668,33670,33677,33682,33684,33685,33688,33689,33691,33692,33693,33702,33703,33705,33708,33726,33727,33728,33735,33737,33743,33744,33745,33748,33757,33619,33768,33770,33782,33784,33785,33788,33793,33798,33802,33807,33809,33813,33817,33709,33839,33849,33861,33863,33864,33866,33869,33871,33873,33874,33878,33880,33881,33882,33884,33888,33892,33893,33895,33898,33904,33907,33908,33910,33912,33916,33917,33921,33925,33938,33939,33941,33950,33958,33960,33961,33962,33967,33969,33972,33978,33981,33982,33984,33986,33991,33992,33996,33999,34003,34012,34023,34026,34031,34032,34033,34034,34039,34098,34042,34043,34045,34050,34051,34055,34060,34062,34064,34076,34078,34082,34083,34084,34085,34087,34090,34091,34095,34099,34100,34102,34111,34118,34127,34128,34129,34130,34131,34134,34137,34140,34141,34142,34143,34144,34145,34146,34148,34155,34159,34169,34170,34171,34173,34175,34177,34181,34182,34185,34187,34188,34191,34195,34200,34205,34207,34208,34210,34213,34215,34228,34230,34231,34232,34236,34237,34238,34239,34242,34247,34250,34251,34254,34221,34264,34266,34271,34272,34278,34280,34285,34291,34294,34300,34303,34304,34308,34309,34317,34318,34320,34321,34322,34328,34329,34331,34334,34337,34343,34345,34358,34360,34362,34364,34365,34368,34370,34374,34386,34387,34390,34391,34392,34393,34397,34400,34401,34402,34403,34404,34409,34412,34415,34421,34422,34423,34426,34445,34449,34454,34456,34458,34460,34465,34470,34471,34472,34477,34481,34483,34484,34485,34487,34488,34489,34495,34496,34497,34499,34501,34513,34514,34517,34519,34522,34524,34528,34531,34533,34535,34440,34554,34556,34557,34564,34565,34567,34571,34574,34575,34576,34579,34580,34585,34590,34591,34593,34595,34600,34606,34607,34609,34610,34617,34618,34620,34621,34622,34624,34627,34629,34637,34648,34653,34657,34660,34661,34671,34673,34674,34683,34691,34692,34693,34694,34695,34696,34697,34699,34700,34704,34707,34709,34711,34712,34713,34718,34720,34723,34727,34732,34733,34734,34737,34741,34750,34751,34753,34760,34761,34762,34766,34773,34774,34777,34778,34780,34783,34786,34787,34788,34794,34795,34797,34801,34803,34808,34810,34815,34817,34819,34822,34825,34826,34827,34832,34841,34834,34835,34836,34840,34842,34843,34844,34846,34847,34856,34861,34862,34864,34866,34869,34874,34876,34881,34883,34885,34888,34889,34890,34891,34894,34897,34901,34902,34904,34906,34908,34911,34912,34916,34921,34929,34937,34939,34944,34968,34970,34971,34972,34975,34976,34984,34986,35002,35005,35006,35008,35018,35019,35020,35021,35022,35025,35026,35027,35035,35038,35047,35055,35056,35057,35061,35063,35073,35078,35085,35086,35087,35093,35094,35096,35097,35098,35100,35104,35110,35111,35112,35120,35121,35122,35125,35129,35130,35134,35136,35138,35141,35142,35145,35151,35154,35159,35162,35163,35164,35169,35170,35171,35179,35182,35184,35187,35189,35194,35195,35196,35197,35209,35213,35216,35220,35221,35227,35228,35231,35232,35237,35248,35252,35253,35254,35255,35260,35284,35285,35286,35287,35288,35301,35305,35307,35309,35313,35315,35318,35321,35325,35327,35332,35333,35335,35343,35345,35346,35348,35349,35358,35360,35362,35364,35366,35371,35372,35375,35381,35383,35389,35390,35392,35395,35397,35399,35401,35405,35406,35411,35414,35415,35416,35420,35421,35425,35429,35431,35445,35446,35447,35449,35450,35451,35454,35455,35456,35459,35462,35467,35471,35472,35474,35478,35479,35481,35487,35495,35497,35502,35503,35507,35510,35511,35515,35518,35523,35526,35528,35529,35530,35537,35539,35540,35541,35543,35549,35551,35564,35568,35572,35573,35574,35580,35583,35589,35590,35595,35601,35612,35614,35615,35594,35629,35632,35639,35644,35650,35651,35652,35653,35654,35656,35666,35667,35668,35673,35661,35678,35683,35693,35702,35704,35705,35708,35710,35713,35716,35717,35723,35725,35727,35732,35733,35740,35742,35743,35896,35897,35901,35902,35909,35911,35913,35915,35919,35921,35923,35924,35927,35928,35931,35933,35929,35939,35940,35942,35944,35945,35949,35955,35957,35958,35963,35966,35974,35975,35979,35984,35986,35987,35993,35995,35996,36004,36025,36026,36037,36038,36041,36043,36047,36054,36053,36057,36061,36065,36072,36076,36079,36080,36082,36085,36087,36088,36094,36095,36097,36099,36105,36114,36119,36123,36197,36201,36204,36206,36223,36226,36228,36232,36237,36240,36241,36245,36254,36255,36256,36262,36267,36268,36271,36274,36277,36279,36281,36283,36288,36293,36294,36295,36296,36298,36302,36305,36308,36309,36311,36313,36324,36325,36327,36332,36336,36284,36337,36338,36340,36349,36353,36356,36357,36358,36363,36369,36372,36374,36384,36385,36386,36387,36390,36391,36401,36403,36406,36407,36408,36409,36413,36416,36417,36427,36429,36430,36431,36436,36443,36444,36445,36446,36449,36450,36457,36460,36461,36463,36464,36465,36473,36474,36475,36482,36483,36489,36496,36498,36501,36506,36507,36509,36510,36514,36519,36521,36525,36526,36531,36533,36538,36539,36544,36545,36547,36548,36551,36559,36561,36564,36572,36584,36590,36592,36593,36599,36601,36602,36589,36608,36610,36615,36616,36623,36624,36630,36631,36632,36638,36640,36641,36643,36645,36647,36648,36652,36653,36654,36660,36661,36662,36663,36666,36672,36673,36675,36679,36687,36689,36690,36691,36692,36693,36696,36701,36702,36709,36765,36768,36769,36772,36773,36774,36789,36790,36792,36798,36800,36801,36806,36810,36811,36813,36816,36818,36819,36821,36832,36835,36836,36840,36846,36849,36853,36854,36859,36862,36866,36868,36872,36876,36888,36891,36904,36905,36911,36906,36908,36909,36915,36916,36919,36927,36931,36932,36940,36955,36957,36962,36966,36967,36972,36976,36980,36985,36997,37000,37003,37004,37006,37008,37013,37015,37016,37017,37019,37024,37025,37026,37029,37040,37042,37043,37044,37046,37053,37068,37054,37059,37060,37061,37063,37064,37077,37079,37080,37081,37084,37085,37087,37093,37074,37110,37099,37103,37104,37108,37118,37119,37120,37124,37125,37126,37128,37133,37136,37140,37142,37143,37144,37146,37148,37150,37152,37157,37154,37155,37159,37161,37166,37167,37169,37172,37174,37175,37177,37178,37180,37181,37187,37191,37192,37199,37203,37207,37209,37210,37211,37217,37220,37223,37229,37236,37241,37242,37243,37249,37251,37253,37254,37258,37262,37265,37267,37268,37269,37272,37278,37281,37286,37288,37292,37293,37294,37296,37297,37298,37299,37302,37307,37308,37309,37311,37314,37315,37317,37331,37332,37335,37337,37338,37342,37348,37349,37353,37354,37356,37357,37358,37359,37360,37361,37367,37369,37371,37373,37376,37377,37380,37381,37382,37383,37385,37386,37388,37392,37394,37395,37398,37400,37404,37405,37411,37412,37413,37414,37416,37422,37423,37424,37427,37429,37430,37432,37433,37434,37436,37438,37440,37442,37443,37446,37447,37450,37453,37454,37455,37457,37464,37465,37468,37469,37472,37473,37477,37479,37480,37481,37486,37487,37488,37493,37494,37495,37496,37497,37499,37500,37501,37503,37512,37513,37514,37517,37518,37522,37527,37529,37535,37536,37540,37541,37543,37544,37547,37551,37554,37558,37560,37562,37563,37564,37565,37567,37568,37569,37570,37571,37573,37574,37575,37576,37579,37580,37581,37582,37584,37587,37589,37591,37592,37593,37596,37597,37599,37600,37601,37603,37605,37607,37608,37612,37614,37616,37625,37627,37631,37632,37634,37640,37645,37649,37652,37653,37660,37661,37662,37663,37665,37668,37669,37671,37673,37674,37683,37684,37686,37687,37703,37704,37705,37712,37713,37714,37717,37719,37720,37722,37726,37732,37733,37735,37737,37738,37741,37743,37744,37745,37747,37748,37750,37754,37757,37759,37760,37761,37762,37768,37770,37771,37773,37775,37778,37781,37784,37787,37790,37793,37795,37796,37798,37800,37803,37812,37813,37814,37818,37801,37825,37828,37829,37830,37831,37833,37834,37835,37836,37837,37843,37849,37852,37854,37855,37858,37862,37863,37881,37879,37880,37882,37883,37885,37889,37890,37892,37896,37897,37901,37902,37903,37909,37910,37911,37919,37934,37935,37937,37938,37939,37940,37947,37951,37949,37955,37957,37960,37962,37964,37973,37977,37980,37983,37985,37987,37992,37995,37997,37998,37999,38001,38002,38020,38019,38264,38265,38270,38276,38280,38284,38285,38286,38301,38302,38303,38305,38310,38313,38315,38316,38324,38326,38330,38333,38335,38342,38344,38345,38347,38352,38353,38354,38355,38361,38362,38365,38366,38367,38368,38372,38374,38429,38430,38434,38436,38437,38438,38444,38449,38451,38455,38456,38457,38458,38460,38461,38465,38482,38484,38486,38487,38488,38497,38510,38516,38523,38524,38526,38527,38529,38530,38531,38532,38537,38545,38550,38554,38557,38559,38564,38565,38566,38569,38574,38575,38579,38586,38602,38610,23986,38616,38618,38621,38622,38623,38633,38639,38641,38650,38658,38659,38661,38665,38682,38683,38685,38689,38690,38691,38696,38705,38707,38721,38723,38730,38734,38735,38741,38743,38744,38746,38747,38755,38759,38762,38766,38771,38774,38775,38776,38779,38781,38783,38784,38793,38805,38806,38807,38809,38810,38814,38815,38818,38828,38830,38833,38834,38837,38838,38840,38841,38842,38844,38846,38847,38849,38852,38853,38855,38857,38858,38860,38861,38862,38864,38865,38868,38871,38872,38873,38877,38878,38880,38875,38881,38884,38895,38897,38900,38903,38904,38906,38919,38922,38937,38925,38926,38932,38934,38940,38942,38944,38947,38950,38955,38958,38959,38960,38962,38963,38965,38949,38974,38980,38983,38986,38993,38994,38995,38998,38999,39001,39002,39010,39011,39013,39014,39018,39020,39083,39085,39086,39088,39092,39095,39096,39098,39099,39103,39106,39109,39112,39116,39137,39139,39141,39142,39143,39146,39155,39158,39170,39175,39176,39185,39189,39190,39191,39194,39195,39196,39199,39202,39206,39207,39211,39217,39218,39219,39220,39221,39225,39226,39227,39228,39232,39233,39238,39239,39240,39245,39246,39252,39256,39257,39259,39260,39262,39263,39264,39323,39325,39327,39334,39344,39345,39346,39349,39353,39354,39357,39359,39363,39369,39379,39380,39385,39386,39388,39390,39399,39402,39403,39404,39408,39412,39413,39417,39421,39422,39426,39427,39428,39435,39436,39440,39441,39446,39454,39456,39458,39459,39460,39463,39469,39470,39475,39477,39478,39480,39495,39489,39492,39498,39499,39500,39502,39505,39508,39510,39517,39594,39596,39598,39599,39602,39604,39605,39606,39609,39611,39614,39615,39617,39619,39622,39624,39630,39632,39634,39637,39638,39639,39643,39644,39648,39652,39653,39655,39657,39660,39666,39667,39669,39673,39674,39677,39679,39680,39681,39682,39683,39684,39685,39688,39689,39691,39692,39693,39694,39696,39698,39702,39705,39707,39708,39712,39718,39723,39725,39731,39732,39733,39735,39737,39738,39741,39752,39755,39756,39765,39766,39767,39771,39774,39777,39779,39781,39782,39784,39786,39787,39788,39789,39790,39795,39797,39799,39800,39801,39807,39808,39812,39813,39814,39815,39817,39818,39819,39821,39823,39824,39828,39834,39837,39838,39846,39847,39849,39852,39856,39857,39858,39863,39864,39867,39868,39870,39871,39873,39879,39880,39886,39888,39895,39896,39901,39903,39909,39911,39914,39915,39919,39923,39927,39928,39929,39930,39933,39935,39936,39938,39947,39951,39953,39958,39960,39961,39962,39964,39966,39970,39971,39974,39975,39976,39977,39978,39985,39989,39990,39991,39997,40001,40003,40004,40005,40009,40010,40014,40015,40016,40019,40020,40022,40024,40027,40029,40030,40031,40035,40041,40042,40028,40043,40040,40046,40048,40050,40053,40055,40059,40166,40178,40183,40185,40203,40194,40209,40215,40216,40220,40221,40222,40239,40240,40242,40243,40244,40250,40252,40261,40253,40258,40259,40263,40266,40275,40276,40287,40291,40290,40293,40297,40298,40299,40304,40310,40311,40315,40316,40318,40323,40324,40326,40330,40333,40334,40338,40339,40341,40342,40343,40344,40353,40362,40364,40366,40369,40373,40377,40380,40383,40387,40391,40393,40394,40404,40405,40406,40407,40410,40414,40415,40416,40421,40423,40425,40427,40430,40432,40435,40436,40446,40458,40450,40455,40462,40464,40465,40466,40469,40470,40473,40476,40477,40570,40571,40572,40576,40578,40579,40580,40581,40583,40590,40591,40598,40600,40603,40606,40612,40616,40620,40622,40623,40624,40627,40628,40629,40646,40648,40651,40661,40671,40676,40679,40684,40685,40686,40688,40689,40690,40693,40696,40703,40706,40707,40713,40719,40720,40721,40722,40724,40726,40727,40729,40730,40731,40735,40738,40742,40746,40747,40751,40753,40754,40756,40759,40761,40762,40764,40765,40767,40769,40771,40772,40773,40774,40775,40787,40789,40790,40791,40792,40794,40797,40798,40808,40809,40813,40814,40815,40816,40817,40819,40821,40826,40829,40847,40848,40849,40850,40852,40854,40855,40862,40865,40866,40867,40869,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], - "ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160], - "iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], - "iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729], - "iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729], - "iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119], - "iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null], - "iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], - "iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], - "iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312], - "iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217], - "iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255], - "iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], - "iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255], - "koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], - "koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], - "macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711], - "windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null], - "windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], - "windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103], - "windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], - "windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], - "windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255], - "windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], - "windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746], - "windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729], - "windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255], - "x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364] - }; - - // For strict environments where `this` inside the global scope - // is `undefined`, take a pure object instead - }(this || {})); - },{}],110:[function(require,module,exports){ - // This is free and unencumbered software released into the public domain. - // See LICENSE.md for more information. + /* eslint-disable complexity */ /** - * @fileoverview Global |this| required for resolving indexes in node. - * @suppress {globalThis} + * Mocks available features in the specified global namespace. + * + * @param {*} _global Namespace to mock (e.g. `window`) + * @returns {FakeTimers} */ - (function(global) { + function withGlobal(_global) { + const userAgent = _global.navigator && _global.navigator.userAgent; + const isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1; + const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint + const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs + const NOOP = function () { + return undefined; + }; + const NOOP_ARRAY = function () { + return []; + }; + const timeoutResult = _global.setTimeout(NOOP, 0); + const addTimerReturnsObject = typeof timeoutResult === "object"; + const hrtimePresent = + _global.process && typeof _global.process.hrtime === "function"; + const hrtimeBigintPresent = + hrtimePresent && typeof _global.process.hrtime.bigint === "function"; + const nextTickPresent = + _global.process && typeof _global.process.nextTick === "function"; + const utilPromisify = _global.process && require("util").promisify; + const performancePresent = + _global.performance && typeof _global.performance.now === "function"; + const hasPerformancePrototype = + _global.Performance && + (typeof _global.Performance).match(/^(function|object)$/); + const hasPerformanceConstructorPrototype = + _global.performance && + _global.performance.constructor && + _global.performance.constructor.prototype; + const queueMicrotaskPresent = _global.hasOwnProperty("queueMicrotask"); + const requestAnimationFramePresent = + _global.requestAnimationFrame && + typeof _global.requestAnimationFrame === "function"; + const cancelAnimationFramePresent = + _global.cancelAnimationFrame && + typeof _global.cancelAnimationFrame === "function"; + const requestIdleCallbackPresent = + _global.requestIdleCallback && + typeof _global.requestIdleCallback === "function"; + const cancelIdleCallbackPresent = + _global.cancelIdleCallback && + typeof _global.cancelIdleCallback === "function"; + const setImmediatePresent = + _global.setImmediate && typeof _global.setImmediate === "function"; - // If we're in node require encoding-indexes and attach it to the global. - if (typeof module !== "undefined" && module.exports && - !global["encoding-indexes"]) { - global["encoding-indexes"] = - require("./encoding-indexes.js")["encoding-indexes"]; - } + // Make properties writable in IE, as per + // https://www.adequatelygood.com/Replacing-setTimeout-Globally.html + /* eslint-disable no-self-assign */ + if (isRunningInIE) { + _global.setTimeout = _global.setTimeout; + _global.clearTimeout = _global.clearTimeout; + _global.setInterval = _global.setInterval; + _global.clearInterval = _global.clearInterval; + _global.Date = _global.Date; + } - // - // Utilities - // + // setImmediate is not a standard function + // avoid adding the prop to the window object if not present + if (setImmediatePresent) { + _global.setImmediate = _global.setImmediate; + _global.clearImmediate = _global.clearImmediate; + } + /* eslint-enable no-self-assign */ - /** - * @param {number} a The number to test. - * @param {number} min The minimum value in the range, inclusive. - * @param {number} max The maximum value in the range, inclusive. - * @return {boolean} True if a >= min and a <= max. - */ - function inRange(a, min, max) { - return min <= a && a <= max; - } + _global.clearTimeout(timeoutResult); - /** - * @param {!Array.<*>} array The array to check. - * @param {*} item The item to look for in the array. - * @return {boolean} True if the item appears in the array. - */ - function includes(array, item) { - return array.indexOf(item) !== -1; - } + const NativeDate = _global.Date; + let uniqueTimerId = idCounterStart; - var floor = Math.floor; + /** + * @param {number} num + * @returns {boolean} + */ + function isNumberFinite(num) { + if (Number.isFinite) { + return Number.isFinite(num); + } - /** - * @param {*} o - * @return {Object} - */ - function ToDictionary(o) { - if (o === undefined) return {}; - if (o === Object(o)) return o; - throw TypeError('Could not convert argument to dictionary'); - } + return isFinite(num); + } - /** - * @param {string} string Input string of UTF-16 code units. - * @return {!Array.} Code points. - */ - function stringToCodePoints(string) { - // https://heycam.github.io/webidl/#dfn-obtain-unicode + let isNearInfiniteLimit = false; - // 1. Let S be the DOMString value. - var s = String(string); + /** + * @param {Clock} clock + * @param {number} i + */ + function checkIsNearInfiniteLimit(clock, i) { + if (clock.loopLimit && i === clock.loopLimit - 1) { + isNearInfiniteLimit = true; + } + } - // 2. Let n be the length of S. - var n = s.length; + /** + * + */ + function resetIsNearInfiniteLimit() { + isNearInfiniteLimit = false; + } - // 3. Initialize i to 0. - var i = 0; + /** + * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into + * number of milliseconds. This is used to support human-readable strings passed + * to clock.tick() + * + * @param {string} str + * @returns {number} + */ + function parseTime(str) { + if (!str) { + return 0; + } - // 4. Initialize U to be an empty sequence of Unicode characters. - var u = []; + const strings = str.split(":"); + const l = strings.length; + let i = l; + let ms = 0; + let parsed; - // 5. While i < n: - while (i < n) { + if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { + throw new Error( + "tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits" + ); + } - // 1. Let c be the code unit in S at index i. - var c = s.charCodeAt(i); + while (i--) { + parsed = parseInt(strings[i], 10); - // 2. Depending on the value of c: + if (parsed >= 60) { + throw new Error(`Invalid time ${str}`); + } - // c < 0xD800 or c > 0xDFFF - if (c < 0xD800 || c > 0xDFFF) { - // Append to U the Unicode character with code point c. - u.push(c); - } - - // 0xDC00 ≤ c ≤ 0xDFFF - else if (0xDC00 <= c && c <= 0xDFFF) { - // Append to U a U+FFFD REPLACEMENT CHARACTER. - u.push(0xFFFD); - } - - // 0xD800 ≤ c ≤ 0xDBFF - else if (0xD800 <= c && c <= 0xDBFF) { - // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT - // CHARACTER. - if (i === n - 1) { - u.push(0xFFFD); + ms += parsed * Math.pow(60, l - i - 1); } - // 2. Otherwise, i < n−1: - else { - // 1. Let d be the code unit in S at index i+1. - var d = s.charCodeAt(i + 1); - - // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: - if (0xDC00 <= d && d <= 0xDFFF) { - // 1. Let a be c & 0x3FF. - var a = c & 0x3FF; - // 2. Let b be d & 0x3FF. - var b = d & 0x3FF; + return ms * 1000; + } - // 3. Append to U the Unicode character with code point - // 2^16+2^10*a+b. - u.push(0x10000 + (a << 10) + b); + /** + * Get the decimal part of the millisecond value as nanoseconds + * + * @param {number} msFloat the number of milliseconds + * @returns {number} an integer number of nanoseconds in the range [0,1e6) + * + * Example: nanoRemainer(123.456789) -> 456789 + */ + function nanoRemainder(msFloat) { + const modulo = 1e6; + const remainder = (msFloat * 1e6) % modulo; + const positiveRemainder = + remainder < 0 ? remainder + modulo : remainder; - // 4. Set i to i+1. - i += 1; - } + return Math.floor(positiveRemainder); + } - // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a - // U+FFFD REPLACEMENT CHARACTER. - else { - u.push(0xFFFD); - } + /** + * Used to grok the `now` parameter to createClock. + * + * @param {Date|number} epoch the system time + * @returns {number} + */ + function getEpoch(epoch) { + if (!epoch) { + return 0; } - } - - // 3. Set i to i+1. - i += 1; + if (typeof epoch.getTime === "function") { + return epoch.getTime(); + } + if (typeof epoch === "number") { + return epoch; + } + throw new TypeError("now should be milliseconds since UNIX epoch"); } - // 6. Return U. - return u; - } - - /** - * @param {!Array.} code_points Array of code points. - * @return {string} string String of UTF-16 code units. - */ - function codePointsToString(code_points) { - var s = ''; - for (var i = 0; i < code_points.length; ++i) { - var cp = code_points[i]; - if (cp <= 0xFFFF) { - s += String.fromCharCode(cp); - } else { - cp -= 0x10000; - s += String.fromCharCode((cp >> 10) + 0xD800, - (cp & 0x3FF) + 0xDC00); - } + /** + * @param {number} from + * @param {number} to + * @param {Timer} timer + * @returns {boolean} + */ + function inRange(from, to, timer) { + return timer && timer.callAt >= from && timer.callAt <= to; } - return s; - } + /** + * @param {Clock} clock + * @param {Timer} job + */ + function getInfiniteLoopError(clock, job) { + const infiniteLoopError = new Error( + `Aborting after running ${clock.loopLimit} timers, assuming an infinite loop!` + ); - // - // Implementation of Encoding specification - // https://encoding.spec.whatwg.org/ - // + if (!job.error) { + return infiniteLoopError; + } - // - // 4. Terminology - // + // pattern never matched in Node + const computedTargetPattern = /target\.*[<|(|[].*?[>|\]|)]\s*/; + let clockMethodPattern = new RegExp( + String(Object.keys(clock).join("|")) + ); - /** - * An ASCII byte is a byte in the range 0x00 to 0x7F, inclusive. - * @param {number} a The number to test. - * @return {boolean} True if a is in the range 0x00 to 0x7F, inclusive. - */ - function isASCIIByte(a) { - return 0x00 <= a && a <= 0x7F; - } + if (addTimerReturnsObject) { + // node.js environment + clockMethodPattern = new RegExp( + `\\s+at (Object\\.)?(?:${Object.keys(clock).join("|")})\\s+` + ); + } - /** - * An ASCII code point is a code point in the range U+0000 to - * U+007F, inclusive. - */ - var isASCIICodePoint = isASCIIByte; + let matchedLineIndex = -1; + job.error.stack.split("\n").some(function (line, i) { + // If we've matched a computed target line (e.g. setTimeout) then we + // don't need to look any further. Return true to stop iterating. + const matchedComputedTarget = line.match(computedTargetPattern); + /* istanbul ignore if */ + if (matchedComputedTarget) { + matchedLineIndex = i; + return true; + } + // If we've matched a clock method line, then there may still be + // others further down the trace. Return false to keep iterating. + const matchedClockMethod = line.match(clockMethodPattern); + if (matchedClockMethod) { + matchedLineIndex = i; + return false; + } - /** - * End-of-stream is a special token that signifies no more tokens - * are in the stream. - * @const - */ var end_of_stream = -1; + // If we haven't matched anything on this line, but we matched + // previously and set the matched line index, then we can stop. + // If we haven't matched previously, then we should keep iterating. + return matchedLineIndex >= 0; + }); - /** - * A stream represents an ordered sequence of tokens. - * - * @constructor - * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide - * the stream. - */ - function Stream(tokens) { - /** @type {!Array.} */ - this.tokens = [].slice.call(tokens); - // Reversed as push/pop is more efficient than shift/unshift. - this.tokens.reverse(); - } + const stack = `${infiniteLoopError}\n${job.type || "Microtask"} - ${ + job.func.name || "anonymous" + }\n${job.error.stack + .split("\n") + .slice(matchedLineIndex + 1) + .join("\n")}`; - Stream.prototype = { - /** - * @return {boolean} True if end-of-stream has been hit. - */ - endOfStream: function() { - return !this.tokens.length; - }, + try { + Object.defineProperty(infiniteLoopError, "stack", { + value: stack, + }); + } catch (e) { + // noop + } - /** - * When a token is read from a stream, the first token in the - * stream must be returned and subsequently removed, and - * end-of-stream must be returned otherwise. - * - * @return {number} Get the next token from the stream, or - * end_of_stream. - */ - read: function() { - if (!this.tokens.length) - return end_of_stream; - return this.tokens.pop(); - }, + return infiniteLoopError; + } /** - * When one or more tokens are prepended to a stream, those tokens - * must be inserted, in given order, before the first token in the - * stream. - * - * @param {(number|!Array.)} token The token(s) to prepend to the - * stream. + * @param {Date} target + * @param {Date} source + * @returns {Date} the target after modifications */ - prepend: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.push(tokens.pop()); - } else { - this.tokens.push(token); - } - }, + function mirrorDateProperties(target, source) { + let prop; + for (prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } - /** - * When one or more tokens are pushed to a stream, those tokens - * must be inserted, in given order, after the last token in the - * stream. - * - * @param {(number|!Array.)} token The tokens(s) to push to the - * stream. - */ - push: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.unshift(tokens.shift()); - } else { - this.tokens.unshift(token); - } - } - }; + // set special now implementation + if (source.now) { + target.now = function now() { + return target.clock.now; + }; + } else { + delete target.now; + } - // - // 5. Encodings - // + // set special toSource implementation + if (source.toSource) { + target.toSource = function toSource() { + return source.toSource(); + }; + } else { + delete target.toSource; + } - // 5.1 Encoders and decoders + // set special toString implementation + target.toString = function toString() { + return source.toString(); + }; - /** @const */ - var finished = -1; + target.prototype = source.prototype; + target.parse = source.parse; + target.UTC = source.UTC; + target.prototype.toUTCString = source.prototype.toUTCString; + target.isFake = true; - /** - * @param {boolean} fatal If true, decoding errors raise an exception. - * @param {number=} opt_code_point Override the standard fallback code point. - * @return {number} The code point to insert on a decoding error. - */ - function decoderError(fatal, opt_code_point) { - if (fatal) - throw TypeError('Decoder error'); - return opt_code_point || 0xFFFD; - } + return target; + } - /** - * @param {number} code_point The code point that could not be encoded. - * @return {number} Always throws, no value is actually returned. - */ - function encoderError(code_point) { - throw TypeError('The code point ' + code_point + ' could not be encoded.'); - } + //eslint-disable-next-line jsdoc/require-jsdoc + function createDate() { + /** + * @param {number} year + * @param {number} month + * @param {number} date + * @param {number} hour + * @param {number} minute + * @param {number} second + * @param {number} ms + * @returns {Date} + */ + function ClockDate(year, month, date, hour, minute, second, ms) { + // the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2. + // This remains so in the 10th edition of 2019 as well. + if (!(this instanceof ClockDate)) { + return new NativeDate(ClockDate.clock.now).toString(); + } - // 5.2 Names and labels + // if Date is called as a constructor with 'new' keyword + // Defensive and verbose to avoid potential harm in passing + // explicit undefined when user does not pass argument + switch (arguments.length) { + case 0: + return new NativeDate(ClockDate.clock.now); + case 1: + return new NativeDate(year); + case 2: + return new NativeDate(year, month); + case 3: + return new NativeDate(year, month, date); + case 4: + return new NativeDate(year, month, date, hour); + case 5: + return new NativeDate(year, month, date, hour, minute); + case 6: + return new NativeDate( + year, + month, + date, + hour, + minute, + second + ); + default: + return new NativeDate( + year, + month, + date, + hour, + minute, + second, + ms + ); + } + } - // TODO: Define @typedef for Encoding: {name:string,labels:Array.} - // https://github.com/google/closure-compiler/issues/247 + return mirrorDateProperties(ClockDate, NativeDate); + } - /** - * @param {string} label The encoding label. - * @return {?{name:string,labels:Array.}} - */ - function getEncoding(label) { - // 1. Remove any leading and trailing ASCII whitespace from label. - label = String(label).trim().toLowerCase(); + //eslint-disable-next-line jsdoc/require-jsdoc + function enqueueJob(clock, job) { + // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob + if (!clock.jobs) { + clock.jobs = []; + } + clock.jobs.push(job); + } - // 2. If label is an ASCII case-insensitive match for any of the - // labels listed in the table below, return the corresponding - // encoding, and failure otherwise. - if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) { - return label_to_encoding[label]; + //eslint-disable-next-line jsdoc/require-jsdoc + function runJobs(clock) { + // runs all microtick-deferred tasks - ecma262/#sec-runjobs + if (!clock.jobs) { + return; + } + for (let i = 0; i < clock.jobs.length; i++) { + const job = clock.jobs[i]; + job.func.apply(null, job.args); + + checkIsNearInfiniteLimit(clock, i); + if (clock.loopLimit && i > clock.loopLimit) { + throw getInfiniteLoopError(clock, job); + } + } + resetIsNearInfiniteLimit(); + clock.jobs = []; } - return null; - } - /** - * Encodings table: https://encoding.spec.whatwg.org/encodings.json - * @const - * @type {!Array.<{ - * heading: string, - * encodings: Array.<{name:string,labels:Array.}> - * }>} - */ - var encodings = [ - { - "encodings": [ - { - "labels": [ - "unicode-1-1-utf-8", - "utf-8", - "utf8" - ], - "name": "UTF-8" + /** + * @param {Clock} clock + * @param {Timer} timer + * @returns {number} id of the created timer + */ + function addTimer(clock, timer) { + if (timer.func === undefined) { + throw new Error("Callback must be provided to timer calls"); } - ], - "heading": "The Encoding" - }, - { - "encodings": [ - { - "labels": [ - "866", - "cp866", - "csibm866", - "ibm866" - ], - "name": "IBM866" - }, - { - "labels": [ - "csisolatin2", - "iso-8859-2", - "iso-ir-101", - "iso8859-2", - "iso88592", - "iso_8859-2", - "iso_8859-2:1987", - "l2", - "latin2" - ], - "name": "ISO-8859-2" - }, - { - "labels": [ - "csisolatin3", - "iso-8859-3", - "iso-ir-109", - "iso8859-3", - "iso88593", - "iso_8859-3", - "iso_8859-3:1988", - "l3", - "latin3" - ], - "name": "ISO-8859-3" - }, - { - "labels": [ - "csisolatin4", - "iso-8859-4", - "iso-ir-110", - "iso8859-4", - "iso88594", - "iso_8859-4", - "iso_8859-4:1988", - "l4", - "latin4" - ], - "name": "ISO-8859-4" - }, - { - "labels": [ - "csisolatincyrillic", - "cyrillic", - "iso-8859-5", - "iso-ir-144", - "iso8859-5", - "iso88595", - "iso_8859-5", - "iso_8859-5:1988" - ], - "name": "ISO-8859-5" - }, - { - "labels": [ - "arabic", + + if (addTimerReturnsObject) { + // Node.js environment + if (typeof timer.func !== "function") { + throw new TypeError( + `[ERR_INVALID_CALLBACK]: Callback must be a function. Received ${ + timer.func + } of type ${typeof timer.func}` + ); + } + } + + if (isNearInfiniteLimit) { + timer.error = new Error(); + } + + timer.type = timer.immediate ? "Immediate" : "Timeout"; + + if (timer.hasOwnProperty("delay")) { + if (typeof timer.delay !== "number") { + timer.delay = parseInt(timer.delay, 10); + } + + if (!isNumberFinite(timer.delay)) { + timer.delay = 0; + } + timer.delay = timer.delay > maxTimeout ? 1 : timer.delay; + timer.delay = Math.max(0, timer.delay); + } + + if (timer.hasOwnProperty("interval")) { + timer.type = "Interval"; + timer.interval = timer.interval > maxTimeout ? 1 : timer.interval; + } + + if (timer.hasOwnProperty("animation")) { + timer.type = "AnimationFrame"; + timer.animation = true; + } + + if (timer.hasOwnProperty("idleCallback")) { + timer.type = "IdleCallback"; + timer.idleCallback = true; + } + + if (!clock.timers) { + clock.timers = {}; + } + + timer.id = uniqueTimerId++; + timer.createdAt = clock.now; + timer.callAt = + clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); + + clock.timers[timer.id] = timer; + + if (addTimerReturnsObject) { + const res = { + refed: true, + ref: function () { + this.refed = true; + return res; + }, + unref: function () { + this.refed = false; + return res; + }, + hasRef: function () { + return this.refed; + }, + refresh: function () { + timer.callAt = + clock.now + + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); + + // it _might_ have been removed, but if not the assignment is perfectly fine + clock.timers[timer.id] = timer; + + return res; + }, + [Symbol.toPrimitive]: function () { + return timer.id; + }, + }; + return res; + } + + return timer.id; + } + + /* eslint consistent-return: "off" */ + /** + * Timer comparitor + * + * @param {Timer} a + * @param {Timer} b + * @returns {number} + */ + function compareTimers(a, b) { + // Sort first by absolute timing + if (a.callAt < b.callAt) { + return -1; + } + if (a.callAt > b.callAt) { + return 1; + } + + // Sort next by immediate, immediate timers take precedence + if (a.immediate && !b.immediate) { + return -1; + } + if (!a.immediate && b.immediate) { + return 1; + } + + // Sort next by creation time, earlier-created timers take precedence + if (a.createdAt < b.createdAt) { + return -1; + } + if (a.createdAt > b.createdAt) { + return 1; + } + + // Sort next by id, lower-id timers take precedence + if (a.id < b.id) { + return -1; + } + if (a.id > b.id) { + return 1; + } + + // As timer ids are unique, no fallback `0` is necessary + } + + /** + * @param {Clock} clock + * @param {number} from + * @param {number} to + * @returns {Timer} + */ + function firstTimerInRange(clock, from, to) { + const timers = clock.timers; + let timer = null; + let id, isInRange; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + isInRange = inRange(from, to, timers[id]); + + if ( + isInRange && + (!timer || compareTimers(timer, timers[id]) === 1) + ) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @returns {Timer} + */ + function firstTimer(clock) { + const timers = clock.timers; + let timer = null; + let id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === 1) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @returns {Timer} + */ + function lastTimer(clock) { + const timers = clock.timers; + let timer = null; + let id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === -1) { + timer = timers[id]; + } + } + } + + return timer; + } + + /** + * @param {Clock} clock + * @param {Timer} timer + */ + function callTimer(clock, timer) { + if (typeof timer.interval === "number") { + clock.timers[timer.id].callAt += timer.interval; + } else { + delete clock.timers[timer.id]; + } + + if (typeof timer.func === "function") { + timer.func.apply(null, timer.args); + } else { + /* eslint no-eval: "off" */ + const eval2 = eval; + (function () { + eval2(timer.func); + })(); + } + } + + /** + * Gets clear handler name for a given timer type + * + * @param {string} ttype + */ + function getClearHandler(ttype) { + if (ttype === "IdleCallback" || ttype === "AnimationFrame") { + return `cancel${ttype}`; + } + return `clear${ttype}`; + } + + /** + * Gets schedule handler name for a given timer type + * + * @param {string} ttype + */ + function getScheduleHandler(ttype) { + if (ttype === "IdleCallback" || ttype === "AnimationFrame") { + return `request${ttype}`; + } + return `set${ttype}`; + } + + /** + * Creates an anonymous function to warn only once + */ + function createWarnOnce() { + let calls = 0; + return function (msg) { + // eslint-disable-next-line + !calls++ && console.warn(msg); + }; + } + const warnOnce = createWarnOnce(); + + /** + * @param {Clock} clock + * @param {number} timerId + * @param {string} ttype + */ + function clearTimer(clock, timerId, ttype) { + if (!timerId) { + // null appears to be allowed in most browsers, and appears to be + // relied upon by some libraries, like Bootstrap carousel + return; + } + + if (!clock.timers) { + clock.timers = {}; + } + + // in Node, the ID is stored as the primitive value for `Timeout` objects + // for `Immediate` objects, no ID exists, so it gets coerced to NaN + const id = Number(timerId); + + if (Number.isNaN(id) || id < idCounterStart) { + const handlerName = getClearHandler(ttype); + + if (clock.shouldClearNativeTimers === true) { + const nativeHandler = clock[`_${handlerName}`]; + return typeof nativeHandler === "function" + ? nativeHandler(timerId) + : undefined; + } + warnOnce( + `FakeTimers: ${handlerName} was invoked to clear a native timer instead of one created by this library.` + + "\nTo automatically clean-up native timers, use `shouldClearNativeTimers`." + ); + } + + if (clock.timers.hasOwnProperty(id)) { + // check that the ID matches a timer of the correct type + const timer = clock.timers[id]; + if ( + timer.type === ttype || + (timer.type === "Timeout" && ttype === "Interval") || + (timer.type === "Interval" && ttype === "Timeout") + ) { + delete clock.timers[id]; + } else { + const clear = getClearHandler(ttype); + const schedule = getScheduleHandler(timer.type); + throw new Error( + `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()` + ); + } + } + } + + /** + * @param {Clock} clock + * @param {Config} config + * @returns {Timer[]} + */ + function uninstall(clock, config) { + let method, i, l; + const installedHrTime = "_hrtime"; + const installedNextTick = "_nextTick"; + + for (i = 0, l = clock.methods.length; i < l; i++) { + method = clock.methods[i]; + if (method === "hrtime" && _global.process) { + _global.process.hrtime = clock[installedHrTime]; + } else if (method === "nextTick" && _global.process) { + _global.process.nextTick = clock[installedNextTick]; + } else if (method === "performance") { + const originalPerfDescriptor = Object.getOwnPropertyDescriptor( + clock, + `_${method}` + ); + if ( + originalPerfDescriptor && + originalPerfDescriptor.get && + !originalPerfDescriptor.set + ) { + Object.defineProperty( + _global, + method, + originalPerfDescriptor + ); + } else if (originalPerfDescriptor.configurable) { + _global[method] = clock[`_${method}`]; + } + } else { + if (_global[method] && _global[method].hadOwnProperty) { + _global[method] = clock[`_${method}`]; + } else { + try { + delete _global[method]; + } catch (ignore) { + /* eslint no-empty: "off" */ + } + } + } + } + + if (config.shouldAdvanceTime === true) { + _global.clearInterval(clock.attachedInterval); + } + + // Prevent multiple executions which will completely remove these props + clock.methods = []; + + // return pending timers, to enable checking what timers remained on uninstall + if (!clock.timers) { + return []; + } + return Object.keys(clock.timers).map(function mapper(key) { + return clock.timers[key]; + }); + } + + /** + * @param {object} target the target containing the method to replace + * @param {string} method the keyname of the method on the target + * @param {Clock} clock + */ + function hijackMethod(target, method, clock) { + clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call( + target, + method + ); + clock[`_${method}`] = target[method]; + + if (method === "Date") { + const date = mirrorDateProperties(clock[method], target[method]); + target[method] = date; + } else if (method === "performance") { + const originalPerfDescriptor = Object.getOwnPropertyDescriptor( + target, + method + ); + // JSDOM has a read only performance field so we have to save/copy it differently + if ( + originalPerfDescriptor && + originalPerfDescriptor.get && + !originalPerfDescriptor.set + ) { + Object.defineProperty( + clock, + `_${method}`, + originalPerfDescriptor + ); + + const perfDescriptor = Object.getOwnPropertyDescriptor( + clock, + method + ); + Object.defineProperty(target, method, perfDescriptor); + } else { + target[method] = clock[method]; + } + } else { + target[method] = function () { + return clock[method].apply(clock, arguments); + }; + + Object.defineProperties( + target[method], + Object.getOwnPropertyDescriptors(clock[method]) + ); + } + + target[method].clock = clock; + } + + /** + * @param {Clock} clock + * @param {number} advanceTimeDelta + */ + function doIntervalTick(clock, advanceTimeDelta) { + clock.tick(advanceTimeDelta); + } + + /** + * @typedef {object} Timers + * @property {setTimeout} setTimeout + * @property {clearTimeout} clearTimeout + * @property {setInterval} setInterval + * @property {clearInterval} clearInterval + * @property {Date} Date + * @property {SetImmediate=} setImmediate + * @property {function(NodeImmediate): void=} clearImmediate + * @property {function(number[]):number[]=} hrtime + * @property {NextTick=} nextTick + * @property {Performance=} performance + * @property {RequestAnimationFrame=} requestAnimationFrame + * @property {boolean=} queueMicrotask + * @property {function(number): void=} cancelAnimationFrame + * @property {RequestIdleCallback=} requestIdleCallback + * @property {function(number): void=} cancelIdleCallback + */ + + /** @type {Timers} */ + const timers = { + setTimeout: _global.setTimeout, + clearTimeout: _global.clearTimeout, + setInterval: _global.setInterval, + clearInterval: _global.clearInterval, + Date: _global.Date, + }; + + if (setImmediatePresent) { + timers.setImmediate = _global.setImmediate; + timers.clearImmediate = _global.clearImmediate; + } + + if (hrtimePresent) { + timers.hrtime = _global.process.hrtime; + } + + if (nextTickPresent) { + timers.nextTick = _global.process.nextTick; + } + + if (performancePresent) { + timers.performance = _global.performance; + } + + if (requestAnimationFramePresent) { + timers.requestAnimationFrame = _global.requestAnimationFrame; + } + + if (queueMicrotaskPresent) { + timers.queueMicrotask = true; + } + + if (cancelAnimationFramePresent) { + timers.cancelAnimationFrame = _global.cancelAnimationFrame; + } + + if (requestIdleCallbackPresent) { + timers.requestIdleCallback = _global.requestIdleCallback; + } + + if (cancelIdleCallbackPresent) { + timers.cancelIdleCallback = _global.cancelIdleCallback; + } + + const originalSetTimeout = _global.setImmediate || _global.setTimeout; + + /** + * @param {Date|number} [start] the system time - non-integer values are floored + * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll() + * @returns {Clock} + */ + function createClock(start, loopLimit) { + // eslint-disable-next-line no-param-reassign + start = Math.floor(getEpoch(start)); + // eslint-disable-next-line no-param-reassign + loopLimit = loopLimit || 1000; + let nanos = 0; + const adjustedSystemTime = [0, 0]; // [millis, nanoremainder] + + if (NativeDate === undefined) { + throw new Error( + "The global scope doesn't have a `Date` object" + + " (see https://github.com/sinonjs/sinon/issues/1852#issuecomment-419622780)" + ); + } + + const clock = { + now: start, + Date: createDate(), + loopLimit: loopLimit, + }; + + clock.Date.clock = clock; + + //eslint-disable-next-line jsdoc/require-jsdoc + function getTimeToNextFrame() { + return 16 - ((clock.now - start) % 16); + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function hrtime(prev) { + const millisSinceStart = clock.now - adjustedSystemTime[0] - start; + const secsSinceStart = Math.floor(millisSinceStart / 1000); + const remainderInNanos = + (millisSinceStart - secsSinceStart * 1e3) * 1e6 + + nanos - + adjustedSystemTime[1]; + + if (Array.isArray(prev)) { + if (prev[1] > 1e9) { + throw new TypeError( + "Number of nanoseconds can't exceed a billion" + ); + } + + const oldSecs = prev[0]; + let nanoDiff = remainderInNanos - prev[1]; + let secDiff = secsSinceStart - oldSecs; + + if (nanoDiff < 0) { + nanoDiff += 1e9; + secDiff -= 1; + } + + return [secDiff, nanoDiff]; + } + return [secsSinceStart, remainderInNanos]; + } + + function fakePerformanceNow() { + const hrt = hrtime(); + const millis = hrt[0] * 1000 + hrt[1] / 1e6; + return millis; + } + + if (hrtimeBigintPresent) { + hrtime.bigint = function () { + const parts = hrtime(); + return BigInt(parts[0]) * BigInt(1e9) + BigInt(parts[1]); // eslint-disable-line + }; + } + + clock.requestIdleCallback = function requestIdleCallback( + func, + timeout + ) { + let timeToNextIdlePeriod = 0; + + if (clock.countTimers() > 0) { + timeToNextIdlePeriod = 50; // const for now + } + + const result = addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: + typeof timeout === "undefined" + ? timeToNextIdlePeriod + : Math.min(timeout, timeToNextIdlePeriod), + idleCallback: true, + }); + + return Number(result); + }; + + clock.cancelIdleCallback = function cancelIdleCallback(timerId) { + return clearTimer(clock, timerId, "IdleCallback"); + }; + + clock.setTimeout = function setTimeout(func, timeout) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout, + }); + }; + if (typeof _global.Promise !== "undefined" && utilPromisify) { + clock.setTimeout[utilPromisify.custom] = + function promisifiedSetTimeout(timeout, arg) { + return new _global.Promise(function setTimeoutExecutor( + resolve + ) { + addTimer(clock, { + func: resolve, + args: [arg], + delay: timeout, + }); + }); + }; + } + + clock.clearTimeout = function clearTimeout(timerId) { + return clearTimer(clock, timerId, "Timeout"); + }; + + clock.nextTick = function nextTick(func) { + return enqueueJob(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 1), + error: isNearInfiniteLimit ? new Error() : null, + }); + }; + + clock.queueMicrotask = function queueMicrotask(func) { + return clock.nextTick(func); // explicitly drop additional arguments + }; + + clock.setInterval = function setInterval(func, timeout) { + // eslint-disable-next-line no-param-reassign + timeout = parseInt(timeout, 10); + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout, + interval: timeout, + }); + }; + + clock.clearInterval = function clearInterval(timerId) { + return clearTimer(clock, timerId, "Interval"); + }; + + if (setImmediatePresent) { + clock.setImmediate = function setImmediate(func) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 1), + immediate: true, + }); + }; + + if (typeof _global.Promise !== "undefined" && utilPromisify) { + clock.setImmediate[utilPromisify.custom] = + function promisifiedSetImmediate(arg) { + return new _global.Promise( + function setImmediateExecutor(resolve) { + addTimer(clock, { + func: resolve, + args: [arg], + immediate: true, + }); + } + ); + }; + } + + clock.clearImmediate = function clearImmediate(timerId) { + return clearTimer(clock, timerId, "Immediate"); + }; + } + + clock.countTimers = function countTimers() { + return ( + Object.keys(clock.timers || {}).length + + (clock.jobs || []).length + ); + }; + + clock.requestAnimationFrame = function requestAnimationFrame(func) { + const result = addTimer(clock, { + func: func, + delay: getTimeToNextFrame(), + get args() { + return [fakePerformanceNow()]; + }, + animation: true, + }); + + return Number(result); + }; + + clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) { + return clearTimer(clock, timerId, "AnimationFrame"); + }; + + clock.runMicrotasks = function runMicrotasks() { + runJobs(clock); + }; + + /** + * @param {number|string} tickValue milliseconds or a string parseable by parseTime + * @param {boolean} isAsync + * @param {Function} resolve + * @param {Function} reject + * @returns {number|undefined} will return the new `now` value or nothing for async + */ + function doTick(tickValue, isAsync, resolve, reject) { + const msFloat = + typeof tickValue === "number" + ? tickValue + : parseTime(tickValue); + const ms = Math.floor(msFloat); + const remainder = nanoRemainder(msFloat); + let nanosTotal = nanos + remainder; + let tickTo = clock.now + ms; + + if (msFloat < 0) { + throw new TypeError("Negative ticks are not supported"); + } + + // adjust for positive overflow + if (nanosTotal >= 1e6) { + tickTo += 1; + nanosTotal -= 1e6; + } + + nanos = nanosTotal; + let tickFrom = clock.now; + let previous = clock.now; + // ESLint fails to detect this correctly + /* eslint-disable prefer-const */ + let timer, + firstException, + oldNow, + nextPromiseTick, + compensationCheck, + postTimerCall; + /* eslint-enable prefer-const */ + + clock.duringTick = true; + + // perform microtasks + oldNow = clock.now; + runJobs(clock); + if (oldNow !== clock.now) { + // compensate for any setSystemTime() call during microtask callback + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + } + + //eslint-disable-next-line jsdoc/require-jsdoc + function doTickInner() { + // perform each timer in the requested range + timer = firstTimerInRange(clock, tickFrom, tickTo); + // eslint-disable-next-line no-unmodified-loop-condition + while (timer && tickFrom <= tickTo) { + if (clock.timers[timer.id]) { + tickFrom = timer.callAt; + clock.now = timer.callAt; + oldNow = clock.now; + try { + runJobs(clock); + callTimer(clock, timer); + } catch (e) { + firstException = firstException || e; + } + + if (isAsync) { + // finish up after native setImmediate callback to allow + // all native es6 promises to process their callbacks after + // each timer fires. + originalSetTimeout(nextPromiseTick); + return; + } + + compensationCheck(); + } + + postTimerCall(); + } + + // perform process.nextTick()s again + oldNow = clock.now; + runJobs(clock); + if (oldNow !== clock.now) { + // compensate for any setSystemTime() call during process.nextTick() callback + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + } + clock.duringTick = false; + + // corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo] + timer = firstTimerInRange(clock, tickFrom, tickTo); + if (timer) { + try { + clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range + } catch (e) { + firstException = firstException || e; + } + } else { + // no timers remaining in the requested range: move the clock all the way to the end + clock.now = tickTo; + + // update nanos + nanos = nanosTotal; + } + if (firstException) { + throw firstException; + } + + if (isAsync) { + resolve(clock.now); + } else { + return clock.now; + } + } + + nextPromiseTick = + isAsync && + function () { + try { + compensationCheck(); + postTimerCall(); + doTickInner(); + } catch (e) { + reject(e); + } + }; + + compensationCheck = function () { + // compensate for any setSystemTime() call during timer callback + if (oldNow !== clock.now) { + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + previous += clock.now - oldNow; + } + }; + + postTimerCall = function () { + timer = firstTimerInRange(clock, previous, tickTo); + previous = tickFrom; + }; + + return doTickInner(); + } + + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {number} will return the new `now` value + */ + clock.tick = function tick(tickValue) { + return doTick(tickValue, false); + }; + + if (typeof _global.Promise !== "undefined") { + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {Promise} + */ + clock.tickAsync = function tickAsync(tickValue) { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + doTick(tickValue, true, resolve, reject); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.next = function next() { + runJobs(clock); + const timer = firstTimer(clock); + if (!timer) { + return clock.now; + } + + clock.duringTick = true; + try { + clock.now = timer.callAt; + callTimer(clock, timer); + runJobs(clock); + return clock.now; + } finally { + clock.duringTick = false; + } + }; + + if (typeof _global.Promise !== "undefined") { + clock.nextAsync = function nextAsync() { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + const timer = firstTimer(clock); + if (!timer) { + resolve(clock.now); + return; + } + + let err; + clock.duringTick = true; + clock.now = timer.callAt; + try { + callTimer(clock, timer); + } catch (e) { + err = e; + } + clock.duringTick = false; + + originalSetTimeout(function () { + if (err) { + reject(err); + } else { + resolve(clock.now); + } + }); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.runAll = function runAll() { + let numTimers, i; + runJobs(clock); + for (i = 0; i < clock.loopLimit; i++) { + if (!clock.timers) { + resetIsNearInfiniteLimit(); + return clock.now; + } + + numTimers = Object.keys(clock.timers).length; + if (numTimers === 0) { + resetIsNearInfiniteLimit(); + return clock.now; + } + + clock.next(); + checkIsNearInfiniteLimit(clock, i); + } + + const excessJob = firstTimer(clock); + throw getInfiniteLoopError(clock, excessJob); + }; + + clock.runToFrame = function runToFrame() { + return clock.tick(getTimeToNextFrame()); + }; + + if (typeof _global.Promise !== "undefined") { + clock.runAllAsync = function runAllAsync() { + return new _global.Promise(function (resolve, reject) { + let i = 0; + /** + * + */ + function doRun() { + originalSetTimeout(function () { + try { + let numTimers; + if (i < clock.loopLimit) { + if (!clock.timers) { + resetIsNearInfiniteLimit(); + resolve(clock.now); + return; + } + + numTimers = Object.keys( + clock.timers + ).length; + if (numTimers === 0) { + resetIsNearInfiniteLimit(); + resolve(clock.now); + return; + } + + clock.next(); + + i++; + + doRun(); + checkIsNearInfiniteLimit(clock, i); + return; + } + + const excessJob = firstTimer(clock); + reject(getInfiniteLoopError(clock, excessJob)); + } catch (e) { + reject(e); + } + }); + } + doRun(); + }); + }; + } + + clock.runToLast = function runToLast() { + const timer = lastTimer(clock); + if (!timer) { + runJobs(clock); + return clock.now; + } + + return clock.tick(timer.callAt - clock.now); + }; + + if (typeof _global.Promise !== "undefined") { + clock.runToLastAsync = function runToLastAsync() { + return new _global.Promise(function (resolve, reject) { + originalSetTimeout(function () { + try { + const timer = lastTimer(clock); + if (!timer) { + resolve(clock.now); + } + + resolve(clock.tickAsync(timer.callAt - clock.now)); + } catch (e) { + reject(e); + } + }); + }); + }; + } + + clock.reset = function reset() { + nanos = 0; + clock.timers = {}; + clock.jobs = []; + clock.now = start; + }; + + clock.setSystemTime = function setSystemTime(systemTime) { + // determine time difference + const newNow = getEpoch(systemTime); + const difference = newNow - clock.now; + let id, timer; + + adjustedSystemTime[0] = adjustedSystemTime[0] + difference; + adjustedSystemTime[1] = adjustedSystemTime[1] + nanos; + // update 'system clock' + clock.now = newNow; + nanos = 0; + + // update timers and intervals to keep them stable + for (id in clock.timers) { + if (clock.timers.hasOwnProperty(id)) { + timer = clock.timers[id]; + timer.createdAt += difference; + timer.callAt += difference; + } + } + }; + + /** + * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" + * @returns {number} will return the new `now` value + */ + clock.jump = function jump(tickValue) { + const msFloat = + typeof tickValue === "number" + ? tickValue + : parseTime(tickValue); + const ms = Math.floor(msFloat); + + for (const timer of Object.values(clock.timers)) { + if (clock.now + ms > timer.callAt) { + timer.callAt = clock.now + ms; + } + } + clock.tick(ms); + }; + + if (performancePresent) { + clock.performance = Object.create(null); + clock.performance.now = fakePerformanceNow; + } + + if (hrtimePresent) { + clock.hrtime = hrtime; + } + + return clock; + } + + /* eslint-disable complexity */ + + /** + * @param {Config=} [config] Optional config + * @returns {Clock} + */ + function install(config) { + if ( + arguments.length > 1 || + config instanceof Date || + Array.isArray(config) || + typeof config === "number" + ) { + throw new TypeError( + `FakeTimers.install called with ${String( + config + )} install requires an object parameter` + ); + } + + if (_global.Date.isFake === true) { + // Timers are already faked; this is a problem. + // Make the user reset timers before continuing. + throw new TypeError( + "Can't install fake timers twice on the same global object." + ); + } + + // eslint-disable-next-line no-param-reassign + config = typeof config !== "undefined" ? config : {}; + config.shouldAdvanceTime = config.shouldAdvanceTime || false; + config.advanceTimeDelta = config.advanceTimeDelta || 20; + config.shouldClearNativeTimers = + config.shouldClearNativeTimers || false; + + if (config.target) { + throw new TypeError( + "config.target is no longer supported. Use `withGlobal(target)` instead." + ); + } + + let i, l; + const clock = createClock(config.now, config.loopLimit); + clock.shouldClearNativeTimers = config.shouldClearNativeTimers; + + clock.uninstall = function () { + return uninstall(clock, config); + }; + + clock.methods = config.toFake || []; + + if (clock.methods.length === 0) { + // do not fake nextTick by default - GitHub#126 + clock.methods = Object.keys(timers).filter(function (key) { + return key !== "nextTick" && key !== "queueMicrotask"; + }); + } + + if (config.shouldAdvanceTime === true) { + const intervalTick = doIntervalTick.bind( + null, + clock, + config.advanceTimeDelta + ); + const intervalId = _global.setInterval( + intervalTick, + config.advanceTimeDelta + ); + clock.attachedInterval = intervalId; + } + + if (clock.methods.includes("performance")) { + const proto = (() => { + if (hasPerformancePrototype) { + return _global.Performance.prototype; + } + if (hasPerformanceConstructorPrototype) { + return _global.performance.constructor.prototype; + } + })(); + if (proto) { + Object.getOwnPropertyNames(proto).forEach(function (name) { + if (name !== "now") { + clock.performance[name] = + name.indexOf("getEntries") === 0 + ? NOOP_ARRAY + : NOOP; + } + }); + } else if ((config.toFake || []).includes("performance")) { + // user explicitly tried to fake performance when not present + throw new ReferenceError( + "non-existent performance object cannot be faked" + ); + } + } + + for (i = 0, l = clock.methods.length; i < l; i++) { + const nameOfMethodToReplace = clock.methods[i]; + if (nameOfMethodToReplace === "hrtime") { + if ( + _global.process && + typeof _global.process.hrtime === "function" + ) { + hijackMethod(_global.process, nameOfMethodToReplace, clock); + } + } else if (nameOfMethodToReplace === "nextTick") { + if ( + _global.process && + typeof _global.process.nextTick === "function" + ) { + hijackMethod(_global.process, nameOfMethodToReplace, clock); + } + } else { + hijackMethod(_global, nameOfMethodToReplace, clock); + } + } + + return clock; + } + + /* eslint-enable complexity */ + + return { + timers: timers, + createClock: createClock, + install: install, + withGlobal: withGlobal, + }; + } + + /** + * @typedef {object} FakeTimers + * @property {Timers} timers + * @property {createClock} createClock + * @property {Function} install + * @property {withGlobal} withGlobal + */ + + /* eslint-enable complexity */ + + /** @type {FakeTimers} */ + const defaultImplementation = withGlobal(globalObject); + + exports.timers = defaultImplementation.timers; + exports.createClock = defaultImplementation.createClock; + exports.install = defaultImplementation.install; + exports.withGlobal = withGlobal; + + },{"@sinonjs/commons":48,"util":113}],62:[function(require,module,exports){ + + var ARRAY_TYPES = [ + Array, + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + module.exports = ARRAY_TYPES; + + },{}],63:[function(require,module,exports){ + + var arrayProto = require("@sinonjs/commons").prototypes.array; + var deepEqual = require("./deep-equal").use(createMatcher); // eslint-disable-line no-use-before-define + var every = require("@sinonjs/commons").every; + var functionName = require("@sinonjs/commons").functionName; + var get = require("lodash.get"); + var iterableToString = require("./iterable-to-string"); + var objectProto = require("@sinonjs/commons").prototypes.object; + var typeOf = require("@sinonjs/commons").typeOf; + var valueToString = require("@sinonjs/commons").valueToString; + + var assertMatcher = require("./create-matcher/assert-matcher"); + var assertMethodExists = require("./create-matcher/assert-method-exists"); + var assertType = require("./create-matcher/assert-type"); + var isIterable = require("./create-matcher/is-iterable"); + var isMatcher = require("./create-matcher/is-matcher"); + + var matcherPrototype = require("./create-matcher/matcher-prototype"); + + var arrayIndexOf = arrayProto.indexOf; + var some = arrayProto.some; + + var hasOwnProperty = objectProto.hasOwnProperty; + var objectToString = objectProto.toString; + + var TYPE_MAP = require("./create-matcher/type-map")(createMatcher); // eslint-disable-line no-use-before-define + + /** + * Creates a matcher object for the passed expectation + * + * @alias module:samsam.createMatcher + * @param {*} expectation An expecttation + * @param {string} message A message for the expectation + * @returns {object} A matcher object + */ + function createMatcher(expectation, message) { + var m = Object.create(matcherPrototype); + var type = typeOf(expectation); + + if (message !== undefined && typeof message !== "string") { + throw new TypeError("Message should be a string"); + } + + if (arguments.length > 2) { + throw new TypeError( + `Expected 1 or 2 arguments, received ${arguments.length}` + ); + } + + if (type in TYPE_MAP) { + TYPE_MAP[type](m, expectation, message); + } else { + m.test = function (actual) { + return deepEqual(actual, expectation); + }; + } + + if (!m.message) { + m.message = `match(${valueToString(expectation)})`; + } + + // ensure that nothing mutates the exported message value, ref https://github.com/sinonjs/sinon/issues/2502 + Object.defineProperty(m, "message", { + configurable: false, + writable: false, + value: m.message, + }); + + return m; + } + + createMatcher.isMatcher = isMatcher; + + createMatcher.any = createMatcher(function () { + return true; + }, "any"); + + createMatcher.defined = createMatcher(function (actual) { + return actual !== null && actual !== undefined; + }, "defined"); + + createMatcher.truthy = createMatcher(function (actual) { + return Boolean(actual); + }, "truthy"); + + createMatcher.falsy = createMatcher(function (actual) { + return !actual; + }, "falsy"); + + createMatcher.same = function (expectation) { + return createMatcher(function (actual) { + return expectation === actual; + }, `same(${valueToString(expectation)})`); + }; + + createMatcher.in = function (arrayOfExpectations) { + if (typeOf(arrayOfExpectations) !== "array") { + throw new TypeError("array expected"); + } + + return createMatcher(function (actual) { + return some(arrayOfExpectations, function (expectation) { + return expectation === actual; + }); + }, `in(${valueToString(arrayOfExpectations)})`); + }; + + createMatcher.typeOf = function (type) { + assertType(type, "string", "type"); + return createMatcher(function (actual) { + return typeOf(actual) === type; + }, `typeOf("${type}")`); + }; + + createMatcher.instanceOf = function (type) { + /* istanbul ignore if */ + if ( + typeof Symbol === "undefined" || + typeof Symbol.hasInstance === "undefined" + ) { + assertType(type, "function", "type"); + } else { + assertMethodExists( + type, + Symbol.hasInstance, + "type", + "[Symbol.hasInstance]" + ); + } + return createMatcher(function (actual) { + return actual instanceof type; + }, `instanceOf(${functionName(type) || objectToString(type)})`); + }; + + /** + * Creates a property matcher + * + * @private + * @param {Function} propertyTest A function to test the property against a value + * @param {string} messagePrefix A prefix to use for messages generated by the matcher + * @returns {object} A matcher + */ + function createPropertyMatcher(propertyTest, messagePrefix) { + return function (property, value) { + assertType(property, "string", "property"); + var onlyProperty = arguments.length === 1; + var message = `${messagePrefix}("${property}"`; + if (!onlyProperty) { + message += `, ${valueToString(value)}`; + } + message += ")"; + return createMatcher(function (actual) { + if ( + actual === undefined || + actual === null || + !propertyTest(actual, property) + ) { + return false; + } + return onlyProperty || deepEqual(actual[property], value); + }, message); + }; + } + + createMatcher.has = createPropertyMatcher(function (actual, property) { + if (typeof actual === "object") { + return property in actual; + } + return actual[property] !== undefined; + }, "has"); + + createMatcher.hasOwn = createPropertyMatcher(function (actual, property) { + return hasOwnProperty(actual, property); + }, "hasOwn"); + + createMatcher.hasNested = function (property, value) { + assertType(property, "string", "property"); + var onlyProperty = arguments.length === 1; + var message = `hasNested("${property}"`; + if (!onlyProperty) { + message += `, ${valueToString(value)}`; + } + message += ")"; + return createMatcher(function (actual) { + if ( + actual === undefined || + actual === null || + get(actual, property) === undefined + ) { + return false; + } + return onlyProperty || deepEqual(get(actual, property), value); + }, message); + }; + + var jsonParseResultTypes = { + null: true, + boolean: true, + number: true, + string: true, + object: true, + array: true, + }; + createMatcher.json = function (value) { + if (!jsonParseResultTypes[typeOf(value)]) { + throw new TypeError("Value cannot be the result of JSON.parse"); + } + var message = `json(${JSON.stringify(value, null, " ")})`; + return createMatcher(function (actual) { + var parsed; + try { + parsed = JSON.parse(actual); + } catch (e) { + return false; + } + return deepEqual(parsed, value); + }, message); + }; + + createMatcher.every = function (predicate) { + assertMatcher(predicate); + + return createMatcher(function (actual) { + if (typeOf(actual) === "object") { + return every(Object.keys(actual), function (key) { + return predicate.test(actual[key]); + }); + } + + return ( + isIterable(actual) && + every(actual, function (element) { + return predicate.test(element); + }) + ); + }, `every(${predicate.message})`); + }; + + createMatcher.some = function (predicate) { + assertMatcher(predicate); + + return createMatcher(function (actual) { + if (typeOf(actual) === "object") { + return !every(Object.keys(actual), function (key) { + return !predicate.test(actual[key]); + }); + } + + return ( + isIterable(actual) && + !every(actual, function (element) { + return !predicate.test(element); + }) + ); + }, `some(${predicate.message})`); + }; + + createMatcher.array = createMatcher.typeOf("array"); + + createMatcher.array.deepEquals = function (expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.length === expectation.length; + return ( + typeOf(actual) === "array" && + sameLength && + every(actual, function (element, index) { + var expected = expectation[index]; + return typeOf(expected) === "array" && + typeOf(element) === "array" + ? createMatcher.array.deepEquals(expected).test(element) + : deepEqual(expected, element); + }) + ); + }, `deepEquals([${iterableToString(expectation)}])`); + }; + + createMatcher.array.startsWith = function (expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement, index) { + return actual[index] === expectedElement; + }) + ); + }, `startsWith([${iterableToString(expectation)}])`); + }; + + createMatcher.array.endsWith = function (expectation) { + return createMatcher(function (actual) { + // This indicates the index in which we should start matching + var offset = actual.length - expectation.length; + + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement, index) { + return actual[offset + index] === expectedElement; + }) + ); + }, `endsWith([${iterableToString(expectation)}])`); + }; + + createMatcher.array.contains = function (expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "array" && + every(expectation, function (expectedElement) { + return arrayIndexOf(actual, expectedElement) !== -1; + }) + ); + }, `contains([${iterableToString(expectation)}])`); + }; + + createMatcher.map = createMatcher.typeOf("map"); + + createMatcher.map.deepEquals = function mapDeepEquals(expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.size === expectation.size; + return ( + typeOf(actual) === "map" && + sameLength && + every(actual, function (element, key) { + return expectation.has(key) && expectation.get(key) === element; + }) + ); + }, `deepEquals(Map[${iterableToString(expectation)}])`); + }; + + createMatcher.map.contains = function mapContains(expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "map" && + every(expectation, function (element, key) { + return actual.has(key) && actual.get(key) === element; + }) + ); + }, `contains(Map[${iterableToString(expectation)}])`); + }; + + createMatcher.set = createMatcher.typeOf("set"); + + createMatcher.set.deepEquals = function setDeepEquals(expectation) { + return createMatcher(function (actual) { + // Comparing lengths is the fastest way to spot a difference before iterating through every item + var sameLength = actual.size === expectation.size; + return ( + typeOf(actual) === "set" && + sameLength && + every(actual, function (element) { + return expectation.has(element); + }) + ); + }, `deepEquals(Set[${iterableToString(expectation)}])`); + }; + + createMatcher.set.contains = function setContains(expectation) { + return createMatcher(function (actual) { + return ( + typeOf(actual) === "set" && + every(expectation, function (element) { + return actual.has(element); + }) + ); + }, `contains(Set[${iterableToString(expectation)}])`); + }; + + createMatcher.bool = createMatcher.typeOf("boolean"); + createMatcher.number = createMatcher.typeOf("number"); + createMatcher.string = createMatcher.typeOf("string"); + createMatcher.object = createMatcher.typeOf("object"); + createMatcher.func = createMatcher.typeOf("function"); + createMatcher.regexp = createMatcher.typeOf("regexp"); + createMatcher.date = createMatcher.typeOf("date"); + createMatcher.symbol = createMatcher.typeOf("symbol"); + + module.exports = createMatcher; + + },{"./create-matcher/assert-matcher":64,"./create-matcher/assert-method-exists":65,"./create-matcher/assert-type":66,"./create-matcher/is-iterable":67,"./create-matcher/is-matcher":68,"./create-matcher/matcher-prototype":70,"./create-matcher/type-map":71,"./deep-equal":72,"./iterable-to-string":86,"@sinonjs/commons":95,"lodash.get":116}],64:[function(require,module,exports){ + + var isMatcher = require("./is-matcher"); + + /** + * Throws a TypeError when `value` is not a matcher + * + * @private + * @param {*} value The value to examine + */ + function assertMatcher(value) { + if (!isMatcher(value)) { + throw new TypeError("Matcher expected"); + } + } + + module.exports = assertMatcher; + + },{"./is-matcher":68}],65:[function(require,module,exports){ + + /** + * Throws a TypeError when expected method doesn't exist + * + * @private + * @param {*} value A value to examine + * @param {string} method The name of the method to look for + * @param {name} name A name to use for the error message + * @param {string} methodPath The name of the method to use for error messages + * @throws {TypeError} When the method doesn't exist + */ + function assertMethodExists(value, method, name, methodPath) { + if (value[method] === null || value[method] === undefined) { + throw new TypeError(`Expected ${name} to have method ${methodPath}`); + } + } + + module.exports = assertMethodExists; + + },{}],66:[function(require,module,exports){ + + var typeOf = require("@sinonjs/commons").typeOf; + + /** + * Ensures that value is of type + * + * @private + * @param {*} value A value to examine + * @param {string} type A basic JavaScript type to compare to, e.g. "object", "string" + * @param {string} name A string to use for the error message + * @throws {TypeError} If value is not of the expected type + * @returns {undefined} + */ + function assertType(value, type, name) { + var actual = typeOf(value); + if (actual !== type) { + throw new TypeError( + `Expected type of ${name} to be ${type}, but was ${actual}` + ); + } + } + + module.exports = assertType; + + },{"@sinonjs/commons":95}],67:[function(require,module,exports){ + + var typeOf = require("@sinonjs/commons").typeOf; + + /** + * Returns `true` for iterables + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` looks like an iterable + */ + function isIterable(value) { + return Boolean(value) && typeOf(value.forEach) === "function"; + } + + module.exports = isIterable; + + },{"@sinonjs/commons":95}],68:[function(require,module,exports){ + + var isPrototypeOf = require("@sinonjs/commons").prototypes.object.isPrototypeOf; + + var matcherPrototype = require("./matcher-prototype"); + + /** + * Returns `true` when `object` is a matcher + * + * @private + * @param {*} object A value to examine + * @returns {boolean} Returns `true` when `object` is a matcher + */ + function isMatcher(object) { + return isPrototypeOf(matcherPrototype, object); + } + + module.exports = isMatcher; + + },{"./matcher-prototype":70,"@sinonjs/commons":95}],69:[function(require,module,exports){ + + var every = require("@sinonjs/commons").prototypes.array.every; + var concat = require("@sinonjs/commons").prototypes.array.concat; + var typeOf = require("@sinonjs/commons").typeOf; + + var deepEqualFactory = require("../deep-equal").use; + + var isMatcher = require("./is-matcher"); + + var keys = Object.keys; + var getOwnPropertySymbols = Object.getOwnPropertySymbols; + + /** + * Matches `actual` with `expectation` + * + * @private + * @param {*} actual A value to examine + * @param {object} expectation An object with properties to match on + * @param {object} matcher A matcher to use for comparison + * @returns {boolean} Returns true when `actual` matches all properties in `expectation` + */ + function matchObject(actual, expectation, matcher) { + var deepEqual = deepEqualFactory(matcher); + if (actual === null || actual === undefined) { + return false; + } + + var expectedKeys = keys(expectation); + /* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */ + if (typeOf(getOwnPropertySymbols) === "function") { + expectedKeys = concat(expectedKeys, getOwnPropertySymbols(expectation)); + } + + return every(expectedKeys, function (key) { + var exp = expectation[key]; + var act = actual[key]; + + if (isMatcher(exp)) { + if (!exp.test(act)) { + return false; + } + } else if (typeOf(exp) === "object") { + if (!matchObject(act, exp, matcher)) { + return false; + } + } else if (!deepEqual(act, exp)) { + return false; + } + + return true; + }); + } + + module.exports = matchObject; + + },{"../deep-equal":72,"./is-matcher":68,"@sinonjs/commons":95}],70:[function(require,module,exports){ + + var matcherPrototype = { + toString: function () { + return this.message; + }, + }; + + matcherPrototype.or = function (valueOrMatcher) { + var createMatcher = require("../create-matcher"); + var isMatcher = createMatcher.isMatcher; + + if (!arguments.length) { + throw new TypeError("Matcher expected"); + } + + var m2 = isMatcher(valueOrMatcher) + ? valueOrMatcher + : createMatcher(valueOrMatcher); + var m1 = this; + var or = Object.create(matcherPrototype); + or.test = function (actual) { + return m1.test(actual) || m2.test(actual); + }; + or.message = `${m1.message}.or(${m2.message})`; + return or; + }; + + matcherPrototype.and = function (valueOrMatcher) { + var createMatcher = require("../create-matcher"); + var isMatcher = createMatcher.isMatcher; + + if (!arguments.length) { + throw new TypeError("Matcher expected"); + } + + var m2 = isMatcher(valueOrMatcher) + ? valueOrMatcher + : createMatcher(valueOrMatcher); + var m1 = this; + var and = Object.create(matcherPrototype); + and.test = function (actual) { + return m1.test(actual) && m2.test(actual); + }; + and.message = `${m1.message}.and(${m2.message})`; + return and; + }; + + module.exports = matcherPrototype; + + },{"../create-matcher":63}],71:[function(require,module,exports){ + + var functionName = require("@sinonjs/commons").functionName; + var join = require("@sinonjs/commons").prototypes.array.join; + var map = require("@sinonjs/commons").prototypes.array.map; + var stringIndexOf = require("@sinonjs/commons").prototypes.string.indexOf; + var valueToString = require("@sinonjs/commons").valueToString; + + var matchObject = require("./match-object"); + + var createTypeMap = function (match) { + return { + function: function (m, expectation, message) { + m.test = expectation; + m.message = message || `match(${functionName(expectation)})`; + }, + number: function (m, expectation) { + m.test = function (actual) { + // we need type coercion here + return expectation == actual; // eslint-disable-line eqeqeq + }; + }, + object: function (m, expectation) { + var array = []; + + if (typeof expectation.test === "function") { + m.test = function (actual) { + return expectation.test(actual) === true; + }; + m.message = `match(${functionName(expectation.test)})`; + return m; + } + + array = map(Object.keys(expectation), function (key) { + return `${key}: ${valueToString(expectation[key])}`; + }); + + m.test = function (actual) { + return matchObject(actual, expectation, match); + }; + m.message = `match(${join(array, ", ")})`; + + return m; + }, + regexp: function (m, expectation) { + m.test = function (actual) { + return typeof actual === "string" && expectation.test(actual); + }; + }, + string: function (m, expectation) { + m.test = function (actual) { + return ( + typeof actual === "string" && + stringIndexOf(actual, expectation) !== -1 + ); + }; + m.message = `match("${expectation}")`; + }, + }; + }; + + module.exports = createTypeMap; + + },{"./match-object":69,"@sinonjs/commons":95}],72:[function(require,module,exports){ + + var valueToString = require("@sinonjs/commons").valueToString; + var className = require("@sinonjs/commons").className; + var typeOf = require("@sinonjs/commons").typeOf; + var arrayProto = require("@sinonjs/commons").prototypes.array; + var objectProto = require("@sinonjs/commons").prototypes.object; + var mapForEach = require("@sinonjs/commons").prototypes.map.forEach; + + var getClass = require("./get-class"); + var identical = require("./identical"); + var isArguments = require("./is-arguments"); + var isArrayType = require("./is-array-type"); + var isDate = require("./is-date"); + var isElement = require("./is-element"); + var isIterable = require("./is-iterable"); + var isMap = require("./is-map"); + var isNaN = require("./is-nan"); + var isObject = require("./is-object"); + var isSet = require("./is-set"); + var isSubset = require("./is-subset"); + + var concat = arrayProto.concat; + var every = arrayProto.every; + var push = arrayProto.push; + + var getTime = Date.prototype.getTime; + var hasOwnProperty = objectProto.hasOwnProperty; + var indexOf = arrayProto.indexOf; + var keys = Object.keys; + var getOwnPropertySymbols = Object.getOwnPropertySymbols; + + /** + * Deep equal comparison. Two values are "deep equal" when: + * + * - They are equal, according to samsam.identical + * - They are both date objects representing the same time + * - They are both arrays containing elements that are all deepEqual + * - They are objects with the same set of properties, and each property + * in ``actual`` is deepEqual to the corresponding property in ``expectation`` + * + * Supports cyclic objects. + * + * @alias module:samsam.deepEqual + * @param {*} actual The object to examine + * @param {*} expectation The object actual is expected to be equal to + * @param {object} match A value to match on + * @returns {boolean} Returns true when actual and expectation are considered equal + */ + function deepEqualCyclic(actual, expectation, match) { + // used for cyclic comparison + // contain already visited objects + var actualObjects = []; + var expectationObjects = []; + // contain pathes (position in the object structure) + // of the already visited objects + // indexes same as in objects arrays + var actualPaths = []; + var expectationPaths = []; + // contains combinations of already compared objects + // in the manner: { "$1['ref']$2['ref']": true } + var compared = {}; + + // does the recursion for the deep equal check + // eslint-disable-next-line complexity + return (function deepEqual( + actualObj, + expectationObj, + actualPath, + expectationPath + ) { + // If both are matchers they must be the same instance in order to be + // considered equal If we didn't do that we would end up running one + // matcher against the other + if (match && match.isMatcher(expectationObj)) { + if (match.isMatcher(actualObj)) { + return actualObj === expectationObj; + } + return expectationObj.test(actualObj); + } + + var actualType = typeof actualObj; + var expectationType = typeof expectationObj; + + if ( + actualObj === expectationObj || + isNaN(actualObj) || + isNaN(expectationObj) || + actualObj === null || + expectationObj === null || + actualObj === undefined || + expectationObj === undefined || + actualType !== "object" || + expectationType !== "object" + ) { + return identical(actualObj, expectationObj); + } + + // Elements are only equal if identical(expected, actual) + if (isElement(actualObj) || isElement(expectationObj)) { + return false; + } + + var isActualDate = isDate(actualObj); + var isExpectationDate = isDate(expectationObj); + if (isActualDate || isExpectationDate) { + if ( + !isActualDate || + !isExpectationDate || + getTime.call(actualObj) !== getTime.call(expectationObj) + ) { + return false; + } + } + + if (actualObj instanceof RegExp && expectationObj instanceof RegExp) { + if (valueToString(actualObj) !== valueToString(expectationObj)) { + return false; + } + } + + if (actualObj instanceof Promise && expectationObj instanceof Promise) { + return actualObj === expectationObj; + } + + if (actualObj instanceof Error && expectationObj instanceof Error) { + return actualObj === expectationObj; + } + + var actualClass = getClass(actualObj); + var expectationClass = getClass(expectationObj); + var actualKeys = keys(actualObj); + var expectationKeys = keys(expectationObj); + var actualName = className(actualObj); + var expectationName = className(expectationObj); + var expectationSymbols = + typeOf(getOwnPropertySymbols) === "function" + ? getOwnPropertySymbols(expectationObj) + : /* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */ + []; + var expectationKeysAndSymbols = concat( + expectationKeys, + expectationSymbols + ); + + if (isArguments(actualObj) || isArguments(expectationObj)) { + if (actualObj.length !== expectationObj.length) { + return false; + } + } else { + if ( + actualType !== expectationType || + actualClass !== expectationClass || + actualKeys.length !== expectationKeys.length || + (actualName && + expectationName && + actualName !== expectationName) + ) { + return false; + } + } + + if (isSet(actualObj) || isSet(expectationObj)) { + if ( + !isSet(actualObj) || + !isSet(expectationObj) || + actualObj.size !== expectationObj.size + ) { + return false; + } + + return isSubset(actualObj, expectationObj, deepEqual); + } + + if (isMap(actualObj) || isMap(expectationObj)) { + if ( + !isMap(actualObj) || + !isMap(expectationObj) || + actualObj.size !== expectationObj.size + ) { + return false; + } + + var mapsDeeplyEqual = true; + mapForEach(actualObj, function (value, key) { + mapsDeeplyEqual = + mapsDeeplyEqual && + deepEqualCyclic(value, expectationObj.get(key)); + }); + + return mapsDeeplyEqual; + } + + // jQuery objects have iteration protocols + // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols + // But, they don't work well with the implementation concerning iterables below, + // so we will detect them and use jQuery's own equality function + /* istanbul ignore next -- this can only be tested in the `test-headless` script */ + if ( + actualObj.constructor && + actualObj.constructor.name === "jQuery" && + typeof actualObj.is === "function" + ) { + return actualObj.is(expectationObj); + } + + var isActualNonArrayIterable = + isIterable(actualObj) && + !isArrayType(actualObj) && + !isArguments(actualObj); + var isExpectationNonArrayIterable = + isIterable(expectationObj) && + !isArrayType(expectationObj) && + !isArguments(expectationObj); + if (isActualNonArrayIterable || isExpectationNonArrayIterable) { + var actualArray = Array.from(actualObj); + var expectationArray = Array.from(expectationObj); + if (actualArray.length !== expectationArray.length) { + return false; + } + + var arrayDeeplyEquals = true; + every(actualArray, function (key) { + arrayDeeplyEquals = + arrayDeeplyEquals && + deepEqualCyclic(actualArray[key], expectationArray[key]); + }); + + return arrayDeeplyEquals; + } + + return every(expectationKeysAndSymbols, function (key) { + if (!hasOwnProperty(actualObj, key)) { + return false; + } + + var actualValue = actualObj[key]; + var expectationValue = expectationObj[key]; + var actualObject = isObject(actualValue); + var expectationObject = isObject(expectationValue); + // determines, if the objects were already visited + // (it's faster to check for isObject first, than to + // get -1 from getIndex for non objects) + var actualIndex = actualObject + ? indexOf(actualObjects, actualValue) + : -1; + var expectationIndex = expectationObject + ? indexOf(expectationObjects, expectationValue) + : -1; + // determines the new paths of the objects + // - for non cyclic objects the current path will be extended + // by current property name + // - for cyclic objects the stored path is taken + var newActualPath = + actualIndex !== -1 + ? actualPaths[actualIndex] + : `${actualPath}[${JSON.stringify(key)}]`; + var newExpectationPath = + expectationIndex !== -1 + ? expectationPaths[expectationIndex] + : `${expectationPath}[${JSON.stringify(key)}]`; + var combinedPath = newActualPath + newExpectationPath; + + // stop recursion if current objects are already compared + if (compared[combinedPath]) { + return true; + } + + // remember the current objects and their paths + if (actualIndex === -1 && actualObject) { + push(actualObjects, actualValue); + push(actualPaths, newActualPath); + } + if (expectationIndex === -1 && expectationObject) { + push(expectationObjects, expectationValue); + push(expectationPaths, newExpectationPath); + } + + // remember that the current objects are already compared + if (actualObject && expectationObject) { + compared[combinedPath] = true; + } + + // End of cyclic logic + + // neither actualValue nor expectationValue is a cycle + // continue with next level + return deepEqual( + actualValue, + expectationValue, + newActualPath, + newExpectationPath + ); + }); + })(actual, expectation, "$1", "$2"); + } + + deepEqualCyclic.use = function (match) { + return function deepEqual(a, b) { + return deepEqualCyclic(a, b, match); + }; + }; + + module.exports = deepEqualCyclic; + + },{"./get-class":73,"./identical":74,"./is-arguments":75,"./is-array-type":76,"./is-date":77,"./is-element":78,"./is-iterable":79,"./is-map":80,"./is-nan":81,"./is-object":83,"./is-set":84,"./is-subset":85,"@sinonjs/commons":95}],73:[function(require,module,exports){ + + var toString = require("@sinonjs/commons").prototypes.object.toString; + + /** + * Returns the internal `Class` by calling `Object.prototype.toString` + * with the provided value as `this`. Return value is a `String`, naming the + * internal class, e.g. "Array" + * + * @private + * @param {*} value - Any value + * @returns {string} - A string representation of the `Class` of `value` + */ + function getClass(value) { + return toString(value).split(/[ \]]/)[1]; + } + + module.exports = getClass; + + },{"@sinonjs/commons":95}],74:[function(require,module,exports){ + + var isNaN = require("./is-nan"); + var isNegZero = require("./is-neg-zero"); + + /** + * Strict equality check according to EcmaScript Harmony's `egal`. + * + * **From the Harmony wiki:** + * > An `egal` function simply makes available the internal `SameValue` function + * > from section 9.12 of the ES5 spec. If two values are egal, then they are not + * > observably distinguishable. + * + * `identical` returns `true` when `===` is `true`, except for `-0` and + * `+0`, where it returns `false`. Additionally, it returns `true` when + * `NaN` is compared to itself. + * + * @alias module:samsam.identical + * @param {*} obj1 The first value to compare + * @param {*} obj2 The second value to compare + * @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise + */ + function identical(obj1, obj2) { + if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { + return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); + } + + return false; + } + + module.exports = identical; + + },{"./is-nan":81,"./is-neg-zero":82}],75:[function(require,module,exports){ + + var getClass = require("./get-class"); + + /** + * Returns `true` when `object` is an `arguments` object, `false` otherwise + * + * @alias module:samsam.isArguments + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an `arguments` object + */ + function isArguments(object) { + return getClass(object) === "Arguments"; + } + + module.exports = isArguments; + + },{"./get-class":73}],76:[function(require,module,exports){ + + var functionName = require("@sinonjs/commons").functionName; + var indexOf = require("@sinonjs/commons").prototypes.array.indexOf; + var map = require("@sinonjs/commons").prototypes.array.map; + var ARRAY_TYPES = require("./array-types"); + var type = require("type-detect"); + + /** + * Returns `true` when `object` is an array type, `false` otherwise + * + * @param {*} object - The object to examine + * @returns {boolean} `true` when `object` is an array type + * @private + */ + function isArrayType(object) { + return indexOf(map(ARRAY_TYPES, functionName), type(object)) !== -1; + } + + module.exports = isArrayType; + + },{"./array-types":62,"@sinonjs/commons":95,"type-detect":151}],77:[function(require,module,exports){ + + /** + * Returns `true` when `value` is an instance of Date + * + * @private + * @param {Date} value The value to examine + * @returns {boolean} `true` when `value` is an instance of Date + */ + function isDate(value) { + return value instanceof Date; + } + + module.exports = isDate; + + },{}],78:[function(require,module,exports){ + + var div = typeof document !== "undefined" && document.createElement("div"); + + /** + * Returns `true` when `object` is a DOM element node. + * + * Unlike Underscore.js/lodash, this function will return `false` if `object` + * is an *element-like* object, i.e. a regular object with a `nodeType` + * property that holds the value `1`. + * + * @alias module:samsam.isElement + * @param {object} object The object to examine + * @returns {boolean} Returns `true` for DOM element nodes + */ + function isElement(object) { + if (!object || object.nodeType !== 1 || !div) { + return false; + } + try { + object.appendChild(div); + object.removeChild(div); + } catch (e) { + return false; + } + return true; + } + + module.exports = isElement; + + },{}],79:[function(require,module,exports){ + + /** + * Returns `true` when the argument is an iterable, `false` otherwise + * + * @alias module:samsam.isIterable + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise + */ + function isIterable(val) { + // checks for null and undefined + if (typeof val !== "object") { + return false; + } + return typeof val[Symbol.iterator] === "function"; + } + + module.exports = isIterable; + + },{}],80:[function(require,module,exports){ + + /** + * Returns `true` when `value` is a Map + * + * @param {*} value A value to examine + * @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise + * @private + */ + function isMap(value) { + return typeof Map !== "undefined" && value instanceof Map; + } + + module.exports = isMap; + + },{}],81:[function(require,module,exports){ + + /** + * Compares a `value` to `NaN` + * + * @private + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `NaN` + */ + function isNaN(value) { + // Unlike global `isNaN`, this function avoids type coercion + // `typeof` check avoids IE host object issues, hat tip to + // lodash + + // eslint-disable-next-line no-self-compare + return typeof value === "number" && value !== value; + } + + module.exports = isNaN; + + },{}],82:[function(require,module,exports){ + + /** + * Returns `true` when `value` is `-0` + * + * @alias module:samsam.isNegZero + * @param {*} value A value to examine + * @returns {boolean} Returns `true` when `value` is `-0` + */ + function isNegZero(value) { + return value === 0 && 1 / value === -Infinity; + } + + module.exports = isNegZero; + + },{}],83:[function(require,module,exports){ + + /** + * Returns `true` when the value is a regular Object and not a specialized Object + * + * This helps speed up deepEqual cyclic checks + * + * The premise is that only Objects are stored in the visited array. + * So if this function returns false, we don't have to do the + * expensive operation of searching for the value in the the array of already + * visited objects + * + * @private + * @param {object} value The object to examine + * @returns {boolean} `true` when the object is a non-specialised object + */ + function isObject(value) { + return ( + typeof value === "object" && + value !== null && + // none of these are collection objects, so we can return false + !(value instanceof Boolean) && + !(value instanceof Date) && + !(value instanceof Error) && + !(value instanceof Number) && + !(value instanceof RegExp) && + !(value instanceof String) + ); + } + + module.exports = isObject; + + },{}],84:[function(require,module,exports){ + + /** + * Returns `true` when the argument is an instance of Set, `false` otherwise + * + * @alias module:samsam.isSet + * @param {*} val - A value to examine + * @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise + */ + function isSet(val) { + return (typeof Set !== "undefined" && val instanceof Set) || false; + } + + module.exports = isSet; + + },{}],85:[function(require,module,exports){ + + var forEach = require("@sinonjs/commons").prototypes.set.forEach; + + /** + * Returns `true` when `s1` is a subset of `s2`, `false` otherwise + * + * @private + * @param {Array|Set} s1 The target value + * @param {Array|Set} s2 The containing value + * @param {Function} compare A comparison function, should return `true` when + * values are considered equal + * @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise + */ + function isSubset(s1, s2, compare) { + var allContained = true; + forEach(s1, function (v1) { + var includes = false; + forEach(s2, function (v2) { + if (compare(v2, v1)) { + includes = true; + } + }); + allContained = allContained && includes; + }); + + return allContained; + } + + module.exports = isSubset; + + },{"@sinonjs/commons":95}],86:[function(require,module,exports){ + + var slice = require("@sinonjs/commons").prototypes.string.slice; + var typeOf = require("@sinonjs/commons").typeOf; + var valueToString = require("@sinonjs/commons").valueToString; + + /** + * Creates a string represenation of an iterable object + * + * @private + * @param {object} obj The iterable object to stringify + * @returns {string} A string representation + */ + function iterableToString(obj) { + if (typeOf(obj) === "map") { + return mapToString(obj); + } + + return genericIterableToString(obj); + } + + /** + * Creates a string representation of a Map + * + * @private + * @param {Map} map The map to stringify + * @returns {string} A string representation + */ + function mapToString(map) { + var representation = ""; + + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + map.forEach(function (value, key) { + representation += `[${stringify(key)},${stringify(value)}],`; + }); + + representation = slice(representation, 0, -1); + return representation; + } + + /** + * Create a string represenation for an iterable + * + * @private + * @param {object} iterable The iterable to stringify + * @returns {string} A string representation + */ + function genericIterableToString(iterable) { + var representation = ""; + + // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods + iterable.forEach(function (value) { + representation += `${stringify(value)},`; + }); + + representation = slice(representation, 0, -1); + return representation; + } + + /** + * Creates a string representation of the passed `item` + * + * @private + * @param {object} item The item to stringify + * @returns {string} A string representation of `item` + */ + function stringify(item) { + return typeof item === "string" ? `'${item}'` : valueToString(item); + } + + module.exports = iterableToString; + + },{"@sinonjs/commons":95}],87:[function(require,module,exports){ + + var valueToString = require("@sinonjs/commons").valueToString; + var indexOf = require("@sinonjs/commons").prototypes.string.indexOf; + var forEach = require("@sinonjs/commons").prototypes.array.forEach; + var type = require("type-detect"); + + var engineCanCompareMaps = typeof Array.from === "function"; + var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define + var isArrayType = require("./is-array-type"); + var isSubset = require("./is-subset"); + var createMatcher = require("./create-matcher"); + + /** + * Returns true when `array` contains all of `subset` as defined by the `compare` + * argument + * + * @param {Array} array An array to search for a subset + * @param {Array} subset The subset to find in the array + * @param {Function} compare A comparison function + * @returns {boolean} [description] + * @private + */ + function arrayContains(array, subset, compare) { + if (subset.length === 0) { + return true; + } + var i, l, j, k; + for (i = 0, l = array.length; i < l; ++i) { + if (compare(array[i], subset[0])) { + for (j = 0, k = subset.length; j < k; ++j) { + if (i + j >= l) { + return false; + } + if (!compare(array[i + j], subset[j])) { + return false; + } + } + return true; + } + } + return false; + } + + /* eslint-disable complexity */ + /** + * Matches an object with a matcher (or value) + * + * @alias module:samsam.match + * @param {object} object The object candidate to match + * @param {object} matcherOrValue A matcher or value to match against + * @returns {boolean} true when `object` matches `matcherOrValue` + */ + function match(object, matcherOrValue) { + if (matcherOrValue && typeof matcherOrValue.test === "function") { + return matcherOrValue.test(object); + } + + switch (type(matcherOrValue)) { + case "bigint": + case "boolean": + case "number": + case "symbol": + return matcherOrValue === object; + case "function": + return matcherOrValue(object) === true; + case "string": + var notNull = typeof object === "string" || Boolean(object); + return ( + notNull && + indexOf( + valueToString(object).toLowerCase(), + matcherOrValue.toLowerCase() + ) >= 0 + ); + case "null": + return object === null; + case "undefined": + return typeof object === "undefined"; + case "Date": + /* istanbul ignore else */ + if (type(object) === "Date") { + return object.getTime() === matcherOrValue.getTime(); + } + /* istanbul ignore next: this is basically the rest of the function, which is covered */ + break; + case "Array": + case "Int8Array": + case "Uint8Array": + case "Uint8ClampedArray": + case "Int16Array": + case "Uint16Array": + case "Int32Array": + case "Uint32Array": + case "Float32Array": + case "Float64Array": + return ( + isArrayType(matcherOrValue) && + arrayContains(object, matcherOrValue, match) + ); + case "Map": + /* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/ + if (!engineCanCompareMaps) { + throw new Error( + "The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances" + ); + } + + return ( + type(object) === "Map" && + arrayContains( + Array.from(object), + Array.from(matcherOrValue), + match + ) + ); + } + + switch (type(object)) { + case "null": + return false; + case "Set": + return isSubset(matcherOrValue, object, match); + } + + /* istanbul ignore else */ + if (matcherOrValue && typeof matcherOrValue === "object") { + if (matcherOrValue === object) { + return true; + } + if (typeof object !== "object") { + return false; + } + var prop; + // eslint-disable-next-line guard-for-in + for (prop in matcherOrValue) { + var value = object[prop]; + if ( + typeof value === "undefined" && + typeof object.getAttribute === "function" + ) { + value = object.getAttribute(prop); + } + if ( + matcherOrValue[prop] === null || + typeof matcherOrValue[prop] === "undefined" + ) { + if (value !== matcherOrValue[prop]) { + return false; + } + } else if ( + typeof value === "undefined" || + !deepEqual(value, matcherOrValue[prop]) + ) { + return false; + } + } + return true; + } + + /* istanbul ignore next */ + throw new Error("Matcher was an unknown or unsupported type"); + } + /* eslint-enable complexity */ + + forEach(Object.keys(createMatcher), function (key) { + match[key] = createMatcher[key]; + }); + + module.exports = match; + + },{"./create-matcher":63,"./deep-equal":72,"./is-array-type":76,"./is-subset":85,"@sinonjs/commons":95,"type-detect":151}],88:[function(require,module,exports){ + + /** + * @module samsam + */ + var identical = require("./identical"); + var isArguments = require("./is-arguments"); + var isElement = require("./is-element"); + var isNegZero = require("./is-neg-zero"); + var isSet = require("./is-set"); + var isMap = require("./is-map"); + var match = require("./match"); + var deepEqualCyclic = require("./deep-equal").use(match); + var createMatcher = require("./create-matcher"); + + module.exports = { + createMatcher: createMatcher, + deepEqual: deepEqualCyclic, + identical: identical, + isArguments: isArguments, + isElement: isElement, + isMap: isMap, + isNegZero: isNegZero, + isSet: isSet, + match: match, + }; + + },{"./create-matcher":63,"./deep-equal":72,"./identical":74,"./is-arguments":75,"./is-element":78,"./is-map":80,"./is-neg-zero":82,"./is-set":84,"./match":87}],89:[function(require,module,exports){ + arguments[4][42][0].apply(exports,arguments); + },{"./prototypes/array":97,"dup":42}],90:[function(require,module,exports){ + arguments[4][43][0].apply(exports,arguments); + },{"./function-name":93,"dup":43}],91:[function(require,module,exports){ + arguments[4][44][0].apply(exports,arguments); + },{"dup":44}],92:[function(require,module,exports){ + arguments[4][45][0].apply(exports,arguments); + },{"dup":45}],93:[function(require,module,exports){ + arguments[4][46][0].apply(exports,arguments); + },{"dup":46}],94:[function(require,module,exports){ + arguments[4][47][0].apply(exports,arguments); + },{"dup":47}],95:[function(require,module,exports){ + arguments[4][48][0].apply(exports,arguments); + },{"./called-in-order":89,"./class-name":90,"./deprecated":91,"./every":92,"./function-name":93,"./global":94,"./order-by-first-call":96,"./prototypes":100,"./type-of":106,"./value-to-string":107,"dup":48}],96:[function(require,module,exports){ + arguments[4][49][0].apply(exports,arguments); + },{"./prototypes/array":97,"dup":49}],97:[function(require,module,exports){ + arguments[4][50][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":50}],98:[function(require,module,exports){ + arguments[4][51][0].apply(exports,arguments); + },{"./throws-on-proto":105,"dup":51}],99:[function(require,module,exports){ + arguments[4][52][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":52}],100:[function(require,module,exports){ + arguments[4][53][0].apply(exports,arguments); + },{"./array":97,"./function":99,"./map":101,"./object":102,"./set":103,"./string":104,"dup":53}],101:[function(require,module,exports){ + arguments[4][54][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":54}],102:[function(require,module,exports){ + arguments[4][55][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":55}],103:[function(require,module,exports){ + arguments[4][56][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":56}],104:[function(require,module,exports){ + arguments[4][57][0].apply(exports,arguments); + },{"./copy-prototype-methods":98,"dup":57}],105:[function(require,module,exports){ + arguments[4][58][0].apply(exports,arguments); + },{"dup":58}],106:[function(require,module,exports){ + arguments[4][59][0].apply(exports,arguments); + },{"dup":59,"type-detect":151}],107:[function(require,module,exports){ + arguments[4][60][0].apply(exports,arguments); + },{"dup":60}],108:[function(require,module,exports){ + // This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + + var encoding = require("./lib/encoding.js"); + + module.exports = { + TextEncoder: encoding.TextEncoder, + TextDecoder: encoding.TextDecoder, + }; + + },{"./lib/encoding.js":110}],109:[function(require,module,exports){ + (function(global) { + + if (typeof module !== "undefined" && module.exports) { + module.exports = global; + } + + global["encoding-indexes"] = + { + "big5":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,17392,19506,17923,17830,17784,160359,19831,17843,162993,19682,163013,15253,18230,18244,19527,19520,148159,144919,160594,159371,159954,19543,172881,18255,17882,19589,162924,19719,19108,18081,158499,29221,154196,137827,146950,147297,26189,22267,null,32149,22813,166841,15860,38708,162799,23515,138590,23204,13861,171696,23249,23479,23804,26478,34195,170309,29793,29853,14453,138579,145054,155681,16108,153822,15093,31484,40855,147809,166157,143850,133770,143966,17162,33924,40854,37935,18736,34323,22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,36934,13542,29636,155065,29894,40903,22451,18735,21580,16689,145038,22552,31346,162661,35727,18094,159368,16769,155033,31662,140476,40904,140481,140489,140492,40905,34052,144827,16564,40906,17633,175615,25281,28782,40907,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,12736,12737,12738,12739,12740,131340,12741,131281,131277,12742,12743,131275,139240,12744,131274,12745,12746,12747,12748,131342,12749,12750,256,193,461,192,274,201,282,200,332,211,465,210,null,7870,null,7872,202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,null,7871,null,7873,234,609,9178,9179,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,172969,135493,null,25866,null,null,20029,28381,40270,37343,null,null,161589,25745,20250,20264,20392,20822,20852,20892,20964,21153,21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,36711,36718,29713,31996,32205,26950,31433,21031,null,null,null,null,37260,30904,37214,32956,null,36107,33014,133607,null,null,32927,40647,19661,40393,40460,19518,171510,159758,40458,172339,13761,null,28314,33342,29977,null,18705,39532,39567,40857,31111,164972,138698,132560,142054,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,163204,21797,null,134210,134421,151851,21904,142534,14828,131905,36422,150968,169189,16467,164030,30586,142392,14900,18389,164189,158194,151018,25821,134524,135092,134357,135412,25741,36478,134806,134155,135012,142505,164438,148691,null,134470,170573,164073,18420,151207,142530,39602,14951,169460,16365,13574,152263,169940,161992,142660,40302,38933,null,17369,155813,25780,21731,142668,142282,135287,14843,135279,157402,157462,162208,25834,151634,134211,36456,139681,166732,132913,null,18443,131497,16378,22643,142733,null,148936,132348,155799,134988,134550,21881,16571,17338,null,19124,141926,135325,33194,39157,134556,25465,14846,141173,36288,22177,25724,15939,null,173569,134665,142031,142537,null,135368,145858,14738,14854,164507,13688,155209,139463,22098,134961,142514,169760,13500,27709,151099,null,null,161140,142987,139784,173659,167117,134778,134196,157724,32659,135375,141315,141625,13819,152035,134796,135053,134826,16275,134960,134471,135503,134732,null,134827,134057,134472,135360,135485,16377,140950,25650,135085,144372,161337,142286,134526,134527,142417,142421,14872,134808,135367,134958,173618,158544,167122,167321,167114,38314,21708,33476,21945,null,171715,39974,39606,161630,142830,28992,33133,33004,23580,157042,33076,14231,21343,164029,37302,134906,134671,134775,134907,13789,151019,13833,134358,22191,141237,135369,134672,134776,135288,135496,164359,136277,134777,151120,142756,23124,135197,135198,135413,135414,22428,134673,161428,164557,135093,134779,151934,14083,135094,135552,152280,172733,149978,137274,147831,164476,22681,21096,13850,153405,31666,23400,18432,19244,40743,18919,39967,39821,154484,143677,22011,13810,22153,20008,22786,138177,194680,38737,131206,20059,20155,13630,23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,149737,32594,31035,31993,32595,156266,13505,null,156491,32770,32896,157202,158033,21341,34916,35265,161970,35744,36125,38021,38264,38271,38376,167439,38886,39029,39118,39134,39267,170000,40060,40479,40644,27503,63751,20023,131207,38429,25143,38050,null,20539,28158,171123,40870,15817,34959,147790,28791,23797,19232,152013,13657,154928,24866,166450,36775,37366,29073,26393,29626,144001,172295,15499,137600,19216,30948,29698,20910,165647,16393,27235,172730,16931,34319,133743,31274,170311,166634,38741,28749,21284,139390,37876,30425,166371,40871,30685,20131,20464,20668,20015,20247,40872,21556,32139,22674,22736,138678,24210,24217,24514,141074,25995,144377,26905,27203,146531,27903,null,29184,148741,29580,16091,150035,23317,29881,35715,154788,153237,31379,31724,31939,32364,33528,34199,40873,34960,40874,36537,40875,36815,34143,39392,37409,40876,167353,136255,16497,17058,23066,null,null,null,39016,26475,17014,22333,null,34262,149883,33471,160013,19585,159092,23931,158485,159678,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,143958,141206,17306,17718,null,23765,146202,35577,23672,15634,144721,23928,40882,29015,17752,147692,138787,19575,14712,13386,131492,158785,35532,20404,131641,22975,33132,38998,170234,24379,134047,null,139713,166253,16642,18107,168057,16135,40883,172469,16632,14294,18167,158790,16764,165554,160767,17773,14548,152730,17761,17691,19849,19579,19830,17898,16328,150287,13921,17630,17597,16877,23870,23880,23894,15868,14351,23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,26111,26195,15090,26258,15138,26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,28033,15599,28068,28081,28181,28184,28201,28294,166336,28347,28386,28378,40831,28392,28393,28452,28468,15686,147265,28545,28606,15722,15733,29111,23705,15754,28716,15761,28752,28756,28783,28799,28809,131877,17345,13809,134872,147159,22462,159443,28990,153568,13902,27042,166889,23412,31305,153825,169177,31333,31357,154028,31419,31408,31426,31427,29137,156813,16842,31450,31453,31466,16879,21682,154625,31499,31573,31529,152334,154878,31650,31599,33692,154548,158847,31696,33825,31634,31672,154912,15789,154725,33938,31738,31750,31797,154817,31812,31875,149634,31910,26237,148856,31945,31943,31974,31860,31987,31989,31950,32359,17693,159300,32093,159446,29837,32137,32171,28981,32179,32210,147543,155689,32228,15635,32245,137209,32229,164717,32285,155937,155994,32366,32402,17195,37996,32295,32576,32577,32583,31030,156368,39393,32663,156497,32675,136801,131176,17756,145254,17667,164666,32762,156809,32773,32776,32797,32808,32815,172167,158915,32827,32828,32865,141076,18825,157222,146915,157416,26405,32935,166472,33031,33050,22704,141046,27775,156824,151480,25831,136330,33304,137310,27219,150117,150165,17530,33321,133901,158290,146814,20473,136445,34018,33634,158474,149927,144688,137075,146936,33450,26907,194964,16859,34123,33488,33562,134678,137140,14017,143741,144730,33403,33506,33560,147083,159139,158469,158615,144846,15807,33565,21996,33669,17675,159141,33708,33729,33747,13438,159444,27223,34138,13462,159298,143087,33880,154596,33905,15827,17636,27303,33866,146613,31064,33960,158614,159351,159299,34014,33807,33681,17568,33939,34020,154769,16960,154816,17731,34100,23282,159385,17703,34163,17686,26559,34326,165413,165435,34241,159880,34306,136578,159949,194994,17770,34344,13896,137378,21495,160666,34430,34673,172280,34798,142375,34737,34778,34831,22113,34412,26710,17935,34885,34886,161248,146873,161252,34910,34972,18011,34996,34997,25537,35013,30583,161551,35207,35210,35238,35241,35239,35260,166437,35303,162084,162493,35484,30611,37374,35472,162393,31465,162618,147343,18195,162616,29052,35596,35615,152624,152933,35647,35660,35661,35497,150138,35728,35739,35503,136927,17941,34895,35995,163156,163215,195028,14117,163155,36054,163224,163261,36114,36099,137488,36059,28764,36113,150729,16080,36215,36265,163842,135188,149898,15228,164284,160012,31463,36525,36534,36547,37588,36633,36653,164709,164882,36773,37635,172703,133712,36787,18730,166366,165181,146875,24312,143970,36857,172052,165564,165121,140069,14720,159447,36919,165180,162494,36961,165228,165387,37032,165651,37060,165606,37038,37117,37223,15088,37289,37316,31916,166195,138889,37390,27807,37441,37474,153017,37561,166598,146587,166668,153051,134449,37676,37739,166625,166891,28815,23235,166626,166629,18789,37444,166892,166969,166911,37747,37979,36540,38277,38310,37926,38304,28662,17081,140922,165592,135804,146990,18911,27676,38523,38550,16748,38563,159445,25050,38582,30965,166624,38589,21452,18849,158904,131700,156688,168111,168165,150225,137493,144138,38705,34370,38710,18959,17725,17797,150249,28789,23361,38683,38748,168405,38743,23370,168427,38751,37925,20688,143543,143548,38793,38815,38833,38846,38848,38866,38880,152684,38894,29724,169011,38911,38901,168989,162170,19153,38964,38963,38987,39014,15118,160117,15697,132656,147804,153350,39114,39095,39112,39111,19199,159015,136915,21936,39137,39142,39148,37752,39225,150057,19314,170071,170245,39413,39436,39483,39440,39512,153381,14020,168113,170965,39648,39650,170757,39668,19470,39700,39725,165376,20532,39732,158120,14531,143485,39760,39744,171326,23109,137315,39822,148043,39938,39935,39948,171624,40404,171959,172434,172459,172257,172323,172511,40318,40323,172340,40462,26760,40388,139611,172435,172576,137531,172595,40249,172217,172724,40592,40597,40606,40610,19764,40618,40623,148324,40641,15200,14821,15645,20274,14270,166955,40706,40712,19350,37924,159138,40727,40726,40761,22175,22154,40773,39352,168075,38898,33919,40802,40809,31452,40846,29206,19390,149877,149947,29047,150008,148296,150097,29598,166874,137466,31135,166270,167478,37737,37875,166468,37612,37761,37835,166252,148665,29207,16107,30578,31299,28880,148595,148472,29054,137199,28835,137406,144793,16071,137349,152623,137208,14114,136955,137273,14049,137076,137425,155467,14115,136896,22363,150053,136190,135848,136134,136374,34051,145062,34051,33877,149908,160101,146993,152924,147195,159826,17652,145134,170397,159526,26617,14131,15381,15847,22636,137506,26640,16471,145215,147681,147595,147727,158753,21707,22174,157361,22162,135135,134056,134669,37830,166675,37788,20216,20779,14361,148534,20156,132197,131967,20299,20362,153169,23144,131499,132043,14745,131850,132116,13365,20265,131776,167603,131701,35546,131596,20120,20685,20749,20386,20227,150030,147082,20290,20526,20588,20609,20428,20453,20568,20732,20825,20827,20829,20830,28278,144789,147001,147135,28018,137348,147081,20904,20931,132576,17629,132259,132242,132241,36218,166556,132878,21081,21156,133235,21217,37742,18042,29068,148364,134176,149932,135396,27089,134685,29817,16094,29849,29716,29782,29592,19342,150204,147597,21456,13700,29199,147657,21940,131909,21709,134086,22301,37469,38644,37734,22493,22413,22399,13886,22731,23193,166470,136954,137071,136976,23084,22968,37519,23166,23247,23058,153926,137715,137313,148117,14069,27909,29763,23073,155267,23169,166871,132115,37856,29836,135939,28933,18802,37896,166395,37821,14240,23582,23710,24158,24136,137622,137596,146158,24269,23375,137475,137476,14081,137376,14045,136958,14035,33066,166471,138682,144498,166312,24332,24334,137511,137131,23147,137019,23364,34324,161277,34912,24702,141408,140843,24539,16056,140719,140734,168072,159603,25024,131134,131142,140827,24985,24984,24693,142491,142599,149204,168269,25713,149093,142186,14889,142114,144464,170218,142968,25399,173147,25782,25393,25553,149987,142695,25252,142497,25659,25963,26994,15348,143502,144045,149897,144043,21773,144096,137433,169023,26318,144009,143795,15072,16784,152964,166690,152975,136956,152923,152613,30958,143619,137258,143924,13412,143887,143746,148169,26254,159012,26219,19347,26160,161904,138731,26211,144082,144097,26142,153714,14545,145466,145340,15257,145314,144382,29904,15254,26511,149034,26806,26654,15300,27326,14435,145365,148615,27187,27218,27337,27397,137490,25873,26776,27212,15319,27258,27479,147392,146586,37792,37618,166890,166603,37513,163870,166364,37991,28069,28427,149996,28007,147327,15759,28164,147516,23101,28170,22599,27940,30786,28987,148250,148086,28913,29264,29319,29332,149391,149285,20857,150180,132587,29818,147192,144991,150090,149783,155617,16134,16049,150239,166947,147253,24743,16115,29900,29756,37767,29751,17567,159210,17745,30083,16227,150745,150790,16216,30037,30323,173510,15129,29800,166604,149931,149902,15099,15821,150094,16127,149957,149747,37370,22322,37698,166627,137316,20703,152097,152039,30584,143922,30478,30479,30587,149143,145281,14942,149744,29752,29851,16063,150202,150215,16584,150166,156078,37639,152961,30750,30861,30856,30930,29648,31065,161601,153315,16654,31131,33942,31141,27181,147194,31290,31220,16750,136934,16690,37429,31217,134476,149900,131737,146874,137070,13719,21867,13680,13994,131540,134157,31458,23129,141045,154287,154268,23053,131675,30960,23082,154566,31486,16889,31837,31853,16913,154547,155324,155302,31949,150009,137136,31886,31868,31918,27314,32220,32263,32211,32590,156257,155996,162632,32151,155266,17002,158581,133398,26582,131150,144847,22468,156690,156664,149858,32733,31527,133164,154345,154947,31500,155150,39398,34373,39523,27164,144447,14818,150007,157101,39455,157088,33920,160039,158929,17642,33079,17410,32966,33033,33090,157620,39107,158274,33378,33381,158289,33875,159143,34320,160283,23174,16767,137280,23339,137377,23268,137432,34464,195004,146831,34861,160802,23042,34926,20293,34951,35007,35046,35173,35149,153219,35156,161669,161668,166901,166873,166812,166393,16045,33955,18165,18127,14322,35389,35356,169032,24397,37419,148100,26068,28969,28868,137285,40301,35999,36073,163292,22938,30659,23024,17262,14036,36394,36519,150537,36656,36682,17140,27736,28603,140065,18587,28537,28299,137178,39913,14005,149807,37051,37015,21873,18694,37307,37892,166475,16482,166652,37927,166941,166971,34021,35371,38297,38311,38295,38294,167220,29765,16066,149759,150082,148458,16103,143909,38543,167655,167526,167525,16076,149997,150136,147438,29714,29803,16124,38721,168112,26695,18973,168083,153567,38749,37736,166281,166950,166703,156606,37562,23313,35689,18748,29689,147995,38811,38769,39224,134950,24001,166853,150194,38943,169178,37622,169431,37349,17600,166736,150119,166756,39132,166469,16128,37418,18725,33812,39227,39245,162566,15869,39323,19311,39338,39516,166757,153800,27279,39457,23294,39471,170225,19344,170312,39356,19389,19351,37757,22642,135938,22562,149944,136424,30788,141087,146872,26821,15741,37976,14631,24912,141185,141675,24839,40015,40019,40059,39989,39952,39807,39887,171565,39839,172533,172286,40225,19630,147716,40472,19632,40204,172468,172269,172275,170287,40357,33981,159250,159711,158594,34300,17715,159140,159364,159216,33824,34286,159232,145367,155748,31202,144796,144960,18733,149982,15714,37851,37566,37704,131775,30905,37495,37965,20452,13376,36964,152925,30781,30804,30902,30795,137047,143817,149825,13978,20338,28634,28633,28702,28702,21524,147893,22459,22771,22410,40214,22487,28980,13487,147884,29163,158784,151447,23336,137141,166473,24844,23246,23051,17084,148616,14124,19323,166396,37819,37816,137430,134941,33906,158912,136211,148218,142374,148417,22932,146871,157505,32168,155995,155812,149945,149899,166394,37605,29666,16105,29876,166755,137375,16097,150195,27352,29683,29691,16086,150078,150164,137177,150118,132007,136228,149989,29768,149782,28837,149878,37508,29670,37727,132350,37681,166606,166422,37766,166887,153045,18741,166530,29035,149827,134399,22180,132634,134123,134328,21762,31172,137210,32254,136898,150096,137298,17710,37889,14090,166592,149933,22960,137407,137347,160900,23201,14050,146779,14000,37471,23161,166529,137314,37748,15565,133812,19094,14730,20724,15721,15692,136092,29045,17147,164376,28175,168164,17643,27991,163407,28775,27823,15574,147437,146989,28162,28428,15727,132085,30033,14012,13512,18048,16090,18545,22980,37486,18750,36673,166940,158656,22546,22472,14038,136274,28926,148322,150129,143331,135856,140221,26809,26983,136088,144613,162804,145119,166531,145366,144378,150687,27162,145069,158903,33854,17631,17614,159014,159057,158850,159710,28439,160009,33597,137018,33773,158848,159827,137179,22921,23170,137139,23137,23153,137477,147964,14125,23023,137020,14023,29070,37776,26266,148133,23150,23083,148115,27179,147193,161590,148571,148170,28957,148057,166369,20400,159016,23746,148686,163405,148413,27148,148054,135940,28838,28979,148457,15781,27871,194597,150095,32357,23019,23855,15859,24412,150109,137183,32164,33830,21637,146170,144128,131604,22398,133333,132633,16357,139166,172726,28675,168283,23920,29583,31955,166489,168992,20424,32743,29389,29456,162548,29496,29497,153334,29505,29512,16041,162584,36972,29173,149746,29665,33270,16074,30476,16081,27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,151388,29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,23646,30654,30667,22770,30744,28857,30748,16552,30777,30791,30801,30822,33864,152885,31027,26627,31026,16643,16649,31121,31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,31981,36755,28864,134351,32207,32212,32208,32253,32686,32692,29343,17303,32800,32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,38469,34699,17926,17943,34990,35071,35108,35143,35217,162151,35369,35384,35476,35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,39809,39901,39921,39924,19565,39968,14191,138178,40265,39994,40702,22096,40339,40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,40696,31432,40772,131220,131767,132000,26906,38083,22956,132311,22592,38081,14265,132565,132629,132726,136890,22359,29043,133826,133837,134079,21610,194619,134091,21662,134139,134203,134227,134245,134268,24807,134285,22138,134325,134365,134381,134511,134578,134600,26965,39983,34725,134660,134670,134871,135056,134957,134771,23584,135100,24075,135260,135247,135286,26398,135291,135304,135318,13895,135359,135379,135471,135483,21348,33965,135907,136053,135990,35713,136567,136729,137155,137159,20088,28859,137261,137578,137773,137797,138282,138352,138412,138952,25283,138965,139029,29080,26709,139333,27113,14024,139900,140247,140282,141098,141425,141647,33533,141671,141715,142037,35237,142056,36768,142094,38840,142143,38983,39613,142412,null,142472,142519,154600,142600,142610,142775,142741,142914,143220,143308,143411,143462,144159,144350,24497,26184,26303,162425,144743,144883,29185,149946,30679,144922,145174,32391,131910,22709,26382,26904,146087,161367,155618,146961,147129,161278,139418,18640,19128,147737,166554,148206,148237,147515,148276,148374,150085,132554,20946,132625,22943,138920,15294,146687,148484,148694,22408,149108,14747,149295,165352,170441,14178,139715,35678,166734,39382,149522,149755,150037,29193,150208,134264,22885,151205,151430,132985,36570,151596,21135,22335,29041,152217,152601,147274,150183,21948,152646,152686,158546,37332,13427,152895,161330,152926,18200,152930,152934,153543,149823,153693,20582,13563,144332,24798,153859,18300,166216,154286,154505,154630,138640,22433,29009,28598,155906,162834,36950,156082,151450,35682,156674,156746,23899,158711,36662,156804,137500,35562,150006,156808,147439,156946,19392,157119,157365,141083,37989,153569,24981,23079,194765,20411,22201,148769,157436,20074,149812,38486,28047,158909,13848,35191,157593,157806,156689,157790,29151,157895,31554,168128,133649,157990,37124,158009,31301,40432,158202,39462,158253,13919,156777,131105,31107,158260,158555,23852,144665,33743,158621,18128,158884,30011,34917,159150,22710,14108,140685,159819,160205,15444,160384,160389,37505,139642,160395,37680,160486,149968,27705,38047,160848,134904,34855,35061,141606,164979,137137,28344,150058,137248,14756,14009,23568,31203,17727,26294,171181,170148,35139,161740,161880,22230,16607,136714,14753,145199,164072,136133,29101,33638,162269,168360,23143,19639,159919,166315,162301,162314,162571,163174,147834,31555,31102,163849,28597,172767,27139,164632,21410,159239,37823,26678,38749,164207,163875,158133,136173,143919,163912,23941,166960,163971,22293,38947,166217,23979,149896,26046,27093,21458,150181,147329,15377,26422,163984,164084,164142,139169,164175,164233,164271,164378,164614,164655,164746,13770,164968,165546,18682,25574,166230,30728,37461,166328,17394,166375,17375,166376,166726,166868,23032,166921,36619,167877,168172,31569,168208,168252,15863,168286,150218,36816,29327,22155,169191,169449,169392,169400,169778,170193,170313,170346,170435,170536,170766,171354,171419,32415,171768,171811,19620,38215,172691,29090,172799,19857,36882,173515,19868,134300,36798,21953,36794,140464,36793,150163,17673,32383,28502,27313,20202,13540,166700,161949,14138,36480,137205,163876,166764,166809,162366,157359,15851,161365,146615,153141,153942,20122,155265,156248,22207,134765,36366,23405,147080,150686,25566,25296,137206,137339,25904,22061,154698,21530,152337,15814,171416,19581,22050,22046,32585,155352,22901,146752,34672,19996,135146,134473,145082,33047,40286,36120,30267,40005,30286,30649,37701,21554,33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,134813,13774,22021,22001,26353,164578,13869,30004,22000,21946,21655,21874,134209,134294,24272,151880,134774,142434,134818,40619,32090,21982,135285,25245,38765,21652,36045,29174,37238,25596,25529,25598,21865,142147,40050,143027,20890,13535,134567,20903,21581,21790,21779,30310,36397,157834,30129,32950,34820,34694,35015,33206,33820,135361,17644,29444,149254,23440,33547,157843,22139,141044,163119,147875,163187,159440,160438,37232,135641,37384,146684,173737,134828,134905,29286,138402,18254,151490,163833,135147,16634,40029,25887,142752,18675,149472,171388,135148,134666,24674,161187,135149,null,155720,135559,29091,32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,149016,22682,150382,33325,21579,22442,154261,133497,null,14930,140389,29556,171692,19721,39917,146686,171824,19547,151465,169374,171998,33884,146870,160434,157619,145184,25390,32037,147191,146988,14890,36872,21196,15988,13946,17897,132238,30272,23280,134838,30842,163630,22695,16575,22140,39819,23924,30292,173108,40581,19681,30201,14331,24857,143578,148466,null,22109,135849,22439,149859,171526,21044,159918,13741,27722,40316,31830,39737,22494,137068,23635,25811,169168,156469,160100,34477,134440,159010,150242,134513,null,20990,139023,23950,38659,138705,40577,36940,31519,39682,23761,31651,25192,25397,39679,31695,39722,31870,39726,31810,31878,39957,31740,39689,40727,39963,149822,40794,21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,38465,27008,20646,30022,137069,39386,21107,null,37209,38529,37212,null,37201,167575,25471,159011,27338,22033,37262,30074,25221,132092,29519,31856,154657,146685,null,149785,30422,39837,20010,134356,33726,34882,null,23626,27072,20717,22394,21023,24053,20174,27697,131570,20281,21660,21722,21146,36226,13822,24332,13811,null,27474,37244,40869,39831,38958,39092,39610,40616,40580,29050,31508,null,27642,34840,32632,null,22048,173642,36471,40787,null,36308,36431,40476,36353,25218,164733,36392,36469,31443,150135,31294,30936,27882,35431,30215,166490,40742,27854,34774,30147,172722,30803,194624,36108,29410,29553,35629,29442,29937,36075,150203,34351,24506,34976,17591,null,137275,159237,null,35454,140571,null,24829,30311,39639,40260,37742,39823,34805,null,34831,36087,29484,38689,39856,13782,29362,19463,31825,39242,155993,24921,19460,40598,24957,null,22367,24943,25254,25145,25294,14940,25058,21418,144373,25444,26626,13778,23895,166850,36826,167481,null,20697,138566,30982,21298,38456,134971,16485,null,30718,null,31938,155418,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,160902,32859,29936,33027,30500,35209,157644,30035,159441,34729,34766,33224,34700,35401,36013,35651,30507,29944,34010,13877,27058,36262,null,35241,29800,28089,34753,147473,29927,15835,29046,24740,24988,15569,29026,24695,null,32625,166701,29264,24809,19326,21024,15384,146631,155351,161366,152881,137540,135934,170243,159196,159917,23745,156077,166415,145015,131310,157766,151310,17762,23327,156492,40784,40614,156267,12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,12321,12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19968,20057,19969,19971,20035,20061,20102,20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,20800,20995,21242,21315,21449,21475,22303,22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,20887,20982,20998,20999,21000,21243,21246,21247,21270,21305,21320,21319,21317,21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,29916,29926,29976,29983,29992,29993,30000,30001,30002,30003,30091,30333,30382,30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,20073,20121,20132,20134,20133,20223,20233,20249,20234,20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,22930,22952,22942,22947,22937,22934,22925,22948,22931,22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,21658,21602,21608,21643,21629,21646,22266,22403,22391,22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,32937,32948,32938,32943,33253,33278,33293,33459,33437,33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,22865,22863,22862,22864,23004,23000,23039,23011,23016,23043,23013,23018,23002,23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,27954,27946,27969,27941,27916,27953,27934,27927,27963,27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,31361,31487,31485,31869,32002,32005,32000,32009,32007,32004,32006,32568,32654,32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,35331,35998,36000,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,21769,21742,21738,21734,21799,21767,21757,21775,22275,22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,32020,32016,32021,32026,32028,32013,32025,32027,32570,32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,24246,24245,24254,24373,24375,24407,24428,24425,24427,24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,33333,33335,33334,33337,33678,33694,33688,33656,33698,33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,25954,25955,26001,26000,26031,26222,26224,26228,26230,26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,36024,36234,36229,36225,36302,36317,36299,36314,36305,36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,28998,29032,29014,29242,29266,29495,29509,29503,29502,29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,39156,39165,39166,39347,39345,39348,39649,40169,40578,40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,32862,32858,32903,33104,33152,33167,33160,33162,33151,33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,26292,26289,27171,27167,27112,27137,27166,27161,27133,27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,39389,39376,39391,39387,39377,39381,39378,39385,39607,39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,36986,37172,37266,37664,37686,37624,37683,37679,37666,37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,35140,35128,35133,35244,35598,35607,35609,35611,35594,35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37000,37291,37292,37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,40672,40725,40748,20787,22181,22750,22751,22754,23541,40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,38876,38907,39006,39000,39003,39100,39237,39241,39446,39449,39693,39912,39911,39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,25885,25884,26005,26345,27387,27396,27386,27570,28748,29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,38002,38000,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,24027,12083,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,710,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,65339,65341,10045,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8679,8632,8633,12751,131276,20058,131210,20994,17553,40880,20872,40881,161287,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,12003,null,null,null,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,32917,32921,32912,32914,32924,33424,33423,33413,33422,33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,27842,27834,27843,27846,27885,27890,27858,27869,27828,27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,24631,24633,24660,24690,24670,24645,24659,24647,24649,24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,32969,32975,32983,32998,32973,33279,33313,33428,33497,33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,26702,26692,26676,26653,26642,26644,26662,26664,26670,26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28000,28055,28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,33607,33605,33612,33619,33566,33580,33611,33575,33608,34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,24720,24710,24766,24752,24762,24787,24788,24783,24804,24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,31531,31533,31535,31538,31544,31514,31523,31892,31896,31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,21902,22284,22569,22583,22553,22558,22567,22563,22568,22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,28252,28257,28209,28200,28256,28273,28267,28217,28194,28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,35000,35008,35006,34998,35004,34999,35005,34994,35073,35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,24886,24882,24878,24902,24879,24911,24873,24896,25120,37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,27002,26952,26953,26933,26988,26931,26941,26981,26864,27000,26932,26985,26944,26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,30873,30848,30870,30843,31100,31106,31101,31097,31249,31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,37470,37507,37422,37450,37446,37485,37484,37455,37472,37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,27050,27041,27038,27097,27031,27024,27074,27061,27045,27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,33972,33985,33997,33962,33946,33969,34000,33949,33959,33979,33954,33940,33991,33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,34587,34627,34604,34625,34622,34630,34592,34610,34602,34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,25005,24991,24978,25002,24993,24973,24934,25011,25133,25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,33362,33360,33358,33361,34084,34107,34063,34048,34089,34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,39382,39384,39371,39383,39372,39603,39660,39659,39667,39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,24296,24293,24395,24508,24989,25000,24982,25029,25012,25030,25025,25036,25018,25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,30261,30258,30256,30395,30438,30618,30621,30625,30620,30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,37634,37668,37631,37673,37689,37685,37674,37652,37644,37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,31730,31744,31743,31739,31758,31732,31755,31731,31746,31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,39421,39422,39420,39427,39614,39678,39677,39681,39676,39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,22169,22896,23356,23657,23658,24000,24173,24174,25048,25055,25069,25070,25073,25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,35621,35639,35622,35638,35630,35620,35643,35645,35642,35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,31788,31803,31980,31978,32374,32373,32376,32368,32375,32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,26079,26344,26339,26340,27379,27376,27370,27368,27385,27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,40000,39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,28740,28746,28744,28745,28741,28742,29213,29210,29209,29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,39502,39507,39508,39500,39503,39496,39498,39497,39506,39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,31990,32410,32408,32411,32409,33248,33249,34374,34375,34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,9584,9583,65517,132423,37595,132575,147397,34124,17077,29679,20917,13897,149826,166372,37700,137691,33518,146632,30780,26436,25311,149811,166314,131744,158643,135941,20395,140525,20488,159017,162436,144896,150193,140563,20521,131966,24484,131968,131911,28379,132127,20605,20737,13434,20750,39020,14147,33814,149924,132231,20832,144308,20842,134143,139516,131813,140592,132494,143923,137603,23426,34685,132531,146585,20914,20920,40244,20937,20943,20945,15580,20947,150182,20915,20962,21314,20973,33741,26942,145197,24443,21003,21030,21052,21173,21079,21140,21177,21189,31765,34114,21216,34317,158483,21253,166622,21833,28377,147328,133460,147436,21299,21316,134114,27851,136998,26651,29653,24650,16042,14540,136936,29149,17570,21357,21364,165547,21374,21375,136598,136723,30694,21395,166555,21408,21419,21422,29607,153458,16217,29596,21441,21445,27721,20041,22526,21465,15019,134031,21472,147435,142755,21494,134263,21523,28793,21803,26199,27995,21613,158547,134516,21853,21647,21668,18342,136973,134877,15796,134477,166332,140952,21831,19693,21551,29719,21894,21929,22021,137431,147514,17746,148533,26291,135348,22071,26317,144010,26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,166758,13859,135759,22342,147877,27758,28811,22338,14001,158846,22502,136214,22531,136276,148323,22566,150517,22620,22698,13665,22752,22748,135740,22779,23551,22339,172368,148088,37843,13729,22815,26790,14019,28249,136766,23076,21843,136850,34053,22985,134478,158849,159018,137180,23001,137211,137138,159142,28017,137256,136917,23033,159301,23211,23139,14054,149929,23159,14088,23190,29797,23251,159649,140628,15749,137489,14130,136888,24195,21200,23414,25992,23420,162318,16388,18525,131588,23509,24928,137780,154060,132517,23539,23453,19728,23557,138052,23571,29646,23572,138405,158504,23625,18653,23685,23785,23791,23947,138745,138807,23824,23832,23878,138916,23738,24023,33532,14381,149761,139337,139635,33415,14390,15298,24110,27274,24181,24186,148668,134355,21414,20151,24272,21416,137073,24073,24308,164994,24313,24315,14496,24316,26686,37915,24333,131521,194708,15070,18606,135994,24378,157832,140240,24408,140401,24419,38845,159342,24434,37696,166454,24487,23990,15711,152144,139114,159992,140904,37334,131742,166441,24625,26245,137335,14691,15815,13881,22416,141236,31089,15936,24734,24740,24755,149890,149903,162387,29860,20705,23200,24932,33828,24898,194726,159442,24961,20980,132694,24967,23466,147383,141407,25043,166813,170333,25040,14642,141696,141505,24611,24924,25886,25483,131352,25285,137072,25301,142861,25452,149983,14871,25656,25592,136078,137212,25744,28554,142902,38932,147596,153373,25825,25829,38011,14950,25658,14935,25933,28438,150056,150051,25989,25965,25951,143486,26037,149824,19255,26065,16600,137257,26080,26083,24543,144384,26136,143863,143864,26180,143780,143781,26187,134773,26215,152038,26227,26228,138813,143921,165364,143816,152339,30661,141559,39332,26370,148380,150049,15147,27130,145346,26462,26471,26466,147917,168173,26583,17641,26658,28240,37436,26625,144358,159136,26717,144495,27105,27147,166623,26995,26819,144845,26881,26880,15666,14849,144956,15232,26540,26977,166474,17148,26934,27032,15265,132041,33635,20624,27129,144985,139562,27205,145155,27293,15347,26545,27336,168348,15373,27421,133411,24798,27445,27508,141261,28341,146139,132021,137560,14144,21537,146266,27617,147196,27612,27703,140427,149745,158545,27738,33318,27769,146876,17605,146877,147876,149772,149760,146633,14053,15595,134450,39811,143865,140433,32655,26679,159013,159137,159211,28054,27996,28284,28420,149887,147589,159346,34099,159604,20935,27804,28189,33838,166689,28207,146991,29779,147330,31180,28239,23185,143435,28664,14093,28573,146992,28410,136343,147517,17749,37872,28484,28508,15694,28532,168304,15675,28575,147780,28627,147601,147797,147513,147440,147380,147775,20959,147798,147799,147776,156125,28747,28798,28839,28801,28876,28885,28886,28895,16644,15848,29108,29078,148087,28971,28997,23176,29002,29038,23708,148325,29007,37730,148161,28972,148570,150055,150050,29114,166888,28861,29198,37954,29205,22801,37955,29220,37697,153093,29230,29248,149876,26813,29269,29271,15957,143428,26637,28477,29314,29482,29483,149539,165931,18669,165892,29480,29486,29647,29610,134202,158254,29641,29769,147938,136935,150052,26147,14021,149943,149901,150011,29687,29717,26883,150054,29753,132547,16087,29788,141485,29792,167602,29767,29668,29814,33721,29804,14128,29812,37873,27180,29826,18771,150156,147807,150137,166799,23366,166915,137374,29896,137608,29966,29929,29982,167641,137803,23511,167596,37765,30029,30026,30055,30062,151426,16132,150803,30094,29789,30110,30132,30210,30252,30289,30287,30319,30326,156661,30352,33263,14328,157969,157966,30369,30373,30391,30412,159647,33890,151709,151933,138780,30494,30502,30528,25775,152096,30552,144044,30639,166244,166248,136897,30708,30729,136054,150034,26826,30895,30919,30931,38565,31022,153056,30935,31028,30897,161292,36792,34948,166699,155779,140828,31110,35072,26882,31104,153687,31133,162617,31036,31145,28202,160038,16040,31174,168205,31188], + "euc-kr":[44034,44035,44037,44038,44043,44044,44045,44046,44047,44056,44062,44063,44065,44066,44067,44069,44070,44071,44072,44073,44074,44075,44078,44082,44083,44084,null,null,null,null,null,null,44085,44086,44087,44090,44091,44093,44094,44095,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44108,44110,44111,44112,44113,44114,44115,44117,null,null,null,null,null,null,44118,44119,44121,44122,44123,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44146,44147,44149,44150,44153,44155,44156,44157,44158,44159,44162,44167,44168,44173,44174,44175,44177,44178,44179,44181,44182,44183,44184,44185,44186,44187,44190,44194,44195,44196,44197,44198,44199,44203,44205,44206,44209,44210,44211,44212,44213,44214,44215,44218,44222,44223,44224,44226,44227,44229,44230,44231,44233,44234,44235,44237,44238,44239,44240,44241,44242,44243,44244,44246,44248,44249,44250,44251,44252,44253,44254,44255,44258,44259,44261,44262,44265,44267,44269,44270,44274,44276,44279,44280,44281,44282,44283,44286,44287,44289,44290,44291,44293,44295,44296,44297,44298,44299,44302,44304,44306,44307,44308,44309,44310,44311,44313,44314,44315,44317,44318,44319,44321,44322,44323,44324,44325,44326,44327,44328,44330,44331,44334,44335,44336,44337,44338,44339,null,null,null,null,null,null,44342,44343,44345,44346,44347,44349,44350,44351,44352,44353,44354,44355,44358,44360,44362,44363,44364,44365,44366,44367,44369,44370,44371,44373,44374,44375,null,null,null,null,null,null,44377,44378,44379,44380,44381,44382,44383,44384,44386,44388,44389,44390,44391,44392,44393,44394,44395,44398,44399,44401,44402,44407,44408,44409,44410,44414,44416,44419,44420,44421,44422,44423,44426,44427,44429,44430,44431,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44446,44447,44448,44449,44450,44451,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44472,44473,44474,44475,44476,44477,44478,44479,44482,44483,44485,44486,44487,44489,44490,44491,44492,44493,44494,44495,44498,44500,44501,44502,44503,44504,44505,44506,44507,44509,44510,44511,44513,44514,44515,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44538,44539,44541,44542,44546,44547,44548,44549,44550,44551,44554,44556,44558,44559,44560,44561,44562,44563,44565,44566,44567,44568,44569,44570,44571,44572,null,null,null,null,null,null,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44594,44595,44597,44598,44601,44603,44604,null,null,null,null,null,null,44605,44606,44607,44610,44612,44615,44616,44617,44619,44623,44625,44626,44627,44629,44631,44632,44633,44634,44635,44638,44642,44643,44644,44646,44647,44650,44651,44653,44654,44655,44657,44658,44659,44660,44661,44662,44663,44666,44670,44671,44672,44673,44674,44675,44678,44679,44680,44681,44682,44683,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44735,44737,44738,44739,44741,44742,44743,44744,44745,44746,44747,44750,44754,44755,44756,44757,44758,44759,44762,44763,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44777,44778,44780,44782,44783,44784,44785,44786,44787,44789,44790,44791,44793,44794,44795,44797,44798,44799,44800,44801,44802,44803,44804,44805,null,null,null,null,null,null,44806,44809,44810,44811,44812,44814,44815,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,null,null,null,null,null,null,44836,44837,44838,44839,44840,44841,44842,44843,44846,44847,44849,44851,44853,44854,44855,44856,44857,44858,44859,44862,44864,44868,44869,44870,44871,44874,44875,44876,44877,44878,44879,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44894,44895,44896,44897,44898,44899,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44922,44923,44924,44925,44926,44927,44929,44930,44931,44933,44934,44935,44937,44938,44939,44940,44941,44942,44943,44946,44947,44948,44950,44951,44952,44953,44954,44955,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44986,44987,44989,44990,44991,44993,44994,44995,44996,44997,44998,45002,45004,45007,45008,45009,45010,45011,45013,45014,45015,45016,45017,45018,45019,45021,45022,45023,45024,45025,null,null,null,null,null,null,45026,45027,45028,45029,45030,45031,45034,45035,45036,45037,45038,45039,45042,45043,45045,45046,45047,45049,45050,45051,45052,45053,45054,45055,45058,45059,null,null,null,null,null,null,45061,45062,45063,45064,45065,45066,45067,45069,45070,45071,45073,45074,45075,45077,45078,45079,45080,45081,45082,45083,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45126,45127,45129,45131,45133,45135,45136,45137,45138,45142,45144,45146,45147,45148,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45182,45183,45185,45186,45187,45189,45190,45191,45192,45193,45194,45195,45198,45200,45202,45203,45204,45205,45206,45207,45211,45213,45214,45219,45220,45221,45222,45223,45226,45232,45234,45238,45239,45241,45242,45243,45245,45246,45247,45248,45249,45250,45251,45254,45258,45259,45260,45261,45262,45263,45266,null,null,null,null,null,null,45267,45269,45270,45271,45273,45274,45275,45276,45277,45278,45279,45281,45282,45283,45284,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,null,null,null,null,null,null,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45322,45325,45326,45327,45329,45332,45333,45334,45335,45338,45342,45343,45344,45345,45346,45350,45351,45353,45354,45355,45357,45358,45359,45360,45361,45362,45363,45366,45370,45371,45372,45373,45374,45375,45378,45379,45381,45382,45383,45385,45386,45387,45388,45389,45390,45391,45394,45395,45398,45399,45401,45402,45403,45405,45406,45407,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45434,45435,45437,45438,45439,45441,45443,45444,45445,45446,45447,45450,45452,45454,45455,45456,45457,45461,45462,45463,45465,45466,45467,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,null,null,null,null,null,null,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45517,45518,45519,45521,45522,45523,45525,null,null,null,null,null,null,45526,45527,45528,45529,45530,45531,45534,45536,45537,45538,45539,45540,45541,45542,45543,45546,45547,45549,45550,45551,45553,45554,45555,45556,45557,45558,45559,45560,45562,45564,45566,45567,45568,45569,45570,45571,45574,45575,45577,45578,45581,45582,45583,45584,45585,45586,45587,45590,45592,45594,45595,45596,45597,45598,45599,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45621,45622,45623,45624,45625,45626,45627,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45657,45658,45659,45661,45662,45663,45665,45666,45667,45668,45669,45670,45671,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45686,45687,45688,45689,45690,45691,45693,45694,45695,45696,45697,45698,45699,45702,45703,45704,45706,45707,45708,45709,45710,null,null,null,null,null,null,45711,45714,45715,45717,45718,45719,45723,45724,45725,45726,45727,45730,45732,45735,45736,45737,45739,45741,45742,45743,45745,45746,45747,45749,45750,45751,null,null,null,null,null,null,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45770,45771,45773,45774,45775,45777,45779,45780,45781,45782,45783,45786,45788,45790,45791,45792,45793,45795,45799,45801,45802,45808,45809,45810,45814,45820,45821,45822,45826,45827,45829,45830,45831,45833,45834,45835,45836,45837,45838,45839,45842,45846,45847,45848,45849,45850,45851,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45911,45913,45914,45917,45920,45921,45922,45923,45926,45928,45930,45932,45933,45935,45938,45939,45941,45942,45943,45945,45946,45947,45948,45949,45950,45951,45954,45958,45959,45960,45961,45962,45963,45965,null,null,null,null,null,null,45966,45967,45969,45970,45971,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45986,45987,45988,45989,45990,45991,45993,45994,45995,45997,null,null,null,null,null,null,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46022,46023,46025,46026,46029,46031,46033,46034,46035,46038,46040,46042,46044,46046,46047,46049,46050,46051,46053,46054,46055,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46097,46098,46099,46100,46101,46102,46103,46105,46106,46107,46109,46110,46111,46113,46114,46115,46116,46117,46118,46119,46122,46124,46125,46126,46127,46128,46129,46130,46131,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46162,46163,46165,46166,46167,46169,46170,46171,46172,46173,46174,46175,46178,46180,46182,null,null,null,null,null,null,46183,46184,46185,46186,46187,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46209,46210,null,null,null,null,null,null,46211,46212,46213,46214,46215,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46238,46239,46240,46241,46242,46243,46245,46246,46247,46249,46250,46251,46253,46254,46255,46256,46257,46258,46259,46260,46262,46264,46266,46267,46268,46269,46270,46271,46273,46274,46275,46277,46278,46279,46281,46282,46283,46284,46285,46286,46287,46289,46290,46291,46292,46294,46295,46296,46297,46298,46299,46302,46303,46305,46306,46309,46311,46312,46313,46314,46315,46318,46320,46322,46323,46324,46325,46326,46327,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46358,46359,46361,46362,46365,46366,46367,46368,46369,46370,46371,46374,46379,46380,46381,46382,46383,46386,46387,46389,46390,46391,46393,46394,46395,46396,46397,46398,46399,46402,46406,null,null,null,null,null,null,46407,46408,46409,46410,46414,46415,46417,46418,46419,46421,46422,46423,46424,46425,46426,46427,46430,46434,46435,46436,46437,46438,46439,46440,46441,46442,null,null,null,null,null,null,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46498,46499,46501,46502,46503,46505,46508,46509,46510,46511,46514,46518,46519,46520,46521,46522,46526,46527,46529,46530,46531,46533,46534,46535,46536,46537,46538,46539,46542,46546,46547,46548,46549,46550,46551,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46610,46611,46613,46614,46615,46617,46618,46619,46620,46621,null,null,null,null,null,null,46622,46623,46624,46625,46626,46627,46628,46630,46631,46632,46633,46634,46635,46637,46638,46639,46640,46641,46642,46643,46645,46646,46647,46648,46649,46650,null,null,null,null,null,null,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46693,46694,46695,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46750,46751,46753,46754,46755,46757,46758,46759,46760,46761,46762,46765,46766,46767,46768,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46805,46806,46807,46808,46809,46810,46811,46812,46813,null,null,null,null,null,null,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46833,46834,46835,46837,46838,46839,46841,46842,null,null,null,null,null,null,46843,46844,46845,46846,46847,46850,46851,46852,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46890,46891,46893,46894,46897,46898,46899,46900,46901,46902,46903,46906,46908,46909,46910,46911,46912,46913,46914,46915,46917,46918,46919,46921,46922,46923,46925,46926,46927,46928,46929,46930,46931,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46945,46946,46947,46949,46950,46951,46953,46954,46955,46956,46957,46958,46959,46962,46964,46966,46967,46968,46969,46970,46971,46974,46975,46977,46978,46979,46981,46982,46983,46984,46985,46986,46987,46990,46995,46996,46997,47002,47003,47005,47006,47007,47009,47010,47011,47012,47013,47014,47015,47018,47022,47023,47024,47025,47026,47027,47030,47031,47033,47034,47035,47036,47037,47038,47039,47040,47041,null,null,null,null,null,null,47042,47043,47044,47045,47046,47048,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,null,null,null,null,null,null,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47086,47087,47089,47090,47091,47093,47094,47095,47096,47097,47098,47099,47102,47106,47107,47108,47109,47110,47114,47115,47117,47118,47119,47121,47122,47123,47124,47125,47126,47127,47130,47132,47134,47135,47136,47137,47138,47139,47142,47143,47145,47146,47147,47149,47150,47151,47152,47153,47154,47155,47158,47162,47163,47164,47165,47166,47167,47169,47170,47171,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47186,47188,47189,47190,47191,47192,47193,47194,47195,47198,47199,47201,47202,47203,47205,47206,47207,47208,47209,47210,47211,47214,47216,47218,47219,47220,47221,47222,47223,47225,47226,47227,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,null,null,null,null,null,null,47264,47265,47266,47267,47268,47269,47270,47271,47273,47274,47275,47276,47277,47278,47279,47281,47282,47283,47285,47286,47287,47289,47290,47291,47292,47293,null,null,null,null,null,null,47294,47295,47298,47300,47302,47303,47304,47305,47306,47307,47309,47310,47311,47313,47314,47315,47317,47318,47319,47320,47321,47322,47323,47324,47326,47328,47330,47331,47332,47333,47334,47335,47338,47339,47341,47342,47343,47345,47346,47347,47348,47349,47350,47351,47354,47356,47358,47359,47360,47361,47362,47363,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47385,47386,47387,47388,47389,47390,47391,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47422,47423,47425,47426,47427,47429,47430,47431,47432,47433,47434,47435,47437,47438,47440,47442,47443,47444,47445,47446,47447,47450,47451,47453,47454,47455,47457,47458,47459,47460,47461,47462,47463,47466,47468,47470,47471,47472,47473,47474,47475,47478,47479,47481,47482,47483,47485,null,null,null,null,null,null,47486,47487,47488,47489,47490,47491,47494,47496,47499,47500,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,null,null,null,null,null,null,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47534,47535,47537,47538,47539,47541,47542,47543,47544,47545,47546,47547,47550,47552,47554,47555,47556,47557,47558,47559,47562,47563,47565,47571,47572,47573,47574,47575,47578,47580,47583,47584,47586,47590,47591,47593,47594,47595,47597,47598,47599,47600,47601,47602,47603,47606,47611,47612,47613,47614,47615,47618,47619,47620,47621,47622,47623,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47674,47675,47677,47678,47679,47681,47683,47684,47685,47686,47687,47690,47692,47695,47696,47697,47698,47702,47703,47705,47706,47707,47709,47710,47711,47712,47713,47714,47715,47718,47722,47723,47724,47725,47726,47727,null,null,null,null,null,null,47730,47731,47733,47734,47735,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47750,47752,47753,47754,47755,47757,47758,47759,47760,47761,47762,null,null,null,null,null,null,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47786,47789,47790,47791,47793,47795,47796,47797,47798,47799,47802,47804,47806,47807,47808,47809,47810,47811,47813,47814,47815,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47869,47870,47871,47873,47874,47875,47877,47878,47879,47880,47881,47882,47883,47884,47886,47888,47890,47891,47892,47893,47894,47895,47897,47898,47899,47901,47902,47903,47905,47906,47907,47908,47909,47910,47911,47912,47914,47916,47917,47918,47919,47920,47921,47922,47923,47927,47929,47930,47935,47936,47937,47938,47939,47942,47944,47946,47947,47948,47950,47953,47954,null,null,null,null,null,null,47955,47957,47958,47959,47961,47962,47963,47964,47965,47966,47967,47968,47970,47972,47973,47974,47975,47976,47977,47978,47979,47981,47982,47983,47984,47985,null,null,null,null,null,null,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48009,48010,48011,48013,48014,48015,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48037,48038,48039,48041,48042,48043,48045,48046,48047,48048,48049,48050,48051,48053,48054,48056,48057,48058,48059,48060,48061,48062,48063,48065,48066,48067,48069,48070,48071,48073,48074,48075,48076,48077,48078,48079,48081,48082,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48122,48123,48125,48126,48129,48131,48132,48133,48134,48135,48138,48142,48144,48146,48147,48153,48154,48160,48161,48162,48163,48166,48168,48170,48171,48172,48174,48175,48178,48179,48181,null,null,null,null,null,null,48182,48183,48185,48186,48187,48188,48189,48190,48191,48194,48198,48199,48200,48202,48203,48206,48207,48209,48210,48211,48212,48213,48214,48215,48216,48217,null,null,null,null,null,null,48218,48219,48220,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48262,48263,48265,48266,48269,48271,48272,48273,48274,48275,48278,48280,48283,48284,48285,48286,48287,48290,48291,48293,48294,48297,48298,48299,48300,48301,48302,48303,48306,48310,48311,48312,48313,48314,48315,48318,48319,48321,48322,48323,48325,48326,48327,48328,48329,48330,48331,48332,48334,48338,48339,48340,48342,48343,48345,48346,48347,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48375,48377,48378,48379,48381,48382,48383,48384,48385,48386,48387,48390,48392,48394,48395,48396,48397,48398,48399,48401,48402,48403,48405,48406,48407,48408,48409,48410,48411,48412,48413,null,null,null,null,null,null,48414,48415,48416,48417,48418,48419,48421,48422,48423,48424,48425,48426,48427,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,null,null,null,null,null,null,48442,48443,48444,48445,48446,48447,48449,48450,48451,48452,48453,48454,48455,48458,48459,48461,48462,48463,48465,48466,48467,48468,48469,48470,48471,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48485,48486,48487,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48514,48515,48517,48518,48523,48524,48525,48526,48527,48530,48532,48534,48535,48536,48539,48541,48542,48543,48544,48545,48546,48547,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48561,48562,48563,48564,48565,48566,48567,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48598,48599,48601,48602,48603,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48618,48619,48620,48621,48622,48623,48625,null,null,null,null,null,null,48626,48627,48629,48630,48631,48633,48634,48635,48636,48637,48638,48639,48641,48642,48644,48646,48647,48648,48649,48650,48651,48654,48655,48657,48658,48659,null,null,null,null,null,null,48661,48662,48663,48664,48665,48666,48667,48670,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48710,48711,48713,48714,48715,48717,48719,48720,48721,48722,48723,48726,48728,48732,48733,48734,48735,48738,48739,48741,48742,48743,48745,48747,48748,48749,48750,48751,48754,48758,48759,48760,48761,48762,48766,48767,48769,48770,48771,48773,48774,48775,48776,48777,48778,48779,48782,48786,48787,48788,48789,48790,48791,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48850,48851,null,null,null,null,null,null,48853,48854,48857,48858,48859,48860,48861,48862,48863,48865,48866,48870,48871,48872,48873,48874,48875,48877,48878,48879,48880,48881,48882,48883,48884,48885,null,null,null,null,null,null,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48898,48899,48900,48901,48902,48903,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48922,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48962,48963,48965,48966,48967,48969,48970,48971,48972,48973,48974,48975,48978,48979,48980,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49045,49046,49047,49048,49049,49050,49051,49052,49053,null,null,null,null,null,null,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49073,49074,49075,49076,49077,49078,49079,49080,null,null,null,null,null,null,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49094,49095,49096,49097,49098,49099,49102,49103,49105,49106,49107,49109,49110,49111,49112,49113,49114,49115,49117,49118,49120,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49234,49235,49236,49237,49238,49239,49241,49242,49243,null,null,null,null,null,null,49245,49246,49247,49249,49250,49251,49252,49253,49254,49255,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,null,null,null,null,null,null,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49298,49299,49301,49302,49303,49305,49306,49307,49308,49309,49310,49311,49314,49316,49318,49319,49320,49321,49322,49323,49326,49329,49330,49335,49336,49337,49338,49339,49342,49346,49347,49348,49350,49351,49354,49355,49357,49358,49359,49361,49362,49363,49364,49365,49366,49367,49370,49374,49375,49376,49377,49378,49379,49382,49383,49385,49386,49387,49389,49390,49391,49392,49393,49394,49395,49398,49400,49402,49403,49404,49405,49406,49407,49409,49410,49411,49413,49414,49415,49417,49418,49419,49420,49421,49422,49423,49425,49426,49427,49428,49430,49431,49432,49433,49434,49435,49441,49442,49445,49448,49449,49450,49451,49454,49458,49459,49460,49461,49463,49466,49467,49469,49470,49471,49473,49474,49475,49476,49477,49478,49479,49482,49486,49487,49488,49489,49490,49491,49494,49495,null,null,null,null,null,null,49497,49498,49499,49501,49502,49503,49504,49505,49506,49507,49510,49514,49515,49516,49517,49518,49519,49521,49522,49523,49525,49526,49527,49529,49530,49531,null,null,null,null,null,null,49532,49533,49534,49535,49536,49537,49538,49539,49540,49542,49543,49544,49545,49546,49547,49551,49553,49554,49555,49557,49559,49560,49561,49562,49563,49566,49568,49570,49571,49572,49574,49575,49578,49579,49581,49582,49583,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49598,49599,49600,49601,49602,49603,49605,49606,49607,49609,49610,49611,49613,49614,49615,49616,49617,49618,49619,49621,49622,49625,49626,49627,49628,49629,49630,49631,49633,49634,49635,49637,49638,49639,49641,49642,49643,49644,49645,49646,49647,49650,49652,49653,49654,49655,49656,49657,49658,49659,49662,49663,49665,49666,49667,49669,49670,49671,49672,49673,49674,49675,49678,49680,49682,49683,49684,49685,49686,49687,49690,49691,49693,49694,49697,49698,49699,49700,49701,49702,49703,49706,49708,49710,49712,49715,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,null,null,null,null,null,null,49734,49735,49737,49738,49739,49740,49741,49742,49743,49746,49747,49749,49750,49751,49753,49754,49755,49756,49757,49758,49759,49761,49762,49763,49764,49766,null,null,null,null,null,null,49767,49768,49769,49770,49771,49774,49775,49777,49778,49779,49781,49782,49783,49784,49785,49786,49787,49790,49792,49794,49795,49796,49797,49798,49799,49802,49803,49804,49805,49806,49807,49809,49810,49811,49812,49813,49814,49815,49817,49818,49820,49822,49823,49824,49825,49826,49827,49830,49831,49833,49834,49835,49838,49839,49840,49841,49842,49843,49846,49848,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49886,49887,49889,49890,49893,49894,49895,49896,49897,49898,49902,49904,49906,49907,49908,49909,49911,49914,49917,49918,49919,49921,49922,49923,49924,49925,49926,49927,49930,49931,49934,49935,49936,49937,49938,49942,49943,49945,49946,49947,49949,49950,49951,49952,49953,49954,49955,49958,49959,49962,49963,49964,49965,49966,49967,49968,49969,49970,null,null,null,null,null,null,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49990,49991,49992,49993,49994,49995,49996,49997,null,null,null,null,null,null,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50026,50027,50029,50030,50031,50033,50035,50036,50037,50038,50039,50042,50043,50046,50047,50048,50049,50050,50051,50053,50054,50055,50057,50058,50059,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50138,50139,50141,50142,50145,50147,50148,50149,50150,50151,50154,50155,50156,50158,50159,50160,50161,50162,50163,50166,50167,50169,50170,50171,50172,50173,50174,null,null,null,null,null,null,50175,50176,50177,50178,50179,50180,50181,50182,50183,50185,50186,50187,50188,50189,50190,50191,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,null,null,null,null,null,null,50203,50204,50205,50206,50207,50208,50209,50210,50211,50213,50214,50215,50216,50217,50218,50219,50221,50222,50223,50225,50226,50227,50229,50230,50231,50232,50233,50234,50235,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50278,50279,50281,50282,50283,50285,50286,50287,50288,50289,50290,50291,50294,50295,50296,50298,50299,50300,50301,50302,50303,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50325,50326,50327,50328,50329,50330,50331,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50361,50362,50363,50365,50366,50367,50368,50369,50370,50371,50372,50373,null,null,null,null,null,null,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,null,null,null,null,null,null,50400,50401,50402,50403,50404,50405,50406,50407,50408,50410,50411,50412,50413,50414,50415,50418,50419,50421,50422,50423,50425,50427,50428,50429,50430,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50445,50446,50447,50449,50450,50451,50453,50454,50455,50456,50457,50458,50459,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50474,50475,50477,50478,50479,50481,50482,50483,50484,50485,50486,50487,50490,50492,50494,50495,50496,50497,50498,50499,50502,50503,50507,50511,50512,50513,50514,50518,50522,50523,50524,50527,50530,50531,50533,50534,50535,50537,50538,50539,50540,50541,50542,50543,50546,50550,50551,50552,50553,50554,50555,50558,50559,50561,50562,50563,50565,50566,50568,50569,50570,50571,50574,50576,50578,50579,50580,50582,50585,50586,50587,50589,50590,50591,50593,50594,50595,50596,50597,50598,50599,50600,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50614,null,null,null,null,null,null,50615,50618,50623,50624,50625,50626,50627,50635,50637,50639,50642,50643,50645,50646,50647,50649,50650,50651,50652,50653,50654,50655,50658,50660,50662,50663,null,null,null,null,null,null,50664,50665,50666,50667,50671,50673,50674,50675,50677,50680,50681,50682,50683,50690,50691,50692,50697,50698,50699,50701,50702,50703,50705,50706,50707,50708,50709,50710,50711,50714,50717,50718,50719,50720,50721,50722,50723,50726,50727,50729,50730,50731,50735,50737,50738,50742,50744,50746,50748,50749,50750,50751,50754,50755,50757,50758,50759,50761,50762,50763,50764,50765,50766,50767,50770,50774,50775,50776,50777,50778,50779,50782,50783,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50797,50798,50800,50802,50803,50804,50805,50806,50807,50810,50811,50813,50814,50815,50817,50818,50819,50820,50821,50822,50823,50826,50828,50830,50831,50832,50833,50834,50835,50838,50839,50841,50842,50843,50845,50846,50847,50848,50849,50850,50851,50854,50856,50858,50859,50860,50861,50862,50863,50866,50867,50869,50870,50871,50875,50876,50877,50878,50879,50882,50884,50886,50887,50888,50889,50890,50891,50894,null,null,null,null,null,null,50895,50897,50898,50899,50901,50902,50903,50904,50905,50906,50907,50910,50911,50914,50915,50916,50917,50918,50919,50922,50923,50925,50926,50927,50929,50930,null,null,null,null,null,null,50931,50932,50933,50934,50935,50938,50939,50940,50942,50943,50944,50945,50946,50947,50950,50951,50953,50954,50955,50957,50958,50959,50960,50961,50962,50963,50966,50968,50970,50971,50972,50973,50974,50975,50978,50979,50981,50982,50983,50985,50986,50987,50988,50989,50990,50991,50994,50996,50998,51000,51001,51002,51003,51006,51007,51009,51010,51011,51013,51014,51015,51016,51017,51019,51022,51024,51033,51034,51035,51037,51038,51039,51041,51042,51043,51044,51045,51046,51047,51049,51050,51052,51053,51054,51055,51056,51057,51058,51059,51062,51063,51065,51066,51067,51071,51072,51073,51074,51078,51083,51084,51085,51087,51090,51091,51093,51097,51099,51100,51101,51102,51103,51106,51111,51112,51113,51114,51115,51118,51119,51121,51122,51123,51125,51126,51127,51128,51129,51130,51131,51134,51138,51139,51140,51141,51142,51143,51146,51147,51149,51151,51153,51154,51155,51156,51157,51158,51159,51161,51162,51163,51164,null,null,null,null,null,null,51166,51167,51168,51169,51170,51171,51173,51174,51175,51177,51178,51179,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,null,null,null,null,null,null,51195,51196,51197,51198,51199,51202,51203,51205,51206,51207,51209,51211,51212,51213,51214,51215,51218,51220,51223,51224,51225,51226,51227,51230,51231,51233,51234,51235,51237,51238,51239,51240,51241,51242,51243,51246,51248,51250,51251,51252,51253,51254,51255,51257,51258,51259,51261,51262,51263,51265,51266,51267,51268,51269,51270,51271,51274,51275,51278,51279,51280,51281,51282,51283,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51314,51315,51317,51318,51319,51321,51323,51324,51325,51326,51327,51330,51332,51336,51337,51338,51342,51343,51344,51345,51346,51347,51349,51350,51351,51352,51353,51354,51355,51356,51358,51360,51362,51363,51364,51365,51366,51367,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51390,51391,51392,51393,null,null,null,null,null,null,51394,51395,51397,51398,51399,51401,51402,51403,51405,51406,51407,51408,51409,51410,51411,51414,51416,51418,51419,51420,51421,51422,51423,51426,51427,51429,null,null,null,null,null,null,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51446,51447,51448,51449,51450,51451,51454,51455,51457,51458,51459,51463,51464,51465,51466,51467,51470,12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,8835,8746,8745,8743,8744,65506,51472,51474,51475,51476,51477,51478,51479,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,null,null,null,null,null,null,51501,51502,51503,51504,51505,51506,51507,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,null,null,null,null,null,null,51528,51529,51530,51531,51532,51533,51534,51535,51538,51539,51541,51542,51543,51545,51546,51547,51548,51549,51550,51551,51554,51556,51557,51558,51559,51560,51561,51562,51563,51565,51566,51567,8658,8660,8704,8707,180,65374,711,728,733,730,729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51569,51570,51571,51573,51574,51575,51576,51577,51578,51579,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51594,51595,51597,51598,51599,null,null,null,null,null,null,51601,51602,51603,51604,51605,51606,51607,51610,51612,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,null,null,null,null,null,null,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51650,51651,51653,51654,51657,51659,51660,51661,51662,51663,51666,51668,51671,51672,51675,65281,65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,51678,51679,51681,51683,51685,51686,51688,51689,51690,51691,51694,51698,51699,51700,51701,51702,51703,51706,51707,51709,51710,51711,51713,51714,51715,51716,null,null,null,null,null,null,51717,51718,51719,51722,51726,51727,51728,51729,51730,51731,51733,51734,51735,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,null,null,null,null,null,null,51750,51751,51752,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,51783,51784,51785,51786,51787,51790,51791,51793,51794,51795,51797,51798,51799,51800,51801,51802,51803,51806,51810,51811,51812,51813,51814,51815,51817,51818,null,null,null,null,null,null,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51838,51839,51840,51841,51842,51843,51845,51846,null,null,null,null,null,null,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,null,null,null,null,null,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51902,51903,51905,51906,51907,51909,null,null,null,null,null,null,51910,51911,51912,51913,51914,51915,51918,51920,51922,51924,51925,51926,51927,51930,51931,51932,51933,51934,51935,51937,51938,51939,51940,51941,51942,51943,null,null,null,null,null,null,51944,51945,51946,51947,51949,51950,51951,51952,51953,51954,51955,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51977,51978,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51979,51980,51981,51982,51983,51985,51986,51987,51989,51990,51991,51993,51994,51995,51996,51997,51998,51999,52002,52003,52004,52005,52006,52007,52008,52009,null,null,null,null,null,null,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52034,52035,52036,null,null,null,null,null,null,52037,52038,52039,52042,52043,52045,52046,52047,52049,52050,52051,52052,52053,52054,52055,52058,52059,52060,52062,52063,52064,52065,52066,52067,52069,52070,52071,52072,52073,52074,52075,52076,13205,13206,13207,8467,13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,null,null,null,null,null,null,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52125,52126,52127,52128,52129,52130,52131,null,null,null,null,null,null,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,198,208,170,294,null,306,null,319,321,216,338,186,222,358,330,null,12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,190,8539,8540,8541,8542,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,null,null,null,null,null,null,52192,52193,52194,52195,52197,52198,52200,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,null,null,null,null,null,null,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52238,52239,52241,52242,52243,52245,52246,52247,52248,52249,52250,52251,52254,52255,52256,52259,52260,230,273,240,295,305,307,312,320,322,248,339,223,254,359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,185,178,179,8308,8319,8321,8322,8323,8324,52261,52262,52266,52267,52269,52271,52273,52274,52275,52276,52277,52278,52279,52282,52287,52288,52289,52290,52291,52294,52295,52297,52298,52299,52301,52302,null,null,null,null,null,null,52303,52304,52305,52306,52307,52310,52314,52315,52316,52317,52318,52319,52321,52322,52323,52325,52327,52329,52330,52331,52332,52333,52334,52335,52337,52338,null,null,null,null,null,null,52339,52340,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,52372,52373,52374,52375,52378,52379,52381,52382,52383,52385,52386,52387,52388,52389,52390,52391,52394,52398,52399,52400,52401,52402,52403,52406,52407,52409,null,null,null,null,null,null,52410,52411,52413,52414,52415,52416,52417,52418,52419,52422,52424,52426,52427,52428,52429,52430,52431,52433,52434,52435,52437,52438,52439,52440,52441,52442,null,null,null,null,null,null,52443,52444,52445,52446,52447,52448,52449,52450,52451,52453,52454,52455,52456,52457,52458,52459,52461,52462,52463,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,52478,52479,52480,52482,52483,52484,52485,52486,52487,52490,52491,52493,52494,52495,52497,52498,52499,52500,52501,52502,52503,52506,52508,52510,52511,52512,null,null,null,null,null,null,52513,52514,52515,52517,52518,52519,52521,52522,52523,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52538,52539,52540,52541,52542,null,null,null,null,null,null,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52573,52574,52575,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,52577,52578,52579,52581,52582,52583,52584,52585,52586,52587,52590,52592,52594,52595,52596,52597,52598,52599,52601,52602,52603,52604,52605,52606,52607,52608,null,null,null,null,null,null,52609,52610,52611,52612,52613,52614,52615,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52630,52631,52633,52634,52635,52637,52638,52639,null,null,null,null,null,null,52640,52641,52642,52643,52646,52648,52650,52651,52652,52653,52654,52655,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52677,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52678,52679,52680,52681,52682,52683,52685,52686,52687,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,null,null,null,null,null,null,52706,52707,52708,52709,52710,52711,52713,52714,52715,52717,52718,52719,52721,52722,52723,52724,52725,52726,52727,52730,52732,52734,52735,52736,52737,52738,null,null,null,null,null,null,52739,52741,52742,52743,52745,52746,52747,52749,52750,52751,52752,52753,52754,52755,52757,52758,52759,52760,52762,52763,52764,52765,52766,52767,52770,52771,52773,52774,52775,52777,52778,52779,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52780,52781,52782,52783,52786,52788,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,null,null,null,null,null,null,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52826,52827,52829,52830,52834,52835,52836,52837,52838,52839,52842,52844,null,null,null,null,null,null,52846,52847,52848,52849,52850,52851,52854,52855,52857,52858,52859,52861,52862,52863,52864,52865,52866,52867,52870,52872,52874,52875,52876,52877,52878,52879,52882,52883,52885,52886,52887,52889,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52890,52891,52892,52893,52894,52895,52898,52902,52903,52904,52905,52906,52907,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,null,null,null,null,null,null,52923,52924,52925,52926,52927,52928,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,null,null,null,null,null,null,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52966,52967,52969,52970,52973,52974,52975,52976,52977,52978,52979,52982,52986,52987,52988,52989,52990,52991,44032,44033,44036,44039,44040,44041,44042,44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,44273,44275,44277,44278,44284,44285,44288,44292,44294,52994,52995,52997,52998,52999,53001,53002,53003,53004,53005,53006,53007,53010,53012,53014,53015,53016,53017,53018,53019,53021,53022,53023,53025,53026,53027,null,null,null,null,null,null,53029,53030,53031,53032,53033,53034,53035,53038,53042,53043,53044,53045,53046,53047,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,null,null,null,null,null,null,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53078,53079,53081,53082,53083,53085,53086,53087,53088,53089,53090,53091,53094,53096,53098,53099,53100,44300,44301,44303,44305,44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,53101,53102,53103,53106,53107,53109,53110,53111,53113,53114,53115,53116,53117,53118,53119,53121,53122,53123,53124,53126,53127,53128,53129,53130,53131,53133,null,null,null,null,null,null,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53154,53155,53156,53157,53158,53159,53161,null,null,null,null,null,null,53162,53163,53164,53165,53166,53167,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53189,53190,53191,53192,53193,53194,53195,44665,44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,44945,44949,44956,44984,44985,44988,44992,44999,45000,45001,45003,45005,45006,45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,45143,45145,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53218,53219,53221,53222,53223,53225,null,null,null,null,null,null,53226,53227,53228,53229,53230,53231,53234,53236,53238,53239,53240,53241,53242,53243,53245,53246,53247,53249,53250,53251,53253,53254,53255,53256,53257,53258,null,null,null,null,null,null,53259,53260,53261,53262,53263,53264,53266,53267,53268,53269,53270,53271,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,45516,45520,45524,45532,45533,53294,53295,53296,53297,53298,53299,53302,53303,53305,53306,53307,53309,53310,53311,53312,53313,53314,53315,53318,53320,53322,53323,53324,53325,53326,53327,null,null,null,null,null,null,53329,53330,53331,53333,53334,53335,53337,53338,53339,53340,53341,53342,53343,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53358,53359,null,null,null,null,null,null,53361,53362,53363,53365,53366,53367,53368,53369,53370,53371,53374,53375,53376,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,45535,45544,45545,45548,45552,45561,45563,45565,45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,45910,45912,45915,45916,45918,45919,45924,45925,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53414,53415,53417,53418,53419,53421,53422,53423,53424,53425,53426,null,null,null,null,null,null,53427,53430,53432,53434,53435,53436,53437,53438,53439,53442,53443,53445,53446,53447,53450,53451,53452,53453,53454,53455,53458,53462,53463,53464,53465,53466,null,null,null,null,null,null,53467,53470,53471,53473,53474,53475,53477,53478,53479,53480,53481,53482,53483,53486,53490,53491,53492,53493,53494,53495,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,45927,45929,45931,45934,45936,45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,53509,53510,53511,53512,53513,53514,53515,53516,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,null,null,null,null,null,null,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53554,53555,53557,53558,53559,53561,53563,53564,53565,53566,null,null,null,null,null,null,53567,53570,53574,53575,53576,53577,53578,53579,53582,53583,53585,53586,53587,53589,53590,53591,53592,53593,53594,53595,53598,53600,53602,53603,53604,53605,53606,53607,53609,53610,53611,53613,46400,46401,46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,46999,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53629,53630,53631,53632,53633,53634,53635,53637,53638,53639,53641,53642,null,null,null,null,null,null,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53666,53667,53669,53670,53671,null,null,null,null,null,null,53673,53674,53675,53676,53677,53678,53679,53682,53684,53686,53687,53688,53689,53691,53693,53694,53695,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,47000,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,47452,47456,47464,47465,53712,53713,53714,53715,53716,53717,53718,53719,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,null,null,null,null,null,null,53739,53740,53741,53742,53743,53744,53745,53746,53747,53749,53750,53751,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,null,null,null,null,null,null,53768,53770,53771,53772,53773,53774,53775,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,47467,47469,47476,47477,47480,47484,47492,47493,47495,47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,47803,47805,47812,47816,47832,47833,47868,53802,53803,53806,53807,53809,53810,53811,53813,53814,53815,53816,53817,53818,53819,53822,53824,53826,53827,53828,53829,53830,53831,53833,53834,53835,53836,null,null,null,null,null,null,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53853,53854,53855,53856,53857,53858,53859,53861,53862,53863,53864,null,null,null,null,null,null,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53890,53891,53893,53894,53895,53897,53898,53899,53900,47872,47876,47885,47887,47889,47896,47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,53901,53902,53903,53906,53907,53908,53910,53911,53912,53913,53914,53915,53917,53918,53919,53921,53922,53923,53925,53926,53927,53928,53929,53930,53931,53933,null,null,null,null,null,null,53934,53935,53936,53938,53939,53940,53941,53942,53943,53946,53947,53949,53950,53953,53955,53956,53957,53958,53959,53962,53964,53965,53966,53967,53968,53969,null,null,null,null,null,null,53970,53971,53973,53974,53975,53977,53978,53979,53981,53982,53983,53984,53985,53986,53987,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54002,54003,54005,54006,54007,54009,54010,48281,48282,48288,48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,54011,54012,54013,54014,54015,54018,54020,54022,54023,54024,54025,54026,54027,54031,54033,54034,54035,54037,54039,54040,54041,54042,54043,54046,54050,54051,null,null,null,null,null,null,54052,54054,54055,54058,54059,54061,54062,54063,54065,54066,54067,54068,54069,54070,54071,54074,54078,54079,54080,54081,54082,54083,54086,54087,54088,54089,null,null,null,null,null,null,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,49372,49373,49380,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54142,54143,54145,54146,54147,54149,54150,54151,null,null,null,null,null,null,54152,54153,54154,54155,54158,54162,54163,54164,54165,54166,54167,54170,54171,54173,54174,54175,54177,54178,54179,54180,54181,54182,54183,54186,54188,54190,null,null,null,null,null,null,54191,54192,54193,54194,54195,54197,54198,54199,54201,54202,54203,54205,54206,54207,54208,54209,54210,54211,54214,54215,54218,54219,54220,54221,54222,54223,54225,54226,54227,54228,54229,54230,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,49695,49696,49704,49705,49707,49709,54231,54233,54234,54235,54236,54237,54238,54239,54240,54242,54244,54245,54246,54247,54248,54249,54250,54251,54254,54255,54257,54258,54259,54261,54262,54263,null,null,null,null,null,null,54264,54265,54266,54267,54270,54272,54274,54275,54276,54277,54278,54279,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,null,null,null,null,null,null,54295,54296,54297,54298,54299,54300,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,49711,49713,49714,49716,49736,49744,49745,49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,50157,50164,50165,50168,50184,50192,50212,50220,50224,54328,54329,54330,54331,54332,54333,54334,54335,54337,54338,54339,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,null,null,null,null,null,null,54356,54357,54358,54359,54360,54361,54362,54363,54365,54366,54367,54369,54370,54371,54373,54374,54375,54376,54377,54378,54379,54380,54382,54384,54385,54386,null,null,null,null,null,null,54387,54388,54389,54390,54391,54394,54395,54397,54398,54401,54403,54404,54405,54406,54407,54410,54412,54414,54415,54416,54417,54418,54419,54421,54422,54423,54424,54425,54426,54427,54428,54429,50228,50236,50237,50248,50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,null,null,null,null,null,null,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54477,54478,54479,54481,54482,54483,54485,null,null,null,null,null,null,54486,54487,54488,54489,54490,54491,54493,54494,54496,54497,54498,54499,54500,54501,54502,54503,54505,54506,54507,54509,54510,54511,54513,54514,54515,54516,54517,54518,54519,54521,54522,54524,50640,50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,50913,50920,54526,54527,54528,54529,54530,54531,54533,54534,54535,54537,54538,54539,54541,54542,54543,54544,54545,54546,54547,54550,54552,54553,54554,54555,54556,54557,null,null,null,null,null,null,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,null,null,null,null,null,null,54584,54585,54586,54587,54590,54591,54593,54594,54595,54597,54598,54599,54600,54601,54602,54603,54606,54608,54610,54611,54612,54613,54614,54615,54618,54619,54621,54622,54623,54625,54626,54627,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,51200,51201,51204,51208,51210,54628,54630,54631,54634,54636,54638,54639,54640,54641,54642,54643,54646,54647,54649,54650,54651,54653,54654,54655,54656,54657,54658,54659,54662,54666,54667,null,null,null,null,null,null,54668,54669,54670,54671,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54694,54695,null,null,null,null,null,null,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,51216,51217,51219,51221,51222,51228,51229,51232,51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,51649,51652,51655,51656,51658,51664,51665,51667,54730,54731,54733,54734,54735,54737,54739,54740,54741,54742,54743,54746,54748,54750,54751,54752,54753,54754,54755,54758,54759,54761,54762,54763,54765,54766,null,null,null,null,null,null,54767,54768,54769,54770,54771,54774,54776,54778,54779,54780,54781,54782,54783,54786,54787,54789,54790,54791,54793,54794,54795,54796,54797,54798,54799,54802,null,null,null,null,null,null,54806,54807,54808,54809,54810,54811,54813,54814,54815,54817,54818,54819,54821,54822,54823,54824,54825,54826,54827,54828,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54842,54843,51669,51670,51673,51674,51676,51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,51992,52000,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,54845,54846,54847,54849,54850,54851,54852,54854,54855,54858,54860,54862,54863,54864,54866,54867,54870,54871,54873,54874,54875,54877,54878,54879,54880,54881,null,null,null,null,null,null,54882,54883,54884,54885,54886,54888,54890,54891,54892,54893,54894,54895,54898,54899,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,null,null,null,null,null,null,54913,54914,54916,54918,54919,54920,54921,54922,54923,54926,54927,54929,54930,54931,54933,54934,54935,54936,54937,54938,54939,54940,54942,54944,54946,54947,54948,54949,54950,54951,54953,54954,52284,52285,52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,52789,54955,54957,54958,54959,54961,54962,54963,54964,54965,54966,54967,54968,54970,54972,54973,54974,54975,54976,54977,54978,54979,54982,54983,54985,54986,54987,null,null,null,null,null,null,54989,54990,54991,54992,54994,54995,54997,54998,55000,55002,55003,55004,55005,55006,55007,55009,55010,55011,55013,55014,55015,55017,55018,55019,55020,55021,null,null,null,null,null,null,55022,55023,55025,55026,55027,55028,55030,55031,55032,55033,55034,55035,55038,55039,55041,55042,55043,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55058,55059,55060,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,52984,52985,52992,52993,52996,53000,53008,53009,53011,53013,53020,53024,53028,53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,53300,53301,53304,53308,55061,55062,55063,55066,55067,55069,55070,55071,55073,55074,55075,55076,55077,55078,55079,55082,55084,55086,55087,55088,55089,55090,55091,55094,55095,55097,null,null,null,null,null,null,55098,55099,55101,55102,55103,55104,55105,55106,55107,55109,55110,55112,55114,55115,55116,55117,55118,55119,55122,55123,55125,55130,55131,55132,55133,55134,null,null,null,null,null,null,55135,55138,55140,55142,55143,55144,55146,55147,55149,55150,55151,55153,55154,55155,55157,55158,55159,55160,55161,55162,55163,55166,55167,55168,55170,55171,55172,55173,55174,55175,55178,55179,53316,53317,53319,53321,53328,53332,53336,53344,53356,53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,53812,53820,53821,53823,53825,53832,53852,55181,55182,55183,55185,55186,55187,55188,55189,55190,55191,55194,55196,55198,55199,55200,55201,55202,55203,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,53860,53888,53889,53892,53896,53904,53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,53960,53961,53963,53972,53976,53980,53988,53989,54000,54001,54004,54008,54016,54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54280,54301,54336,54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,55193,55195,55197,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20285,20339,20551,20729,21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21283,23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,21138,27298,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,23622,24760,25106,26690,26800,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26856,28330,30028,30328,30926,31293,31995,32363,32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,34467,36002,38799,20018,23521,25096,26524,29916,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31185,33747,35463,35506,36328,36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21312,21475,21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,36020,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,24524,25216,26071,26083,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26398,26399,26462,26827,26820,27231,27450,27683,27773,27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,31048,31098,31637,32000,32186,32648,32774,32813,32908,35352,35663,35912,36215,37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,26976,28275,63778,30007,63779,63780,63781,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32013,63782,63783,34930,22218,23064,63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20025,20150,20294,21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,63835,30313,32645,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,36706,38722,24976,25088,25891,28451,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29001,29833,32244,32879,34030,36646,36899,37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,20698,23534,24278,26009,29134,30274,30637,32842,34044,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36988,39719,40845,22744,23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31435,31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,33180,33707,37000,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,40629,28357,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,20497,21006,21563,21839,25991,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27766,32010,32011,32862,34442,38272,38639,21247,27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,36820,38930,39151,21187,25300,25765,28196,28497,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30332,36299,37297,37474,39662,39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30887,34327,38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,23142,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,31807,32566,33104,33105,33178,33344,33433,33705,35331,36000,36070,36091,36212,36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26000,26503,27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,31875,32203,32737,32933,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,33086,33218,33778,34586,35048,35513,35692,36027,37145,38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,39164,39391,40605,21066,63849,26388,63850,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20632,21034,23665,25955,27733,29642,29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32997,33298,34223,35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,23744,24101,24833,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,25100,34899,36848,37477,23815,23847,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23913,29791,33181,34664,28629,25342,32722,35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,36805,22833,23460,23526,24713,23529,23563,24515,27777,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63858,28145,28683,29978,33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27387,32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,22914,63874,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,28814,28976,29744,33398,33490,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63910,38331,39653,40573,26308,63911,29121,33865,63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,63924,20034,20522,63925,21000,21473,26355,27757,28618,29450,30591,31330,33454,34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,63929,25034,25942,26111,26212,26791,27738,28595,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28879,29100,29522,31613,34568,35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31368,31407,32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,34131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,29232,29503,29783,33489,34945,36677,36960,63942,38498,39000,40219,26376,36234,37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,27943,63946,28216,63947,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28641,29494,29495,63948,29788,30001,63949,30290,63950,63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,30691,32681,33380,34191,34811,34915,35516,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,35696,37291,20108,20197,20234,63965,63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63991,63992,63993,20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,27583,27656,28593,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29006,29728,30000,30008,30033,30322,31564,31627,31661,31686,32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,37336,37478,37580,37664,38662,38742,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38748,38914,40718,21046,21137,21884,22564,24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,24939,26837,28121,29742,31278,32066,32156,32305,33131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36394,36405,37758,37912,20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21675,22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,32221,36655,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,37319,37365,20874,26613,31574,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36012,20932,22971,24765,34389,20508,63999,21076,23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,33729,35531,38737,39894,64000,21059,26367,28053,28399,32224,35558,36910,36958,39636,21021,21119,21736,24980,25220,25307,26786,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26898,26970,27189,28818,28966,30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,22684,25277,25512,26894,27000,27166,28267,30394,31179,33467,33833,35535,36264,36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36101,21462,21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,35351,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,29923,36009,36774,37393,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38442,20843,21485,25420,20329,21764,24726,25943,27803,28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,29922,31080,34920,35961,39111,39108,39491,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21697,31263,26963,35575,35914,39080,39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,64008,64009,38917,20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,27194,28779,30069,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,25928,25989,26313,26783,28045,28102,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29243,32948,37237,39501,20399,20505,21402,21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,26342,29081,29113,29114,29351,31143,31232,32690,35440,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "gb18030":[19970,19972,19973,19974,19983,19986,19991,19999,20000,20001,20003,20006,20009,20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,21979,21982,21984,21986,21991,21993,21997,21998,22000,22001,22004,22006,22008,22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24006,24007,24008,24009,24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28998,28999,29000,29001,29003,29005,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,58850,58851,58852,12288,65281,65282,65283,65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,58994,58995,58996,58997,58998,58999,59000,59001,59002,59003,59004,59005,59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,234,593,7743,324,328,505,609,59337,59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,27686,20133,23475,39559,37219,25000,37039,38889,21547,28085,23506,20989,21898,32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,30000,29980,24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,34996,34997,34998,35000,35001,35002,35003,35005,35006,35007,35008,35011,35012,35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,21310,36188,21350,21347,20994,21000,21006,21037,21043,21055,21056,21068,21086,21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34000,34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,28049,28015,28062,28064,27998,28051,28052,27996,28000,28028,28003,28186,28103,28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,26297,36980,36989,36994,37000,36995,37003,24400,24407,24406,24408,23611,21675,23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,23000,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27000,26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,32951,32999,33000,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26000,40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,58000,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565], + "gb18030-ranges":[[0,128],[36,165],[38,169],[45,178],[50,184],[81,216],[89,226],[95,235],[96,238],[100,244],[103,248],[104,251],[105,253],[109,258],[126,276],[133,284],[148,300],[172,325],[175,329],[179,334],[208,364],[306,463],[307,465],[308,467],[309,469],[310,471],[311,473],[312,475],[313,477],[341,506],[428,594],[443,610],[544,712],[545,716],[558,730],[741,930],[742,938],[749,962],[750,970],[805,1026],[819,1104],[820,1106],[7922,8209],[7924,8215],[7925,8218],[7927,8222],[7934,8231],[7943,8241],[7944,8244],[7945,8246],[7950,8252],[8062,8365],[8148,8452],[8149,8454],[8152,8458],[8164,8471],[8174,8482],[8236,8556],[8240,8570],[8262,8596],[8264,8602],[8374,8713],[8380,8720],[8381,8722],[8384,8726],[8388,8731],[8390,8737],[8392,8740],[8393,8742],[8394,8748],[8396,8751],[8401,8760],[8406,8766],[8416,8777],[8419,8781],[8424,8787],[8437,8802],[8439,8808],[8445,8816],[8482,8854],[8485,8858],[8496,8870],[8521,8896],[8603,8979],[8936,9322],[8946,9372],[9046,9548],[9050,9588],[9063,9616],[9066,9622],[9076,9634],[9092,9652],[9100,9662],[9108,9672],[9111,9676],[9113,9680],[9131,9702],[9162,9735],[9164,9738],[9218,9793],[9219,9795],[11329,11906],[11331,11909],[11334,11913],[11336,11917],[11346,11928],[11361,11944],[11363,11947],[11366,11951],[11370,11956],[11372,11960],[11375,11964],[11389,11979],[11682,12284],[11686,12292],[11687,12312],[11692,12319],[11694,12330],[11714,12351],[11716,12436],[11723,12447],[11725,12535],[11730,12543],[11736,12586],[11982,12842],[11989,12850],[12102,12964],[12336,13200],[12348,13215],[12350,13218],[12384,13253],[12393,13263],[12395,13267],[12397,13270],[12510,13384],[12553,13428],[12851,13727],[12962,13839],[12973,13851],[13738,14617],[13823,14703],[13919,14801],[13933,14816],[14080,14964],[14298,15183],[14585,15471],[14698,15585],[15583,16471],[15847,16736],[16318,17208],[16434,17325],[16438,17330],[16481,17374],[16729,17623],[17102,17997],[17122,18018],[17315,18212],[17320,18218],[17402,18301],[17418,18318],[17859,18760],[17909,18811],[17911,18814],[17915,18820],[17916,18823],[17936,18844],[17939,18848],[17961,18872],[18664,19576],[18703,19620],[18814,19738],[18962,19887],[19043,40870],[33469,59244],[33470,59336],[33471,59367],[33484,59413],[33485,59417],[33490,59423],[33497,59431],[33501,59437],[33505,59443],[33513,59452],[33520,59460],[33536,59478],[33550,59493],[37845,63789],[37921,63866],[37948,63894],[38029,63976],[38038,63986],[38064,64016],[38065,64018],[38066,64021],[38069,64025],[38075,64034],[38076,64037],[38078,64042],[39108,65074],[39109,65093],[39113,65107],[39114,65112],[39115,65127],[39116,65132],[39265,65375],[39394,65510],[189000,65536]], + "jis0208":[12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,8213,8208,65295,65340,65374,8741,65372,8230,8229,8216,8217,8220,8221,65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,65291,65293,177,215,247,65309,8800,65308,65310,8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,65504,65505,65285,65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,null,null,null,null,null,null,null,null,null,null,null,8712,8715,8838,8839,8834,8835,8746,8745,null,null,null,null,null,null,null,null,8743,8744,65506,8658,8660,8704,8707,null,null,null,null,null,null,null,null,null,null,null,8736,8869,8978,8706,8711,8801,8786,8810,8811,8730,8765,8733,8757,8747,8748,null,null,null,null,null,null,null,8491,8240,9839,9837,9834,8224,8225,182,null,null,null,null,9711,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,null,null,null,null,null,null,null,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,null,null,null,null,null,null,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,null,null,null,null,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,13129,13076,13090,13133,13080,13095,13059,13110,13137,13143,13069,13094,13091,13099,13130,13115,13212,13213,13214,13198,13199,13252,13217,null,null,null,null,null,null,null,null,13179,12317,12319,8470,13261,8481,12964,12965,12966,12967,12968,12849,12850,12857,13182,13181,13180,8786,8801,8747,8750,8721,8730,8869,8736,8735,8895,8757,8745,8746,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20124,21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21000,33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,23721,32747,36107,38593,38929,38996,39000,20225,20238,21361,21916,22120,22522,22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32000,24509,35215,35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,36578,39003,28857,20253,27583,28593,30000,38651,20814,21520,22581,22615,22956,23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,21329,21542,22915,24199,24444,24754,25161,25209,25259,26000,27604,27852,30130,30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,33178,33433,35676,36000,36070,36212,38428,38468,20398,25771,27494,33310,33889,34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,26906,26915,26913,26822,27001,26999,26972,27000,26987,26964,27006,26990,26937,26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,33983,33951,34009,33997,33979,34010,34000,33985,33990,34006,33953,34081,34047,34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38000,38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,65506,65508,65287,65282,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,65506,65508,65287,65282,12849,8470,8481,8757,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "jis0212":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,728,711,184,729,733,175,731,730,65374,900,901,null,null,null,null,null,null,null,null,161,166,191,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,186,170,169,174,8482,164,8470,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,902,904,905,906,938,null,908,null,910,939,null,911,null,null,null,null,940,941,942,943,970,912,972,962,973,971,944,974,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,198,272,null,294,null,306,null,321,319,null,330,216,338,null,358,222,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,230,273,240,295,305,307,312,322,320,329,331,248,339,223,359,254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,193,192,196,194,258,461,256,260,197,195,262,264,268,199,266,270,201,200,203,202,282,278,274,280,null,284,286,290,288,292,205,204,207,206,463,304,298,302,296,308,310,313,317,315,323,327,325,209,211,210,214,212,465,336,332,213,340,344,342,346,348,352,350,356,354,218,217,220,219,364,467,368,362,370,366,360,471,475,473,469,372,221,376,374,377,381,379,null,null,null,null,null,null,null,225,224,228,226,259,462,257,261,229,227,263,265,269,231,267,271,233,232,235,234,283,279,275,281,501,285,287,null,289,293,237,236,239,238,464,null,299,303,297,309,311,314,318,316,324,328,326,241,243,242,246,244,466,337,333,245,341,345,343,347,349,353,351,357,355,250,249,252,251,365,468,369,363,371,367,361,472,476,474,470,373,253,255,375,378,382,380,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19970,19972,19973,19980,19986,19999,20003,20004,20008,20011,20014,20015,20016,20021,20032,20033,20036,20039,20049,20058,20060,20067,20072,20073,20084,20085,20089,20095,20109,20118,20119,20125,20143,20153,20163,20176,20186,20187,20192,20193,20194,20200,20207,20209,20211,20213,20221,20222,20223,20224,20226,20227,20232,20235,20236,20242,20245,20246,20247,20249,20270,20273,20320,20275,20277,20279,20281,20283,20286,20288,20290,20296,20297,20299,20300,20306,20308,20310,20312,20319,20323,20330,20332,20334,20337,20343,20344,20345,20346,20349,20350,20353,20354,20356,20357,20361,20362,20364,20366,20368,20370,20371,20372,20375,20377,20378,20382,20383,20402,20407,20409,20411,20412,20413,20414,20416,20417,20421,20422,20424,20425,20427,20428,20429,20431,20434,20444,20448,20450,20464,20466,20476,20477,20479,20480,20481,20484,20487,20490,20492,20494,20496,20499,20503,20504,20507,20508,20509,20510,20514,20519,20526,20528,20530,20531,20533,20544,20545,20546,20549,20550,20554,20556,20558,20561,20562,20563,20567,20569,20575,20576,20578,20579,20582,20583,20586,20589,20592,20593,20539,20609,20611,20612,20614,20618,20622,20623,20624,20626,20627,20628,20630,20635,20636,20638,20639,20640,20641,20642,20650,20655,20656,20665,20666,20669,20672,20675,20676,20679,20684,20686,20688,20691,20692,20696,20700,20701,20703,20706,20708,20710,20712,20713,20719,20721,20726,20730,20734,20739,20742,20743,20744,20747,20748,20749,20750,20722,20752,20759,20761,20763,20764,20765,20766,20771,20775,20776,20780,20781,20783,20785,20787,20788,20789,20792,20793,20802,20810,20815,20819,20821,20823,20824,20831,20836,20838,20862,20867,20868,20875,20878,20888,20893,20897,20899,20909,20920,20922,20924,20926,20927,20930,20936,20943,20945,20946,20947,20949,20952,20958,20962,20965,20974,20978,20979,20980,20983,20993,20994,20997,21010,21011,21013,21014,21016,21026,21032,21041,21042,21045,21052,21061,21065,21077,21079,21080,21082,21084,21087,21088,21089,21094,21102,21111,21112,21113,21120,21122,21125,21130,21132,21139,21141,21142,21143,21144,21146,21148,21156,21157,21158,21159,21167,21168,21174,21175,21176,21178,21179,21181,21184,21188,21190,21192,21196,21199,21201,21204,21206,21211,21212,21217,21221,21224,21225,21226,21228,21232,21233,21236,21238,21239,21248,21251,21258,21259,21260,21265,21267,21272,21275,21276,21278,21279,21285,21287,21288,21289,21291,21292,21293,21296,21298,21301,21308,21309,21310,21314,21324,21323,21337,21339,21345,21347,21349,21356,21357,21362,21369,21374,21379,21383,21384,21390,21395,21396,21401,21405,21409,21412,21418,21419,21423,21426,21428,21429,21431,21432,21434,21437,21440,21445,21455,21458,21459,21461,21466,21469,21470,21472,21478,21479,21493,21506,21523,21530,21537,21543,21544,21546,21551,21553,21556,21557,21571,21572,21575,21581,21583,21598,21602,21604,21606,21607,21609,21611,21613,21614,21620,21631,21633,21635,21637,21640,21641,21645,21649,21653,21654,21660,21663,21665,21670,21671,21673,21674,21677,21678,21681,21687,21689,21690,21691,21695,21702,21706,21709,21710,21728,21738,21740,21743,21750,21756,21758,21759,21760,21761,21765,21768,21769,21772,21773,21774,21781,21802,21803,21810,21813,21814,21819,21820,21821,21825,21831,21833,21834,21837,21840,21841,21848,21850,21851,21854,21856,21857,21860,21862,21887,21889,21890,21894,21896,21902,21903,21905,21906,21907,21908,21911,21923,21924,21933,21938,21951,21953,21955,21958,21961,21963,21964,21966,21969,21970,21971,21975,21976,21979,21982,21986,21993,22006,22015,22021,22024,22026,22029,22030,22031,22032,22033,22034,22041,22060,22064,22067,22069,22071,22073,22075,22076,22077,22079,22080,22081,22083,22084,22086,22089,22091,22093,22095,22100,22110,22112,22113,22114,22115,22118,22121,22125,22127,22129,22130,22133,22148,22149,22152,22155,22156,22165,22169,22170,22173,22174,22175,22182,22183,22184,22185,22187,22188,22189,22193,22195,22199,22206,22213,22217,22218,22219,22223,22224,22220,22221,22233,22236,22237,22239,22241,22244,22245,22246,22247,22248,22257,22251,22253,22262,22263,22273,22274,22279,22282,22284,22289,22293,22298,22299,22301,22304,22306,22307,22308,22309,22313,22314,22316,22318,22319,22323,22324,22333,22334,22335,22341,22342,22348,22349,22354,22370,22373,22375,22376,22379,22381,22382,22383,22384,22385,22387,22388,22389,22391,22393,22394,22395,22396,22398,22401,22403,22412,22420,22423,22425,22426,22428,22429,22430,22431,22433,22421,22439,22440,22441,22444,22456,22461,22471,22472,22476,22479,22485,22493,22494,22500,22502,22503,22505,22509,22512,22517,22518,22520,22525,22526,22527,22531,22532,22536,22537,22497,22540,22541,22555,22558,22559,22560,22566,22567,22573,22578,22585,22591,22601,22604,22605,22607,22608,22613,22623,22625,22628,22631,22632,22648,22652,22655,22656,22657,22663,22664,22665,22666,22668,22669,22671,22672,22676,22678,22685,22688,22689,22690,22694,22697,22705,22706,22724,22716,22722,22728,22733,22734,22736,22738,22740,22742,22746,22749,22753,22754,22761,22771,22789,22790,22795,22796,22802,22803,22804,34369,22813,22817,22819,22820,22824,22831,22832,22835,22837,22838,22847,22851,22854,22866,22867,22873,22875,22877,22878,22879,22881,22883,22891,22893,22895,22898,22901,22902,22905,22907,22908,22923,22924,22926,22930,22933,22935,22943,22948,22951,22957,22958,22959,22960,22963,22967,22970,22972,22977,22979,22980,22984,22986,22989,22994,23005,23006,23007,23011,23012,23015,23022,23023,23025,23026,23028,23031,23040,23044,23052,23053,23054,23058,23059,23070,23075,23076,23079,23080,23082,23085,23088,23108,23109,23111,23112,23116,23120,23125,23134,23139,23141,23143,23149,23159,23162,23163,23166,23179,23184,23187,23190,23193,23196,23198,23199,23200,23202,23207,23212,23217,23218,23219,23221,23224,23226,23227,23231,23236,23238,23240,23247,23258,23260,23264,23269,23274,23278,23285,23286,23293,23296,23297,23304,23319,23348,23321,23323,23325,23329,23333,23341,23352,23361,23371,23372,23378,23382,23390,23400,23406,23407,23420,23421,23422,23423,23425,23428,23430,23434,23438,23440,23441,23443,23444,23446,23464,23465,23468,23469,23471,23473,23474,23479,23482,23484,23488,23489,23501,23503,23510,23511,23512,23513,23514,23520,23535,23537,23540,23549,23564,23575,23582,23583,23587,23590,23593,23595,23596,23598,23600,23602,23605,23606,23641,23642,23644,23650,23651,23655,23656,23657,23661,23664,23668,23669,23674,23675,23676,23677,23687,23688,23690,23695,23698,23709,23711,23712,23714,23715,23718,23722,23730,23732,23733,23738,23753,23755,23762,23773,23767,23790,23793,23794,23796,23809,23814,23821,23826,23851,23843,23844,23846,23847,23857,23860,23865,23869,23871,23874,23875,23878,23880,23893,23889,23897,23882,23903,23904,23905,23906,23908,23914,23917,23920,23929,23930,23934,23935,23937,23939,23944,23946,23954,23955,23956,23957,23961,23963,23967,23968,23975,23979,23984,23988,23992,23993,24003,24007,24011,24016,24014,24024,24025,24032,24036,24041,24056,24057,24064,24071,24077,24082,24084,24085,24088,24095,24096,24110,24104,24114,24117,24126,24139,24144,24137,24145,24150,24152,24155,24156,24158,24168,24170,24171,24172,24173,24174,24176,24192,24203,24206,24226,24228,24229,24232,24234,24236,24241,24243,24253,24254,24255,24262,24268,24267,24270,24273,24274,24276,24277,24284,24286,24293,24299,24322,24326,24327,24328,24334,24345,24348,24349,24353,24354,24355,24356,24360,24363,24364,24366,24368,24372,24374,24379,24381,24383,24384,24388,24389,24391,24397,24400,24404,24408,24411,24416,24419,24420,24423,24431,24434,24436,24437,24440,24442,24445,24446,24457,24461,24463,24470,24476,24477,24482,24487,24491,24484,24492,24495,24496,24497,24504,24516,24519,24520,24521,24523,24528,24529,24530,24531,24532,24542,24545,24546,24552,24553,24554,24556,24557,24558,24559,24562,24563,24566,24570,24572,24583,24586,24589,24595,24596,24599,24600,24602,24607,24612,24621,24627,24629,24640,24647,24648,24649,24652,24657,24660,24662,24663,24669,24673,24679,24689,24702,24703,24706,24710,24712,24714,24718,24721,24723,24725,24728,24733,24734,24738,24740,24741,24744,24752,24753,24759,24763,24766,24770,24772,24776,24777,24778,24779,24782,24783,24788,24789,24793,24795,24797,24798,24802,24805,24818,24821,24824,24828,24829,24834,24839,24842,24844,24848,24849,24850,24851,24852,24854,24855,24857,24860,24862,24866,24874,24875,24880,24881,24885,24886,24887,24889,24897,24901,24902,24905,24926,24928,24940,24946,24952,24955,24956,24959,24960,24961,24963,24964,24971,24973,24978,24979,24983,24984,24988,24989,24991,24992,24997,25000,25002,25005,25016,25017,25020,25024,25025,25026,25038,25039,25045,25052,25053,25054,25055,25057,25058,25063,25065,25061,25068,25069,25071,25089,25091,25092,25095,25107,25109,25116,25120,25122,25123,25127,25129,25131,25145,25149,25154,25155,25156,25158,25164,25168,25169,25170,25172,25174,25178,25180,25188,25197,25199,25203,25210,25213,25229,25230,25231,25232,25254,25256,25267,25270,25271,25274,25278,25279,25284,25294,25301,25302,25306,25322,25330,25332,25340,25341,25347,25348,25354,25355,25357,25360,25363,25366,25368,25385,25386,25389,25397,25398,25401,25404,25409,25410,25411,25412,25414,25418,25419,25422,25426,25427,25428,25432,25435,25445,25446,25452,25453,25457,25460,25461,25464,25468,25469,25471,25474,25476,25479,25482,25488,25492,25493,25497,25498,25502,25508,25510,25517,25518,25519,25533,25537,25541,25544,25550,25553,25555,25556,25557,25564,25568,25573,25578,25580,25586,25587,25589,25592,25593,25609,25610,25616,25618,25620,25624,25630,25632,25634,25636,25637,25641,25642,25647,25648,25653,25661,25663,25675,25679,25681,25682,25683,25684,25690,25691,25692,25693,25695,25696,25697,25699,25709,25715,25716,25723,25725,25733,25735,25743,25744,25745,25752,25753,25755,25757,25759,25761,25763,25766,25768,25772,25779,25789,25790,25791,25796,25801,25802,25803,25804,25806,25808,25809,25813,25815,25828,25829,25833,25834,25837,25840,25845,25847,25851,25855,25857,25860,25864,25865,25866,25871,25875,25876,25878,25881,25883,25886,25887,25890,25894,25897,25902,25905,25914,25916,25917,25923,25927,25929,25936,25938,25940,25951,25952,25959,25963,25978,25981,25985,25989,25994,26002,26005,26008,26013,26016,26019,26022,26030,26034,26035,26036,26047,26050,26056,26057,26062,26064,26068,26070,26072,26079,26096,26098,26100,26101,26105,26110,26111,26112,26116,26120,26121,26125,26129,26130,26133,26134,26141,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26161,26163,26169,26167,26176,26181,26182,26186,26188,26193,26190,26199,26200,26201,26203,26204,26208,26209,26363,26218,26219,26220,26238,26227,26229,26239,26231,26232,26233,26235,26240,26236,26251,26252,26253,26256,26258,26265,26266,26267,26268,26271,26272,26276,26285,26289,26290,26293,26299,26303,26304,26306,26307,26312,26316,26318,26319,26324,26331,26335,26344,26347,26348,26350,26362,26373,26375,26382,26387,26393,26396,26400,26402,26419,26430,26437,26439,26440,26444,26452,26453,26461,26470,26476,26478,26484,26486,26491,26497,26500,26510,26511,26513,26515,26518,26520,26521,26523,26544,26545,26546,26549,26555,26556,26557,26617,26560,26562,26563,26565,26568,26569,26578,26583,26585,26588,26593,26598,26608,26610,26614,26615,26706,26644,26649,26653,26655,26664,26663,26668,26669,26671,26672,26673,26675,26683,26687,26692,26693,26698,26700,26709,26711,26712,26715,26731,26734,26735,26736,26737,26738,26741,26745,26746,26747,26748,26754,26756,26758,26760,26774,26776,26778,26780,26785,26787,26789,26793,26794,26798,26802,26811,26821,26824,26828,26831,26832,26833,26835,26838,26841,26844,26845,26853,26856,26858,26859,26860,26861,26864,26865,26869,26870,26875,26876,26877,26886,26889,26890,26896,26897,26899,26902,26903,26929,26931,26933,26936,26939,26946,26949,26953,26958,26967,26971,26979,26980,26981,26982,26984,26985,26988,26992,26993,26994,27002,27003,27007,27008,27021,27026,27030,27032,27041,27045,27046,27048,27051,27053,27055,27063,27064,27066,27068,27077,27080,27089,27094,27095,27106,27109,27118,27119,27121,27123,27125,27134,27136,27137,27139,27151,27153,27157,27162,27165,27168,27172,27176,27184,27186,27188,27191,27195,27198,27199,27205,27206,27209,27210,27214,27216,27217,27218,27221,27222,27227,27236,27239,27242,27249,27251,27262,27265,27267,27270,27271,27273,27275,27281,27291,27293,27294,27295,27301,27307,27311,27312,27313,27316,27325,27326,27327,27334,27337,27336,27340,27344,27348,27349,27350,27356,27357,27364,27367,27372,27376,27377,27378,27388,27389,27394,27395,27398,27399,27401,27407,27408,27409,27415,27419,27422,27428,27432,27435,27436,27439,27445,27446,27451,27455,27462,27466,27469,27474,27478,27480,27485,27488,27495,27499,27502,27504,27509,27517,27518,27522,27525,27543,27547,27551,27552,27554,27555,27560,27561,27564,27565,27566,27568,27576,27577,27581,27582,27587,27588,27593,27596,27606,27610,27617,27619,27622,27623,27630,27633,27639,27641,27647,27650,27652,27653,27657,27661,27662,27664,27666,27673,27679,27686,27687,27688,27692,27694,27699,27701,27702,27706,27707,27711,27722,27723,27725,27727,27730,27732,27737,27739,27740,27755,27757,27759,27764,27766,27768,27769,27771,27781,27782,27783,27785,27796,27797,27799,27800,27804,27807,27824,27826,27828,27842,27846,27853,27855,27856,27857,27858,27860,27862,27866,27868,27872,27879,27881,27883,27884,27886,27890,27892,27908,27911,27914,27918,27919,27921,27923,27930,27942,27943,27944,27751,27950,27951,27953,27961,27964,27967,27991,27998,27999,28001,28005,28007,28015,28016,28028,28034,28039,28049,28050,28052,28054,28055,28056,28074,28076,28084,28087,28089,28093,28095,28100,28104,28106,28110,28111,28118,28123,28125,28127,28128,28130,28133,28137,28143,28144,28148,28150,28156,28160,28164,28190,28194,28199,28210,28214,28217,28219,28220,28228,28229,28232,28233,28235,28239,28241,28242,28243,28244,28247,28252,28253,28254,28258,28259,28264,28275,28283,28285,28301,28307,28313,28320,28327,28333,28334,28337,28339,28347,28351,28352,28353,28355,28359,28360,28362,28365,28366,28367,28395,28397,28398,28409,28411,28413,28420,28424,28426,28428,28429,28438,28440,28442,28443,28454,28457,28458,28463,28464,28467,28470,28475,28476,28461,28495,28497,28498,28499,28503,28505,28506,28509,28510,28513,28514,28520,28524,28541,28542,28547,28551,28552,28555,28556,28557,28560,28562,28563,28564,28566,28570,28575,28576,28581,28582,28583,28584,28590,28591,28592,28597,28598,28604,28613,28615,28616,28618,28634,28638,28648,28649,28656,28661,28665,28668,28669,28672,28677,28678,28679,28685,28695,28704,28707,28719,28724,28727,28729,28732,28739,28740,28744,28745,28746,28747,28756,28757,28765,28766,28750,28772,28773,28780,28782,28789,28790,28798,28801,28805,28806,28820,28821,28822,28823,28824,28827,28836,28843,28848,28849,28852,28855,28874,28881,28883,28884,28885,28886,28888,28892,28900,28922,28931,28932,28933,28934,28935,28939,28940,28943,28958,28960,28971,28973,28975,28976,28977,28984,28993,28997,28998,28999,29002,29003,29008,29010,29015,29018,29020,29022,29024,29032,29049,29056,29061,29063,29068,29074,29082,29083,29088,29090,29103,29104,29106,29107,29114,29119,29120,29121,29124,29131,29132,29139,29142,29145,29146,29148,29176,29182,29184,29191,29192,29193,29203,29207,29210,29213,29215,29220,29227,29231,29236,29240,29241,29249,29250,29251,29253,29262,29263,29264,29267,29269,29270,29274,29276,29278,29280,29283,29288,29291,29294,29295,29297,29303,29304,29307,29308,29311,29316,29321,29325,29326,29331,29339,29352,29357,29358,29361,29364,29374,29377,29383,29385,29388,29397,29398,29400,29407,29413,29427,29428,29434,29435,29438,29442,29444,29445,29447,29451,29453,29458,29459,29464,29465,29470,29474,29476,29479,29480,29484,29489,29490,29493,29498,29499,29501,29507,29517,29520,29522,29526,29528,29533,29534,29535,29536,29542,29543,29545,29547,29548,29550,29551,29553,29559,29561,29564,29568,29569,29571,29573,29574,29582,29584,29587,29589,29591,29592,29596,29598,29599,29600,29602,29605,29606,29610,29611,29613,29621,29623,29625,29628,29629,29631,29637,29638,29641,29643,29644,29647,29650,29651,29654,29657,29661,29665,29667,29670,29671,29673,29684,29685,29687,29689,29690,29691,29693,29695,29696,29697,29700,29703,29706,29713,29722,29723,29732,29734,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29753,29760,29763,29764,29766,29767,29771,29773,29777,29778,29783,29789,29794,29798,29799,29800,29803,29805,29806,29809,29810,29824,29825,29829,29830,29831,29833,29839,29840,29841,29842,29848,29849,29850,29852,29855,29856,29857,29859,29862,29864,29865,29866,29867,29870,29871,29873,29874,29877,29881,29883,29887,29896,29897,29900,29904,29907,29912,29914,29915,29918,29919,29924,29928,29930,29931,29935,29940,29946,29947,29948,29951,29958,29970,29974,29975,29984,29985,29988,29991,29993,29994,29999,30006,30009,30013,30014,30015,30016,30019,30023,30024,30030,30032,30034,30039,30046,30047,30049,30063,30065,30073,30074,30075,30076,30077,30078,30081,30085,30096,30098,30099,30101,30105,30108,30114,30116,30132,30138,30143,30144,30145,30148,30150,30156,30158,30159,30167,30172,30175,30176,30177,30180,30183,30188,30190,30191,30193,30201,30208,30210,30211,30212,30215,30216,30218,30220,30223,30226,30227,30229,30230,30233,30235,30236,30237,30238,30243,30245,30246,30249,30253,30258,30259,30261,30264,30265,30266,30268,30282,30272,30273,30275,30276,30277,30281,30283,30293,30297,30303,30308,30309,30317,30318,30319,30321,30324,30337,30341,30348,30349,30357,30363,30364,30365,30367,30368,30370,30371,30372,30373,30374,30375,30376,30378,30381,30397,30401,30405,30409,30411,30412,30414,30420,30425,30432,30438,30440,30444,30448,30449,30454,30457,30460,30464,30470,30474,30478,30482,30484,30485,30487,30489,30490,30492,30498,30504,30509,30510,30511,30516,30517,30518,30521,30525,30526,30530,30533,30534,30538,30541,30542,30543,30546,30550,30551,30556,30558,30559,30560,30562,30564,30567,30570,30572,30576,30578,30579,30580,30586,30589,30592,30596,30604,30605,30612,30613,30614,30618,30623,30626,30631,30634,30638,30639,30641,30645,30654,30659,30665,30673,30674,30677,30681,30686,30687,30688,30692,30694,30698,30700,30704,30705,30708,30712,30715,30725,30726,30729,30733,30734,30737,30749,30753,30754,30755,30765,30766,30768,30773,30775,30787,30788,30791,30792,30796,30798,30802,30812,30814,30816,30817,30819,30820,30824,30826,30830,30842,30846,30858,30863,30868,30872,30881,30877,30878,30879,30884,30888,30892,30893,30896,30897,30898,30899,30907,30909,30911,30919,30920,30921,30924,30926,30930,30931,30933,30934,30948,30939,30943,30944,30945,30950,30954,30962,30963,30976,30966,30967,30970,30971,30975,30982,30988,30992,31002,31004,31006,31007,31008,31013,31015,31017,31021,31025,31028,31029,31035,31037,31039,31044,31045,31046,31050,31051,31055,31057,31060,31064,31067,31068,31079,31081,31083,31090,31097,31099,31100,31102,31115,31116,31121,31123,31124,31125,31126,31128,31131,31132,31137,31144,31145,31147,31151,31153,31156,31160,31163,31170,31172,31175,31176,31178,31183,31188,31190,31194,31197,31198,31200,31202,31205,31210,31211,31213,31217,31224,31228,31234,31235,31239,31241,31242,31244,31249,31253,31259,31262,31265,31271,31275,31277,31279,31280,31284,31285,31288,31289,31290,31300,31301,31303,31304,31308,31317,31318,31321,31324,31325,31327,31328,31333,31335,31338,31341,31349,31352,31358,31360,31362,31365,31366,31370,31371,31376,31377,31380,31390,31392,31395,31404,31411,31413,31417,31419,31420,31430,31433,31436,31438,31441,31451,31464,31465,31467,31468,31473,31476,31483,31485,31486,31495,31508,31519,31523,31527,31529,31530,31531,31533,31534,31535,31536,31537,31540,31549,31551,31552,31553,31559,31566,31573,31584,31588,31590,31593,31594,31597,31599,31602,31603,31607,31620,31625,31630,31632,31633,31638,31643,31646,31648,31653,31660,31663,31664,31666,31669,31670,31674,31675,31676,31677,31682,31685,31688,31690,31700,31702,31703,31705,31706,31707,31720,31722,31730,31732,31733,31736,31737,31738,31740,31742,31745,31746,31747,31748,31750,31753,31755,31756,31758,31759,31769,31771,31776,31781,31782,31784,31788,31793,31795,31796,31798,31801,31802,31814,31818,31829,31825,31826,31827,31833,31834,31835,31836,31837,31838,31841,31843,31847,31849,31853,31854,31856,31858,31865,31868,31869,31878,31879,31887,31892,31902,31904,31910,31920,31926,31927,31930,31931,31932,31935,31940,31943,31944,31945,31949,31951,31955,31956,31957,31959,31961,31962,31965,31974,31977,31979,31989,32003,32007,32008,32009,32015,32017,32018,32019,32022,32029,32030,32035,32038,32042,32045,32049,32060,32061,32062,32064,32065,32071,32072,32077,32081,32083,32087,32089,32090,32092,32093,32101,32103,32106,32112,32120,32122,32123,32127,32129,32130,32131,32133,32134,32136,32139,32140,32141,32145,32150,32151,32157,32158,32166,32167,32170,32179,32182,32183,32185,32194,32195,32196,32197,32198,32204,32205,32206,32215,32217,32256,32226,32229,32230,32234,32235,32237,32241,32245,32246,32249,32250,32264,32272,32273,32277,32279,32284,32285,32288,32295,32296,32300,32301,32303,32307,32310,32319,32324,32325,32327,32334,32336,32338,32344,32351,32353,32354,32357,32363,32366,32367,32371,32376,32382,32385,32390,32391,32394,32397,32401,32405,32408,32410,32413,32414,32572,32571,32573,32574,32575,32579,32580,32583,32591,32594,32595,32603,32604,32605,32609,32611,32612,32613,32614,32621,32625,32637,32638,32639,32640,32651,32653,32655,32656,32657,32662,32663,32668,32673,32674,32678,32682,32685,32692,32700,32703,32704,32707,32712,32718,32719,32731,32735,32739,32741,32744,32748,32750,32751,32754,32762,32765,32766,32767,32775,32776,32778,32781,32782,32783,32785,32787,32788,32790,32797,32798,32799,32800,32804,32806,32812,32814,32816,32820,32821,32823,32825,32826,32828,32830,32832,32836,32864,32868,32870,32877,32881,32885,32897,32904,32910,32924,32926,32934,32935,32939,32952,32953,32968,32973,32975,32978,32980,32981,32983,32984,32992,33005,33006,33008,33010,33011,33014,33017,33018,33022,33027,33035,33046,33047,33048,33052,33054,33056,33060,33063,33068,33072,33077,33082,33084,33093,33095,33098,33100,33106,33111,33120,33121,33127,33128,33129,33133,33135,33143,33153,33168,33156,33157,33158,33163,33166,33174,33176,33179,33182,33186,33198,33202,33204,33211,33227,33219,33221,33226,33230,33231,33237,33239,33243,33245,33246,33249,33252,33259,33260,33264,33265,33266,33269,33270,33272,33273,33277,33279,33280,33283,33295,33299,33300,33305,33306,33309,33313,33314,33320,33330,33332,33338,33347,33348,33349,33350,33355,33358,33359,33361,33366,33372,33376,33379,33383,33389,33396,33403,33405,33407,33408,33409,33411,33412,33415,33417,33418,33422,33425,33428,33430,33432,33434,33435,33440,33441,33443,33444,33447,33448,33449,33450,33454,33456,33458,33460,33463,33466,33468,33470,33471,33478,33488,33493,33498,33504,33506,33508,33512,33514,33517,33519,33526,33527,33533,33534,33536,33537,33543,33544,33546,33547,33620,33563,33565,33566,33567,33569,33570,33580,33581,33582,33584,33587,33591,33594,33596,33597,33602,33603,33604,33607,33613,33614,33617,33621,33622,33623,33648,33656,33661,33663,33664,33666,33668,33670,33677,33682,33684,33685,33688,33689,33691,33692,33693,33702,33703,33705,33708,33726,33727,33728,33735,33737,33743,33744,33745,33748,33757,33619,33768,33770,33782,33784,33785,33788,33793,33798,33802,33807,33809,33813,33817,33709,33839,33849,33861,33863,33864,33866,33869,33871,33873,33874,33878,33880,33881,33882,33884,33888,33892,33893,33895,33898,33904,33907,33908,33910,33912,33916,33917,33921,33925,33938,33939,33941,33950,33958,33960,33961,33962,33967,33969,33972,33978,33981,33982,33984,33986,33991,33992,33996,33999,34003,34012,34023,34026,34031,34032,34033,34034,34039,34098,34042,34043,34045,34050,34051,34055,34060,34062,34064,34076,34078,34082,34083,34084,34085,34087,34090,34091,34095,34099,34100,34102,34111,34118,34127,34128,34129,34130,34131,34134,34137,34140,34141,34142,34143,34144,34145,34146,34148,34155,34159,34169,34170,34171,34173,34175,34177,34181,34182,34185,34187,34188,34191,34195,34200,34205,34207,34208,34210,34213,34215,34228,34230,34231,34232,34236,34237,34238,34239,34242,34247,34250,34251,34254,34221,34264,34266,34271,34272,34278,34280,34285,34291,34294,34300,34303,34304,34308,34309,34317,34318,34320,34321,34322,34328,34329,34331,34334,34337,34343,34345,34358,34360,34362,34364,34365,34368,34370,34374,34386,34387,34390,34391,34392,34393,34397,34400,34401,34402,34403,34404,34409,34412,34415,34421,34422,34423,34426,34445,34449,34454,34456,34458,34460,34465,34470,34471,34472,34477,34481,34483,34484,34485,34487,34488,34489,34495,34496,34497,34499,34501,34513,34514,34517,34519,34522,34524,34528,34531,34533,34535,34440,34554,34556,34557,34564,34565,34567,34571,34574,34575,34576,34579,34580,34585,34590,34591,34593,34595,34600,34606,34607,34609,34610,34617,34618,34620,34621,34622,34624,34627,34629,34637,34648,34653,34657,34660,34661,34671,34673,34674,34683,34691,34692,34693,34694,34695,34696,34697,34699,34700,34704,34707,34709,34711,34712,34713,34718,34720,34723,34727,34732,34733,34734,34737,34741,34750,34751,34753,34760,34761,34762,34766,34773,34774,34777,34778,34780,34783,34786,34787,34788,34794,34795,34797,34801,34803,34808,34810,34815,34817,34819,34822,34825,34826,34827,34832,34841,34834,34835,34836,34840,34842,34843,34844,34846,34847,34856,34861,34862,34864,34866,34869,34874,34876,34881,34883,34885,34888,34889,34890,34891,34894,34897,34901,34902,34904,34906,34908,34911,34912,34916,34921,34929,34937,34939,34944,34968,34970,34971,34972,34975,34976,34984,34986,35002,35005,35006,35008,35018,35019,35020,35021,35022,35025,35026,35027,35035,35038,35047,35055,35056,35057,35061,35063,35073,35078,35085,35086,35087,35093,35094,35096,35097,35098,35100,35104,35110,35111,35112,35120,35121,35122,35125,35129,35130,35134,35136,35138,35141,35142,35145,35151,35154,35159,35162,35163,35164,35169,35170,35171,35179,35182,35184,35187,35189,35194,35195,35196,35197,35209,35213,35216,35220,35221,35227,35228,35231,35232,35237,35248,35252,35253,35254,35255,35260,35284,35285,35286,35287,35288,35301,35305,35307,35309,35313,35315,35318,35321,35325,35327,35332,35333,35335,35343,35345,35346,35348,35349,35358,35360,35362,35364,35366,35371,35372,35375,35381,35383,35389,35390,35392,35395,35397,35399,35401,35405,35406,35411,35414,35415,35416,35420,35421,35425,35429,35431,35445,35446,35447,35449,35450,35451,35454,35455,35456,35459,35462,35467,35471,35472,35474,35478,35479,35481,35487,35495,35497,35502,35503,35507,35510,35511,35515,35518,35523,35526,35528,35529,35530,35537,35539,35540,35541,35543,35549,35551,35564,35568,35572,35573,35574,35580,35583,35589,35590,35595,35601,35612,35614,35615,35594,35629,35632,35639,35644,35650,35651,35652,35653,35654,35656,35666,35667,35668,35673,35661,35678,35683,35693,35702,35704,35705,35708,35710,35713,35716,35717,35723,35725,35727,35732,35733,35740,35742,35743,35896,35897,35901,35902,35909,35911,35913,35915,35919,35921,35923,35924,35927,35928,35931,35933,35929,35939,35940,35942,35944,35945,35949,35955,35957,35958,35963,35966,35974,35975,35979,35984,35986,35987,35993,35995,35996,36004,36025,36026,36037,36038,36041,36043,36047,36054,36053,36057,36061,36065,36072,36076,36079,36080,36082,36085,36087,36088,36094,36095,36097,36099,36105,36114,36119,36123,36197,36201,36204,36206,36223,36226,36228,36232,36237,36240,36241,36245,36254,36255,36256,36262,36267,36268,36271,36274,36277,36279,36281,36283,36288,36293,36294,36295,36296,36298,36302,36305,36308,36309,36311,36313,36324,36325,36327,36332,36336,36284,36337,36338,36340,36349,36353,36356,36357,36358,36363,36369,36372,36374,36384,36385,36386,36387,36390,36391,36401,36403,36406,36407,36408,36409,36413,36416,36417,36427,36429,36430,36431,36436,36443,36444,36445,36446,36449,36450,36457,36460,36461,36463,36464,36465,36473,36474,36475,36482,36483,36489,36496,36498,36501,36506,36507,36509,36510,36514,36519,36521,36525,36526,36531,36533,36538,36539,36544,36545,36547,36548,36551,36559,36561,36564,36572,36584,36590,36592,36593,36599,36601,36602,36589,36608,36610,36615,36616,36623,36624,36630,36631,36632,36638,36640,36641,36643,36645,36647,36648,36652,36653,36654,36660,36661,36662,36663,36666,36672,36673,36675,36679,36687,36689,36690,36691,36692,36693,36696,36701,36702,36709,36765,36768,36769,36772,36773,36774,36789,36790,36792,36798,36800,36801,36806,36810,36811,36813,36816,36818,36819,36821,36832,36835,36836,36840,36846,36849,36853,36854,36859,36862,36866,36868,36872,36876,36888,36891,36904,36905,36911,36906,36908,36909,36915,36916,36919,36927,36931,36932,36940,36955,36957,36962,36966,36967,36972,36976,36980,36985,36997,37000,37003,37004,37006,37008,37013,37015,37016,37017,37019,37024,37025,37026,37029,37040,37042,37043,37044,37046,37053,37068,37054,37059,37060,37061,37063,37064,37077,37079,37080,37081,37084,37085,37087,37093,37074,37110,37099,37103,37104,37108,37118,37119,37120,37124,37125,37126,37128,37133,37136,37140,37142,37143,37144,37146,37148,37150,37152,37157,37154,37155,37159,37161,37166,37167,37169,37172,37174,37175,37177,37178,37180,37181,37187,37191,37192,37199,37203,37207,37209,37210,37211,37217,37220,37223,37229,37236,37241,37242,37243,37249,37251,37253,37254,37258,37262,37265,37267,37268,37269,37272,37278,37281,37286,37288,37292,37293,37294,37296,37297,37298,37299,37302,37307,37308,37309,37311,37314,37315,37317,37331,37332,37335,37337,37338,37342,37348,37349,37353,37354,37356,37357,37358,37359,37360,37361,37367,37369,37371,37373,37376,37377,37380,37381,37382,37383,37385,37386,37388,37392,37394,37395,37398,37400,37404,37405,37411,37412,37413,37414,37416,37422,37423,37424,37427,37429,37430,37432,37433,37434,37436,37438,37440,37442,37443,37446,37447,37450,37453,37454,37455,37457,37464,37465,37468,37469,37472,37473,37477,37479,37480,37481,37486,37487,37488,37493,37494,37495,37496,37497,37499,37500,37501,37503,37512,37513,37514,37517,37518,37522,37527,37529,37535,37536,37540,37541,37543,37544,37547,37551,37554,37558,37560,37562,37563,37564,37565,37567,37568,37569,37570,37571,37573,37574,37575,37576,37579,37580,37581,37582,37584,37587,37589,37591,37592,37593,37596,37597,37599,37600,37601,37603,37605,37607,37608,37612,37614,37616,37625,37627,37631,37632,37634,37640,37645,37649,37652,37653,37660,37661,37662,37663,37665,37668,37669,37671,37673,37674,37683,37684,37686,37687,37703,37704,37705,37712,37713,37714,37717,37719,37720,37722,37726,37732,37733,37735,37737,37738,37741,37743,37744,37745,37747,37748,37750,37754,37757,37759,37760,37761,37762,37768,37770,37771,37773,37775,37778,37781,37784,37787,37790,37793,37795,37796,37798,37800,37803,37812,37813,37814,37818,37801,37825,37828,37829,37830,37831,37833,37834,37835,37836,37837,37843,37849,37852,37854,37855,37858,37862,37863,37881,37879,37880,37882,37883,37885,37889,37890,37892,37896,37897,37901,37902,37903,37909,37910,37911,37919,37934,37935,37937,37938,37939,37940,37947,37951,37949,37955,37957,37960,37962,37964,37973,37977,37980,37983,37985,37987,37992,37995,37997,37998,37999,38001,38002,38020,38019,38264,38265,38270,38276,38280,38284,38285,38286,38301,38302,38303,38305,38310,38313,38315,38316,38324,38326,38330,38333,38335,38342,38344,38345,38347,38352,38353,38354,38355,38361,38362,38365,38366,38367,38368,38372,38374,38429,38430,38434,38436,38437,38438,38444,38449,38451,38455,38456,38457,38458,38460,38461,38465,38482,38484,38486,38487,38488,38497,38510,38516,38523,38524,38526,38527,38529,38530,38531,38532,38537,38545,38550,38554,38557,38559,38564,38565,38566,38569,38574,38575,38579,38586,38602,38610,23986,38616,38618,38621,38622,38623,38633,38639,38641,38650,38658,38659,38661,38665,38682,38683,38685,38689,38690,38691,38696,38705,38707,38721,38723,38730,38734,38735,38741,38743,38744,38746,38747,38755,38759,38762,38766,38771,38774,38775,38776,38779,38781,38783,38784,38793,38805,38806,38807,38809,38810,38814,38815,38818,38828,38830,38833,38834,38837,38838,38840,38841,38842,38844,38846,38847,38849,38852,38853,38855,38857,38858,38860,38861,38862,38864,38865,38868,38871,38872,38873,38877,38878,38880,38875,38881,38884,38895,38897,38900,38903,38904,38906,38919,38922,38937,38925,38926,38932,38934,38940,38942,38944,38947,38950,38955,38958,38959,38960,38962,38963,38965,38949,38974,38980,38983,38986,38993,38994,38995,38998,38999,39001,39002,39010,39011,39013,39014,39018,39020,39083,39085,39086,39088,39092,39095,39096,39098,39099,39103,39106,39109,39112,39116,39137,39139,39141,39142,39143,39146,39155,39158,39170,39175,39176,39185,39189,39190,39191,39194,39195,39196,39199,39202,39206,39207,39211,39217,39218,39219,39220,39221,39225,39226,39227,39228,39232,39233,39238,39239,39240,39245,39246,39252,39256,39257,39259,39260,39262,39263,39264,39323,39325,39327,39334,39344,39345,39346,39349,39353,39354,39357,39359,39363,39369,39379,39380,39385,39386,39388,39390,39399,39402,39403,39404,39408,39412,39413,39417,39421,39422,39426,39427,39428,39435,39436,39440,39441,39446,39454,39456,39458,39459,39460,39463,39469,39470,39475,39477,39478,39480,39495,39489,39492,39498,39499,39500,39502,39505,39508,39510,39517,39594,39596,39598,39599,39602,39604,39605,39606,39609,39611,39614,39615,39617,39619,39622,39624,39630,39632,39634,39637,39638,39639,39643,39644,39648,39652,39653,39655,39657,39660,39666,39667,39669,39673,39674,39677,39679,39680,39681,39682,39683,39684,39685,39688,39689,39691,39692,39693,39694,39696,39698,39702,39705,39707,39708,39712,39718,39723,39725,39731,39732,39733,39735,39737,39738,39741,39752,39755,39756,39765,39766,39767,39771,39774,39777,39779,39781,39782,39784,39786,39787,39788,39789,39790,39795,39797,39799,39800,39801,39807,39808,39812,39813,39814,39815,39817,39818,39819,39821,39823,39824,39828,39834,39837,39838,39846,39847,39849,39852,39856,39857,39858,39863,39864,39867,39868,39870,39871,39873,39879,39880,39886,39888,39895,39896,39901,39903,39909,39911,39914,39915,39919,39923,39927,39928,39929,39930,39933,39935,39936,39938,39947,39951,39953,39958,39960,39961,39962,39964,39966,39970,39971,39974,39975,39976,39977,39978,39985,39989,39990,39991,39997,40001,40003,40004,40005,40009,40010,40014,40015,40016,40019,40020,40022,40024,40027,40029,40030,40031,40035,40041,40042,40028,40043,40040,40046,40048,40050,40053,40055,40059,40166,40178,40183,40185,40203,40194,40209,40215,40216,40220,40221,40222,40239,40240,40242,40243,40244,40250,40252,40261,40253,40258,40259,40263,40266,40275,40276,40287,40291,40290,40293,40297,40298,40299,40304,40310,40311,40315,40316,40318,40323,40324,40326,40330,40333,40334,40338,40339,40341,40342,40343,40344,40353,40362,40364,40366,40369,40373,40377,40380,40383,40387,40391,40393,40394,40404,40405,40406,40407,40410,40414,40415,40416,40421,40423,40425,40427,40430,40432,40435,40436,40446,40458,40450,40455,40462,40464,40465,40466,40469,40470,40473,40476,40477,40570,40571,40572,40576,40578,40579,40580,40581,40583,40590,40591,40598,40600,40603,40606,40612,40616,40620,40622,40623,40624,40627,40628,40629,40646,40648,40651,40661,40671,40676,40679,40684,40685,40686,40688,40689,40690,40693,40696,40703,40706,40707,40713,40719,40720,40721,40722,40724,40726,40727,40729,40730,40731,40735,40738,40742,40746,40747,40751,40753,40754,40756,40759,40761,40762,40764,40765,40767,40769,40771,40772,40773,40774,40775,40787,40789,40790,40791,40792,40794,40797,40798,40808,40809,40813,40814,40815,40816,40817,40819,40821,40826,40829,40847,40848,40849,40850,40852,40854,40855,40862,40865,40866,40867,40869,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null], + "ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160], + "iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729], + "iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729], + "iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119], + "iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null], + "iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312], + "iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217], + "iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255], + "iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255], + "koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066], + "macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711], + "windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null], + "windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729], + "windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103], + "windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255], + "windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null], + "windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255], + "windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null], + "windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746], + "windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729], + "windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255], + "x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364] + }; + + // For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + }(this || {})); + },{}],110:[function(require,module,exports){ + // This is free and unencumbered software released into the public domain. + // See LICENSE.md for more information. + + /** + * @fileoverview Global |this| required for resolving indexes in node. + * @suppress {globalThis} + */ + (function(global) { + + // If we're in node require encoding-indexes and attach it to the global. + if (typeof module !== "undefined" && module.exports && + !global["encoding-indexes"]) { + global["encoding-indexes"] = + require("./encoding-indexes.js")["encoding-indexes"]; + } + + // + // Utilities + // + + /** + * @param {number} a The number to test. + * @param {number} min The minimum value in the range, inclusive. + * @param {number} max The maximum value in the range, inclusive. + * @return {boolean} True if a >= min and a <= max. + */ + function inRange(a, min, max) { + return min <= a && a <= max; + } + + /** + * @param {!Array.<*>} array The array to check. + * @param {*} item The item to look for in the array. + * @return {boolean} True if the item appears in the array. + */ + function includes(array, item) { + return array.indexOf(item) !== -1; + } + + var floor = Math.floor; + + /** + * @param {*} o + * @return {Object} + */ + function ToDictionary(o) { + if (o === undefined) return {}; + if (o === Object(o)) return o; + throw TypeError('Could not convert argument to dictionary'); + } + + /** + * @param {string} string Input string of UTF-16 code units. + * @return {!Array.} Code points. + */ + function stringToCodePoints(string) { + // https://heycam.github.io/webidl/#dfn-obtain-unicode + + // 1. Let S be the DOMString value. + var s = String(string); + + // 2. Let n be the length of S. + var n = s.length; + + // 3. Initialize i to 0. + var i = 0; + + // 4. Initialize U to be an empty sequence of Unicode characters. + var u = []; + + // 5. While i < n: + while (i < n) { + + // 1. Let c be the code unit in S at index i. + var c = s.charCodeAt(i); + + // 2. Depending on the value of c: + + // c < 0xD800 or c > 0xDFFF + if (c < 0xD800 || c > 0xDFFF) { + // Append to U the Unicode character with code point c. + u.push(c); + } + + // 0xDC00 ≤ c ≤ 0xDFFF + else if (0xDC00 <= c && c <= 0xDFFF) { + // Append to U a U+FFFD REPLACEMENT CHARACTER. + u.push(0xFFFD); + } + + // 0xD800 ≤ c ≤ 0xDBFF + else if (0xD800 <= c && c <= 0xDBFF) { + // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT + // CHARACTER. + if (i === n - 1) { + u.push(0xFFFD); + } + // 2. Otherwise, i < n−1: + else { + // 1. Let d be the code unit in S at index i+1. + var d = s.charCodeAt(i + 1); + + // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: + if (0xDC00 <= d && d <= 0xDFFF) { + // 1. Let a be c & 0x3FF. + var a = c & 0x3FF; + + // 2. Let b be d & 0x3FF. + var b = d & 0x3FF; + + // 3. Append to U the Unicode character with code point + // 2^16+2^10*a+b. + u.push(0x10000 + (a << 10) + b); + + // 4. Set i to i+1. + i += 1; + } + + // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a + // U+FFFD REPLACEMENT CHARACTER. + else { + u.push(0xFFFD); + } + } + } + + // 3. Set i to i+1. + i += 1; + } + + // 6. Return U. + return u; + } + + /** + * @param {!Array.} code_points Array of code points. + * @return {string} string String of UTF-16 code units. + */ + function codePointsToString(code_points) { + var s = ''; + for (var i = 0; i < code_points.length; ++i) { + var cp = code_points[i]; + if (cp <= 0xFFFF) { + s += String.fromCharCode(cp); + } else { + cp -= 0x10000; + s += String.fromCharCode((cp >> 10) + 0xD800, + (cp & 0x3FF) + 0xDC00); + } + } + return s; + } + + + // + // Implementation of Encoding specification + // https://encoding.spec.whatwg.org/ + // + + // + // 4. Terminology + // + + /** + * An ASCII byte is a byte in the range 0x00 to 0x7F, inclusive. + * @param {number} a The number to test. + * @return {boolean} True if a is in the range 0x00 to 0x7F, inclusive. + */ + function isASCIIByte(a) { + return 0x00 <= a && a <= 0x7F; + } + + /** + * An ASCII code point is a code point in the range U+0000 to + * U+007F, inclusive. + */ + var isASCIICodePoint = isASCIIByte; + + + /** + * End-of-stream is a special token that signifies no more tokens + * are in the stream. + * @const + */ var end_of_stream = -1; + + /** + * A stream represents an ordered sequence of tokens. + * + * @constructor + * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide + * the stream. + */ + function Stream(tokens) { + /** @type {!Array.} */ + this.tokens = [].slice.call(tokens); + // Reversed as push/pop is more efficient than shift/unshift. + this.tokens.reverse(); + } + + Stream.prototype = { + /** + * @return {boolean} True if end-of-stream has been hit. + */ + endOfStream: function() { + return !this.tokens.length; + }, + + /** + * When a token is read from a stream, the first token in the + * stream must be returned and subsequently removed, and + * end-of-stream must be returned otherwise. + * + * @return {number} Get the next token from the stream, or + * end_of_stream. + */ + read: function() { + if (!this.tokens.length) + return end_of_stream; + return this.tokens.pop(); + }, + + /** + * When one or more tokens are prepended to a stream, those tokens + * must be inserted, in given order, before the first token in the + * stream. + * + * @param {(number|!Array.)} token The token(s) to prepend to the + * stream. + */ + prepend: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.push(tokens.pop()); + } else { + this.tokens.push(token); + } + }, + + /** + * When one or more tokens are pushed to a stream, those tokens + * must be inserted, in given order, after the last token in the + * stream. + * + * @param {(number|!Array.)} token The tokens(s) to push to the + * stream. + */ + push: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.unshift(tokens.shift()); + } else { + this.tokens.unshift(token); + } + } + }; + + // + // 5. Encodings + // + + // 5.1 Encoders and decoders + + /** @const */ + var finished = -1; + + /** + * @param {boolean} fatal If true, decoding errors raise an exception. + * @param {number=} opt_code_point Override the standard fallback code point. + * @return {number} The code point to insert on a decoding error. + */ + function decoderError(fatal, opt_code_point) { + if (fatal) + throw TypeError('Decoder error'); + return opt_code_point || 0xFFFD; + } + + /** + * @param {number} code_point The code point that could not be encoded. + * @return {number} Always throws, no value is actually returned. + */ + function encoderError(code_point) { + throw TypeError('The code point ' + code_point + ' could not be encoded.'); + } + + // 5.2 Names and labels + + // TODO: Define @typedef for Encoding: {name:string,labels:Array.} + // https://github.com/google/closure-compiler/issues/247 + + /** + * @param {string} label The encoding label. + * @return {?{name:string,labels:Array.}} + */ + function getEncoding(label) { + // 1. Remove any leading and trailing ASCII whitespace from label. + label = String(label).trim().toLowerCase(); + + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, return the corresponding + // encoding, and failure otherwise. + if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) { + return label_to_encoding[label]; + } + return null; + } + + /** + * Encodings table: https://encoding.spec.whatwg.org/encodings.json + * @const + * @type {!Array.<{ + * heading: string, + * encodings: Array.<{name:string,labels:Array.}> + * }>} + */ + var encodings = [ + { + "encodings": [ + { + "labels": [ + "unicode-1-1-utf-8", + "utf-8", + "utf8" + ], + "name": "UTF-8" + } + ], + "heading": "The Encoding" + }, + { + "encodings": [ + { + "labels": [ + "866", + "cp866", + "csibm866", + "ibm866" + ], + "name": "IBM866" + }, + { + "labels": [ + "csisolatin2", + "iso-8859-2", + "iso-ir-101", + "iso8859-2", + "iso88592", + "iso_8859-2", + "iso_8859-2:1987", + "l2", + "latin2" + ], + "name": "ISO-8859-2" + }, + { + "labels": [ + "csisolatin3", + "iso-8859-3", + "iso-ir-109", + "iso8859-3", + "iso88593", + "iso_8859-3", + "iso_8859-3:1988", + "l3", + "latin3" + ], + "name": "ISO-8859-3" + }, + { + "labels": [ + "csisolatin4", + "iso-8859-4", + "iso-ir-110", + "iso8859-4", + "iso88594", + "iso_8859-4", + "iso_8859-4:1988", + "l4", + "latin4" + ], + "name": "ISO-8859-4" + }, + { + "labels": [ + "csisolatincyrillic", + "cyrillic", + "iso-8859-5", + "iso-ir-144", + "iso8859-5", + "iso88595", + "iso_8859-5", + "iso_8859-5:1988" + ], + "name": "ISO-8859-5" + }, + { + "labels": [ + "arabic", "asmo-708", "csiso88596e", "csiso88596i", @@ -9340,8627 +33780,38738 @@ "x-mac-cyrillic", "x-mac-ukrainian" ], - "name": "x-mac-cyrillic" + "name": "x-mac-cyrillic" + } + ], + "heading": "Legacy single-byte encodings" + }, + { + "encodings": [ + { + "labels": [ + "chinese", + "csgb2312", + "csiso58gb231280", + "gb2312", + "gb_2312", + "gb_2312-80", + "gbk", + "iso-ir-58", + "x-gbk" + ], + "name": "GBK" + }, + { + "labels": [ + "gb18030" + ], + "name": "gb18030" + } + ], + "heading": "Legacy multi-byte Chinese (simplified) encodings" + }, + { + "encodings": [ + { + "labels": [ + "big5", + "big5-hkscs", + "cn-big5", + "csbig5", + "x-x-big5" + ], + "name": "Big5" + } + ], + "heading": "Legacy multi-byte Chinese (traditional) encodings" + }, + { + "encodings": [ + { + "labels": [ + "cseucpkdfmtjapanese", + "euc-jp", + "x-euc-jp" + ], + "name": "EUC-JP" + }, + { + "labels": [ + "csiso2022jp", + "iso-2022-jp" + ], + "name": "ISO-2022-JP" + }, + { + "labels": [ + "csshiftjis", + "ms932", + "ms_kanji", + "shift-jis", + "shift_jis", + "sjis", + "windows-31j", + "x-sjis" + ], + "name": "Shift_JIS" + } + ], + "heading": "Legacy multi-byte Japanese encodings" + }, + { + "encodings": [ + { + "labels": [ + "cseuckr", + "csksc56011987", + "euc-kr", + "iso-ir-149", + "korean", + "ks_c_5601-1987", + "ks_c_5601-1989", + "ksc5601", + "ksc_5601", + "windows-949" + ], + "name": "EUC-KR" + } + ], + "heading": "Legacy multi-byte Korean encodings" + }, + { + "encodings": [ + { + "labels": [ + "csiso2022kr", + "hz-gb-2312", + "iso-2022-cn", + "iso-2022-cn-ext", + "iso-2022-kr" + ], + "name": "replacement" + }, + { + "labels": [ + "utf-16be" + ], + "name": "UTF-16BE" + }, + { + "labels": [ + "utf-16", + "utf-16le" + ], + "name": "UTF-16LE" + }, + { + "labels": [ + "x-user-defined" + ], + "name": "x-user-defined" + } + ], + "heading": "Legacy miscellaneous encodings" + } + ]; + + // Label to encoding registry. + /** @type {Object.}>} */ + var label_to_encoding = {}; + encodings.forEach(function(category) { + category.encodings.forEach(function(encoding) { + encoding.labels.forEach(function(label) { + label_to_encoding[label] = encoding; + }); + }); + }); + + // Registry of of encoder/decoder factories, by encoding name. + /** @type {Object.} */ + var encoders = {}; + /** @type {Object.} */ + var decoders = {}; + + // + // 6. Indexes + // + + /** + * @param {number} pointer The |pointer| to search for. + * @param {(!Array.|undefined)} index The |index| to search within. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in |index|. + */ + function indexCodePointFor(pointer, index) { + if (!index) return null; + return index[pointer] || null; + } + + /** + * @param {number} code_point The |code point| to search for. + * @param {!Array.} index The |index| to search within. + * @return {?number} The first pointer corresponding to |code point| in + * |index|, or null if |code point| is not in |index|. + */ + function indexPointerFor(code_point, index) { + var pointer = index.indexOf(code_point); + return pointer === -1 ? null : pointer; + } + + /** + * @param {string} name Name of the index. + * @return {(!Array.|!Array.>)} + * */ + function index(name) { + if (!('encoding-indexes' in global)) { + throw Error("Indexes missing." + + " Did you forget to include encoding-indexes.js first?"); + } + return global['encoding-indexes'][name]; + } + + /** + * @param {number} pointer The |pointer| to search for in the gb18030 index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the gb18030 index. + */ + function indexGB18030RangesCodePointFor(pointer) { + // 1. If pointer is greater than 39419 and less than 189000, or + // pointer is greater than 1237575, return null. + if ((pointer > 39419 && pointer < 189000) || (pointer > 1237575)) + return null; + + // 2. If pointer is 7457, return code point U+E7C7. + if (pointer === 7457) return 0xE7C7; + + // 3. Let offset be the last pointer in index gb18030 ranges that + // is equal to or less than pointer and let code point offset be + // its corresponding code point. + var offset = 0; + var code_point_offset = 0; + var idx = index('gb18030-ranges'); + var i; + for (i = 0; i < idx.length; ++i) { + /** @type {!Array.} */ + var entry = idx[i]; + if (entry[0] <= pointer) { + offset = entry[0]; + code_point_offset = entry[1]; + } else { + break; + } + } + + // 4. Return a code point whose value is code point offset + + // pointer − offset. + return code_point_offset + pointer - offset; + } + + /** + * @param {number} code_point The |code point| to locate in the gb18030 index. + * @return {number} The first pointer corresponding to |code point| in the + * gb18030 index. + */ + function indexGB18030RangesPointerFor(code_point) { + // 1. If code point is U+E7C7, return pointer 7457. + if (code_point === 0xE7C7) return 7457; + + // 2. Let offset be the last code point in index gb18030 ranges + // that is equal to or less than code point and let pointer offset + // be its corresponding pointer. + var offset = 0; + var pointer_offset = 0; + var idx = index('gb18030-ranges'); + var i; + for (i = 0; i < idx.length; ++i) { + /** @type {!Array.} */ + var entry = idx[i]; + if (entry[1] <= code_point) { + offset = entry[1]; + pointer_offset = entry[0]; + } else { + break; + } + } + + // 3. Return a pointer whose value is pointer offset + code point + // − offset. + return pointer_offset + code_point - offset; + } + + /** + * @param {number} code_point The |code_point| to search for in the Shift_JIS + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the Shift_JIS index. + */ + function indexShiftJISPointerFor(code_point) { + // 1. Let index be index jis0208 excluding all entries whose + // pointer is in the range 8272 to 8835, inclusive. + shift_jis_index = shift_jis_index || + index('jis0208').map(function(code_point, pointer) { + return inRange(pointer, 8272, 8835) ? null : code_point; + }); + var index_ = shift_jis_index; + + // 2. Return the index pointer for code point in index. + return index_.indexOf(code_point); + } + var shift_jis_index; + + /** + * @param {number} code_point The |code_point| to search for in the big5 + * index. + * @return {?number} The code point corresponding to |pointer| in |index|, + * or null if |code point| is not in the big5 index. + */ + function indexBig5PointerFor(code_point) { + // 1. Let index be index Big5 excluding all entries whose pointer + big5_index_no_hkscs = big5_index_no_hkscs || + index('big5').map(function(code_point, pointer) { + return (pointer < (0xA1 - 0x81) * 157) ? null : code_point; + }); + var index_ = big5_index_no_hkscs; + + // 2. If code point is U+2550, U+255E, U+2561, U+256A, U+5341, or + // U+5345, return the last pointer corresponding to code point in + // index. + if (code_point === 0x2550 || code_point === 0x255E || + code_point === 0x2561 || code_point === 0x256A || + code_point === 0x5341 || code_point === 0x5345) { + return index_.lastIndexOf(code_point); + } + + // 3. Return the index pointer for code point in index. + return indexPointerFor(code_point, index_); + } + var big5_index_no_hkscs; + + // + // 8. API + // + + /** @const */ var DEFAULT_ENCODING = 'utf-8'; + + // 8.1 Interface TextDecoder + + /** + * @constructor + * @param {string=} label The label of the encoding; + * defaults to 'utf-8'. + * @param {Object=} options + */ + function TextDecoder(label, options) { + // Web IDL conventions + if (!(this instanceof TextDecoder)) + throw TypeError('Called as a function. Did you forget \'new\'?'); + label = label !== undefined ? String(label) : DEFAULT_ENCODING; + options = ToDictionary(options); + + // A TextDecoder object has an associated encoding, decoder, + // stream, ignore BOM flag (initially unset), BOM seen flag + // (initially unset), error mode (initially replacement), and do + // not flush flag (initially unset). + + /** @private */ + this._encoding = null; + /** @private @type {?Decoder} */ + this._decoder = null; + /** @private @type {boolean} */ + this._ignoreBOM = false; + /** @private @type {boolean} */ + this._BOMseen = false; + /** @private @type {string} */ + this._error_mode = 'replacement'; + /** @private @type {boolean} */ + this._do_not_flush = false; + + + // 1. Let encoding be the result of getting an encoding from + // label. + var encoding = getEncoding(label); + + // 2. If encoding is failure or replacement, throw a RangeError. + if (encoding === null || encoding.name === 'replacement') + throw RangeError('Unknown encoding: ' + label); + if (!decoders[encoding.name]) { + throw Error('Decoder not present.' + + ' Did you forget to include encoding-indexes.js first?'); + } + + // 3. Let dec be a new TextDecoder object. + var dec = this; + + // 4. Set dec's encoding to encoding. + dec._encoding = encoding; + + // 5. If options's fatal member is true, set dec's error mode to + // fatal. + if (Boolean(options['fatal'])) + dec._error_mode = 'fatal'; + + // 6. If options's ignoreBOM member is true, set dec's ignore BOM + // flag. + if (Boolean(options['ignoreBOM'])) + dec._ignoreBOM = true; + + // For pre-ES5 runtimes: + if (!Object.defineProperty) { + this.encoding = dec._encoding.name.toLowerCase(); + this.fatal = dec._error_mode === 'fatal'; + this.ignoreBOM = dec._ignoreBOM; + } + + // 7. Return dec. + return dec; + } + + if (Object.defineProperty) { + // The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextDecoder.prototype, 'encoding', { + /** @this {TextDecoder} */ + get: function() { return this._encoding.name.toLowerCase(); } + }); + + // The fatal attribute's getter must return true if error mode + // is fatal, and false otherwise. + Object.defineProperty(TextDecoder.prototype, 'fatal', { + /** @this {TextDecoder} */ + get: function() { return this._error_mode === 'fatal'; } + }); + + // The ignoreBOM attribute's getter must return true if ignore + // BOM flag is set, and false otherwise. + Object.defineProperty(TextDecoder.prototype, 'ignoreBOM', { + /** @this {TextDecoder} */ + get: function() { return this._ignoreBOM; } + }); + } + + /** + * @param {BufferSource=} input The buffer of bytes to decode. + * @param {Object=} options + * @return {string} The decoded string. + */ + TextDecoder.prototype.decode = function decode(input, options) { + var bytes; + if (typeof input === 'object' && input instanceof ArrayBuffer) { + bytes = new Uint8Array(input); + } else if (typeof input === 'object' && 'buffer' in input && + input.buffer instanceof ArrayBuffer) { + bytes = new Uint8Array(input.buffer, + input.byteOffset, + input.byteLength); + } else { + bytes = new Uint8Array(0); + } + + options = ToDictionary(options); + + // 1. If the do not flush flag is unset, set decoder to a new + // encoding's decoder, set stream to a new stream, and unset the + // BOM seen flag. + if (!this._do_not_flush) { + this._decoder = decoders[this._encoding.name]({ + fatal: this._error_mode === 'fatal'}); + this._BOMseen = false; + } + + // 2. If options's stream is true, set the do not flush flag, and + // unset the do not flush flag otherwise. + this._do_not_flush = Boolean(options['stream']); + + // 3. If input is given, push a copy of input to stream. + // TODO: Align with spec algorithm - maintain stream on instance. + var input_stream = new Stream(bytes); + + // 4. Let output be a new stream. + var output = []; + + /** @type {?(number|!Array.)} */ + var result; + + // 5. While true: + while (true) { + // 1. Let token be the result of reading from stream. + var token = input_stream.read(); + + // 2. If token is end-of-stream and the do not flush flag is + // set, return output, serialized. + // TODO: Align with spec algorithm. + if (token === end_of_stream) + break; + + // 3. Otherwise, run these subsubsteps: + + // 1. Let result be the result of processing token for decoder, + // stream, output, and error mode. + result = this._decoder.handler(input_stream, token); + + // 2. If result is finished, return output, serialized. + if (result === finished) + break; + + if (result !== null) { + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + + // 3. Otherwise, if result is error, throw a TypeError. + // (Thrown in handler) + + // 4. Otherwise, do nothing. + } + // TODO: Align with spec algorithm. + if (!this._do_not_flush) { + do { + result = this._decoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (result === null) + continue; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } while (!input_stream.endOfStream()); + this._decoder = null; + } + + // A TextDecoder object also has an associated serialize stream + // algorithm... + /** + * @param {!Array.} stream + * @return {string} + * @this {TextDecoder} + */ + function serializeStream(stream) { + // 1. Let token be the result of reading from stream. + // (Done in-place on array, rather than as a stream) + + // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore + // BOM flag and BOM seen flag are unset, run these subsubsteps: + if (includes(['UTF-8', 'UTF-16LE', 'UTF-16BE'], this._encoding.name) && + !this._ignoreBOM && !this._BOMseen) { + if (stream.length > 0 && stream[0] === 0xFEFF) { + // 1. If token is U+FEFF, set BOM seen flag. + this._BOMseen = true; + stream.shift(); + } else if (stream.length > 0) { + // 2. Otherwise, if token is not end-of-stream, set BOM seen + // flag and append token to stream. + this._BOMseen = true; + } else ; + } + // 4. Otherwise, return output. + return codePointsToString(stream); + } + + return serializeStream.call(this, output); + }; + + // 8.2 Interface TextEncoder + + /** + * @constructor + * @param {string=} label The label of the encoding. NONSTANDARD. + * @param {Object=} options NONSTANDARD. + */ + function TextEncoder(label, options) { + // Web IDL conventions + if (!(this instanceof TextEncoder)) + throw TypeError('Called as a function. Did you forget \'new\'?'); + options = ToDictionary(options); + + // A TextEncoder object has an associated encoding and encoder. + + /** @private */ + this._encoding = null; + /** @private @type {?Encoder} */ + this._encoder = null; + + // Non-standard + /** @private @type {boolean} */ + this._do_not_flush = false; + /** @private @type {string} */ + this._fatal = Boolean(options['fatal']) ? 'fatal' : 'replacement'; + + // 1. Let enc be a new TextEncoder object. + var enc = this; + + // 2. Set enc's encoding to UTF-8's encoder. + if (Boolean(options['NONSTANDARD_allowLegacyEncoding'])) { + // NONSTANDARD behavior. + label = label !== undefined ? String(label) : DEFAULT_ENCODING; + var encoding = getEncoding(label); + if (encoding === null || encoding.name === 'replacement') + throw RangeError('Unknown encoding: ' + label); + if (!encoders[encoding.name]) { + throw Error('Encoder not present.' + + ' Did you forget to include encoding-indexes.js first?'); + } + enc._encoding = encoding; + } else { + // Standard behavior. + enc._encoding = getEncoding('utf-8'); + + if (label !== undefined && 'console' in global) { + console.warn('TextEncoder constructor called with encoding label, ' + + 'which is ignored.'); + } + } + + // For pre-ES5 runtimes: + if (!Object.defineProperty) + this.encoding = enc._encoding.name.toLowerCase(); + + // 3. Return enc. + return enc; + } + + if (Object.defineProperty) { + // The encoding attribute's getter must return encoding's name. + Object.defineProperty(TextEncoder.prototype, 'encoding', { + /** @this {TextEncoder} */ + get: function() { return this._encoding.name.toLowerCase(); } + }); + } + + /** + * @param {string=} opt_string The string to encode. + * @param {Object=} options + * @return {!Uint8Array} Encoded bytes, as a Uint8Array. + */ + TextEncoder.prototype.encode = function encode(opt_string, options) { + opt_string = opt_string === undefined ? '' : String(opt_string); + options = ToDictionary(options); + + // NOTE: This option is nonstandard. None of the encodings + // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when + // the input is a USVString so streaming is not necessary. + if (!this._do_not_flush) + this._encoder = encoders[this._encoding.name]({ + fatal: this._fatal === 'fatal'}); + this._do_not_flush = Boolean(options['stream']); + + // 1. Convert input to a stream. + var input = new Stream(stringToCodePoints(opt_string)); + + // 2. Let output be a new stream + var output = []; + + /** @type {?(number|!Array.)} */ + var result; + // 3. While true, run these substeps: + while (true) { + // 1. Let token be the result of reading from input. + var token = input.read(); + if (token === end_of_stream) + break; + // 2. Let result be the result of processing token for encoder, + // input, output. + result = this._encoder.handler(input, token); + if (result === finished) + break; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + // TODO: Align with spec algorithm. + if (!this._do_not_flush) { + while (true) { + result = this._encoder.handler(input, input.read()); + if (result === finished) + break; + if (Array.isArray(result)) + output.push.apply(output, /**@type {!Array.}*/(result)); + else + output.push(result); + } + this._encoder = null; + } + // 3. If result is finished, convert output into a byte sequence, + // and then return a Uint8Array object wrapping an ArrayBuffer + // containing output. + return new Uint8Array(output); + }; + + + // + // 9. The encoding + // + + // 9.1 utf-8 + + // 9.1.1 utf-8 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function UTF8Decoder(options) { + var fatal = options.fatal; + + // utf-8's decoder's has an associated utf-8 code point, utf-8 + // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 + // lower boundary (initially 0x80), and a utf-8 upper boundary + // (initially 0xBF). + var /** @type {number} */ utf8_code_point = 0, + /** @type {number} */ utf8_bytes_seen = 0, + /** @type {number} */ utf8_bytes_needed = 0, + /** @type {number} */ utf8_lower_boundary = 0x80, + /** @type {number} */ utf8_upper_boundary = 0xBF; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, + // set utf-8 bytes needed to 0 and return error. + if (bite === end_of_stream && utf8_bytes_needed !== 0) { + utf8_bytes_needed = 0; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 3. If utf-8 bytes needed is 0, based on byte: + if (utf8_bytes_needed === 0) { + + // 0x00 to 0x7F + if (inRange(bite, 0x00, 0x7F)) { + // Return a code point whose value is byte. + return bite; + } + + // 0xC2 to 0xDF + else if (inRange(bite, 0xC2, 0xDF)) { + // 1. Set utf-8 bytes needed to 1. + utf8_bytes_needed = 1; + + // 2. Set UTF-8 code point to byte & 0x1F. + utf8_code_point = bite & 0x1F; + } + + // 0xE0 to 0xEF + else if (inRange(bite, 0xE0, 0xEF)) { + // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. + if (bite === 0xE0) + utf8_lower_boundary = 0xA0; + // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. + if (bite === 0xED) + utf8_upper_boundary = 0x9F; + // 3. Set utf-8 bytes needed to 2. + utf8_bytes_needed = 2; + // 4. Set UTF-8 code point to byte & 0xF. + utf8_code_point = bite & 0xF; + } + + // 0xF0 to 0xF4 + else if (inRange(bite, 0xF0, 0xF4)) { + // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. + if (bite === 0xF0) + utf8_lower_boundary = 0x90; + // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. + if (bite === 0xF4) + utf8_upper_boundary = 0x8F; + // 3. Set utf-8 bytes needed to 3. + utf8_bytes_needed = 3; + // 4. Set UTF-8 code point to byte & 0x7. + utf8_code_point = bite & 0x7; + } + + // Otherwise + else { + // Return error. + return decoderError(fatal); + } + + // Return continue. + return null; + } + + // 4. If byte is not in the range utf-8 lower boundary to utf-8 + // upper boundary, inclusive, run these substeps: + if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { + + // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 + // bytes seen to 0, set utf-8 lower boundary to 0x80, and set + // utf-8 upper boundary to 0xBF. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 2. Prepend byte to stream. + stream.prepend(bite); + + // 3. Return error. + return decoderError(fatal); + } + + // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary + // to 0xBF. + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 6. Set UTF-8 code point to (UTF-8 code point << 6) | (byte & + // 0x3F) + utf8_code_point = (utf8_code_point << 6) | (bite & 0x3F); + + // 7. Increase utf-8 bytes seen by one. + utf8_bytes_seen += 1; + + // 8. If utf-8 bytes seen is not equal to utf-8 bytes needed, + // continue. + if (utf8_bytes_seen !== utf8_bytes_needed) + return null; + + // 9. Let code point be utf-8 code point. + var code_point = utf8_code_point; + + // 10. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes + // seen to 0. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + + // 11. Return a code point whose value is code point. + return code_point; + }; + } + + // 9.1.2 utf-8 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function UTF8Encoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Set count and offset based on the range code point is in: + var count, offset; + // U+0080 to U+07FF, inclusive: + if (inRange(code_point, 0x0080, 0x07FF)) { + // 1 and 0xC0 + count = 1; + offset = 0xC0; + } + // U+0800 to U+FFFF, inclusive: + else if (inRange(code_point, 0x0800, 0xFFFF)) { + // 2 and 0xE0 + count = 2; + offset = 0xE0; + } + // U+10000 to U+10FFFF, inclusive: + else if (inRange(code_point, 0x10000, 0x10FFFF)) { + // 3 and 0xF0 + count = 3; + offset = 0xF0; + } + + // 4. Let bytes be a byte sequence whose first byte is (code + // point >> (6 × count)) + offset. + var bytes = [(code_point >> (6 * count)) + offset]; + + // 5. Run these substeps while count is greater than 0: + while (count > 0) { + + // 1. Set temp to code point >> (6 × (count − 1)). + var temp = code_point >> (6 * (count - 1)); + + // 2. Append to bytes 0x80 | (temp & 0x3F). + bytes.push(0x80 | (temp & 0x3F)); + + // 3. Decrease count by one. + count -= 1; + } + + // 6. Return bytes bytes, in order. + return bytes; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['UTF-8'] = function(options) { + return new UTF8Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['UTF-8'] = function(options) { + return new UTF8Decoder(options); + }; + + // + // 10. Legacy single-byte encodings + // + + // 10.1 single-byte decoder + /** + * @constructor + * @implements {Decoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */ + function SingleByteDecoder(index, options) { + var fatal = options.fatal; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 3. Let code point be the index code point for byte − 0x80 in + // index single-byte. + var code_point = index[bite - 0x80]; + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + }; + } + + // 10.2 single-byte encoder + /** + * @constructor + * @implements {Encoder} + * @param {!Array.} index The encoding index. + * @param {{fatal: boolean}} options + */ + function SingleByteEncoder(index, options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index pointer for code point in index + // single-byte. + var pointer = indexPointerFor(code_point, index); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + encoderError(code_point); + + // 5. Return a byte whose value is pointer + 0x80. + return pointer + 0x80; + }; + } + + (function() { + if (!('encoding-indexes' in global)) + return; + encodings.forEach(function(category) { + if (category.heading !== 'Legacy single-byte encodings') + return; + category.encodings.forEach(function(encoding) { + var name = encoding.name; + var idx = index(name.toLowerCase()); + /** @param {{fatal: boolean}} options */ + decoders[name] = function(options) { + return new SingleByteDecoder(idx, options); + }; + /** @param {{fatal: boolean}} options */ + encoders[name] = function(options) { + return new SingleByteEncoder(idx, options); + }; + }); + }); + }()); + + // + // 11. Legacy multi-byte Chinese (simplified) encodings + // + + // 11.1 gbk + + // 11.1.1 gbk decoder + // gbk's decoder is gb18030's decoder. + /** @param {{fatal: boolean}} options */ + decoders['GBK'] = function(options) { + return new GB18030Decoder(options); + }; + + // 11.1.2 gbk encoder + // gbk's encoder is gb18030's encoder with its gbk flag set. + /** @param {{fatal: boolean}} options */ + encoders['GBK'] = function(options) { + return new GB18030Encoder(options, true); + }; + + // 11.2 gb18030 + + // 11.2.1 gb18030 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function GB18030Decoder(options) { + var fatal = options.fatal; + // gb18030's decoder has an associated gb18030 first, gb18030 + // second, and gb18030 third (all initially 0x00). + var /** @type {number} */ gb18030_first = 0x00, + /** @type {number} */ gb18030_second = 0x00, + /** @type {number} */ gb18030_third = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and gb18030 first, gb18030 + // second, and gb18030 third are 0x00, return finished. + if (bite === end_of_stream && gb18030_first === 0x00 && + gb18030_second === 0x00 && gb18030_third === 0x00) { + return finished; + } + // 2. If byte is end-of-stream, and gb18030 first, gb18030 + // second, or gb18030 third is not 0x00, set gb18030 first, + // gb18030 second, and gb18030 third to 0x00, and return error. + if (bite === end_of_stream && + (gb18030_first !== 0x00 || gb18030_second !== 0x00 || + gb18030_third !== 0x00)) { + gb18030_first = 0x00; + gb18030_second = 0x00; + gb18030_third = 0x00; + decoderError(fatal); + } + var code_point; + // 3. If gb18030 third is not 0x00, run these substeps: + if (gb18030_third !== 0x00) { + // 1. Let code point be null. + code_point = null; + // 2. If byte is in the range 0x30 to 0x39, inclusive, set + // code point to the index gb18030 ranges code point for + // (((gb18030 first − 0x81) × 10 + gb18030 second − 0x30) × + // 126 + gb18030 third − 0x81) × 10 + byte − 0x30. + if (inRange(bite, 0x30, 0x39)) { + code_point = indexGB18030RangesCodePointFor( + (((gb18030_first - 0x81) * 10 + gb18030_second - 0x30) * 126 + + gb18030_third - 0x81) * 10 + bite - 0x30); + } + + // 3. Let buffer be a byte sequence consisting of gb18030 + // second, gb18030 third, and byte, in order. + var buffer = [gb18030_second, gb18030_third, bite]; + + // 4. Set gb18030 first, gb18030 second, and gb18030 third to + // 0x00. + gb18030_first = 0x00; + gb18030_second = 0x00; + gb18030_third = 0x00; + + // 5. If code point is null, prepend buffer to stream and + // return error. + if (code_point === null) { + stream.prepend(buffer); + return decoderError(fatal); + } + + // 6. Return a code point whose value is code point. + return code_point; + } + + // 4. If gb18030 second is not 0x00, run these substeps: + if (gb18030_second !== 0x00) { + + // 1. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 third to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + gb18030_third = bite; + return null; + } + + // 2. Prepend gb18030 second followed by byte to stream, set + // gb18030 first and gb18030 second to 0x00, and return error. + stream.prepend([gb18030_second, bite]); + gb18030_first = 0x00; + gb18030_second = 0x00; + return decoderError(fatal); + } + + // 5. If gb18030 first is not 0x00, run these substeps: + if (gb18030_first !== 0x00) { + + // 1. If byte is in the range 0x30 to 0x39, inclusive, set + // gb18030 second to byte and return continue. + if (inRange(bite, 0x30, 0x39)) { + gb18030_second = bite; + return null; + } + + // 2. Let lead be gb18030 first, let pointer be null, and set + // gb18030 first to 0x00. + var lead = gb18030_first; + var pointer = null; + gb18030_first = 0x00; + + // 3. Let offset be 0x40 if byte is less than 0x7F and 0x41 + // otherwise. + var offset = bite < 0x7F ? 0x40 : 0x41; + + // 4. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 190 + + // (byte − offset). + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFE)) + pointer = (lead - 0x81) * 190 + (bite - offset); + + // 5. Let code point be null if pointer is null and the index + // code point for pointer in index gb18030 otherwise. + code_point = pointer === null ? null : + indexCodePointFor(pointer, index('gb18030')); + + // 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 7. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 8. Return a code point whose value is code point. + return code_point; + } + + // 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 7. If byte is 0x80, return code point U+20AC. + if (bite === 0x80) + return 0x20AC; + + // 8. If byte is in the range 0x81 to 0xFE, inclusive, set + // gb18030 first to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + gb18030_first = bite; + return null; + } + + // 9. Return error. + return decoderError(fatal); + }; + } + + // 11.2.2 gb18030 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + * @param {boolean=} gbk_flag + */ + function GB18030Encoder(options, gbk_flag) { + options.fatal; + // gb18030's decoder has an associated gbk flag (initially unset). + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is U+E5E5, return error with code point. + if (code_point === 0xE5E5) + return encoderError(code_point); + + // 4. If the gbk flag is set and code point is U+20AC, return + // byte 0x80. + if (gbk_flag && code_point === 0x20AC) + return 0x80; + + // 5. Let pointer be the index pointer for code point in index + // gb18030. + var pointer = indexPointerFor(code_point, index('gb18030')); + + // 6. If pointer is not null, run these substeps: + if (pointer !== null) { + + // 1. Let lead be floor(pointer / 190) + 0x81. + var lead = floor(pointer / 190) + 0x81; + + // 2. Let trail be pointer % 190. + var trail = pointer % 190; + + // 3. Let offset be 0x40 if trail is less than 0x3F and 0x41 otherwise. + var offset = trail < 0x3F ? 0x40 : 0x41; + + // 4. Return two bytes whose values are lead and trail + offset. + return [lead, trail + offset]; + } + + // 7. If gbk flag is set, return error with code point. + if (gbk_flag) + return encoderError(code_point); + + // 8. Set pointer to the index gb18030 ranges pointer for code + // point. + pointer = indexGB18030RangesPointerFor(code_point); + + // 9. Let byte1 be floor(pointer / 10 / 126 / 10). + var byte1 = floor(pointer / 10 / 126 / 10); + + // 10. Set pointer to pointer − byte1 × 10 × 126 × 10. + pointer = pointer - byte1 * 10 * 126 * 10; + + // 11. Let byte2 be floor(pointer / 10 / 126). + var byte2 = floor(pointer / 10 / 126); + + // 12. Set pointer to pointer − byte2 × 10 × 126. + pointer = pointer - byte2 * 10 * 126; + + // 13. Let byte3 be floor(pointer / 10). + var byte3 = floor(pointer / 10); + + // 14. Let byte4 be pointer − byte3 × 10. + var byte4 = pointer - byte3 * 10; + + // 15. Return four bytes whose values are byte1 + 0x81, byte2 + + // 0x30, byte3 + 0x81, byte4 + 0x30. + return [byte1 + 0x81, + byte2 + 0x30, + byte3 + 0x81, + byte4 + 0x30]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['gb18030'] = function(options) { + return new GB18030Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['gb18030'] = function(options) { + return new GB18030Decoder(options); + }; + + + // + // 12. Legacy multi-byte Chinese (traditional) encodings + // + + // 12.1 Big5 + + // 12.1.1 Big5 decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function Big5Decoder(options) { + var fatal = options.fatal; + // Big5's decoder has an associated Big5 lead (initially 0x00). + var /** @type {number} */ Big5_lead = 0x00; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and Big5 lead is not 0x00, set + // Big5 lead to 0x00 and return error. + if (bite === end_of_stream && Big5_lead !== 0x00) { + Big5_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and Big5 lead is 0x00, return + // finished. + if (bite === end_of_stream && Big5_lead === 0x00) + return finished; + + // 3. If Big5 lead is not 0x00, let lead be Big5 lead, let + // pointer be null, set Big5 lead to 0x00, and then run these + // substeps: + if (Big5_lead !== 0x00) { + var lead = Big5_lead; + var pointer = null; + Big5_lead = 0x00; + + // 1. Let offset be 0x40 if byte is less than 0x7F and 0x62 + // otherwise. + var offset = bite < 0x7F ? 0x40 : 0x62; + + // 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1 + // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 + + // (byte − offset). + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0xA1, 0xFE)) + pointer = (lead - 0x81) * 157 + (bite - offset); + + // 3. If there is a row in the table below whose first column + // is pointer, return the two code points listed in its second + // column + // Pointer | Code points + // --------+-------------- + // 1133 | U+00CA U+0304 + // 1135 | U+00CA U+030C + // 1164 | U+00EA U+0304 + // 1166 | U+00EA U+030C + switch (pointer) { + case 1133: return [0x00CA, 0x0304]; + case 1135: return [0x00CA, 0x030C]; + case 1164: return [0x00EA, 0x0304]; + case 1166: return [0x00EA, 0x030C]; + } + + // 4. Let code point be null if pointer is null and the index + // code point for pointer in index Big5 otherwise. + var code_point = (pointer === null) ? null : + indexCodePointFor(pointer, index('big5')); + + // 5. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 6. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 7. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5 + // lead to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + Big5_lead = bite; + return null; + } + + // 6. Return error. + return decoderError(fatal); + }; + } + + // 12.1.2 Big5 encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function Big5Encoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index Big5 pointer for code point. + var pointer = indexBig5PointerFor(code_point); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 5. Let lead be floor(pointer / 157) + 0x81. + var lead = floor(pointer / 157) + 0x81; + + // 6. If lead is less than 0xA1, return error with code point. + if (lead < 0xA1) + return encoderError(code_point); + + // 7. Let trail be pointer % 157. + var trail = pointer % 157; + + // 8. Let offset be 0x40 if trail is less than 0x3F and 0x62 + // otherwise. + var offset = trail < 0x3F ? 0x40 : 0x62; + + // Return two bytes whose values are lead and trail + offset. + return [lead, trail + offset]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['Big5'] = function(options) { + return new Big5Encoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['Big5'] = function(options) { + return new Big5Decoder(options); + }; + + + // + // 13. Legacy multi-byte Japanese encodings + // + + // 13.1 euc-jp + + // 13.1.1 euc-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function EUCJPDecoder(options) { + var fatal = options.fatal; + + // euc-jp's decoder has an associated euc-jp jis0212 flag + // (initially unset) and euc-jp lead (initially 0x00). + var /** @type {boolean} */ eucjp_jis0212_flag = false, + /** @type {number} */ eucjp_lead = 0x00; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and euc-jp lead is not 0x00, set + // euc-jp lead to 0x00, and return error. + if (bite === end_of_stream && eucjp_lead !== 0x00) { + eucjp_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and euc-jp lead is 0x00, return + // finished. + if (bite === end_of_stream && eucjp_lead === 0x00) + return finished; + + // 3. If euc-jp lead is 0x8E and byte is in the range 0xA1 to + // 0xDF, inclusive, set euc-jp lead to 0x00 and return a code + // point whose value is 0xFF61 − 0xA1 + byte. + if (eucjp_lead === 0x8E && inRange(bite, 0xA1, 0xDF)) { + eucjp_lead = 0x00; + return 0xFF61 - 0xA1 + bite; + } + + // 4. If euc-jp lead is 0x8F and byte is in the range 0xA1 to + // 0xFE, inclusive, set the euc-jp jis0212 flag, set euc-jp lead + // to byte, and return continue. + if (eucjp_lead === 0x8F && inRange(bite, 0xA1, 0xFE)) { + eucjp_jis0212_flag = true; + eucjp_lead = bite; + return null; + } + + // 5. If euc-jp lead is not 0x00, let lead be euc-jp lead, set + // euc-jp lead to 0x00, and run these substeps: + if (eucjp_lead !== 0x00) { + var lead = eucjp_lead; + eucjp_lead = 0x00; + + // 1. Let code point be null. + var code_point = null; + + // 2. If lead and byte are both in the range 0xA1 to 0xFE, + // inclusive, set code point to the index code point for (lead + // − 0xA1) × 94 + byte − 0xA1 in index jis0208 if the euc-jp + // jis0212 flag is unset and in index jis0212 otherwise. + if (inRange(lead, 0xA1, 0xFE) && inRange(bite, 0xA1, 0xFE)) { + code_point = indexCodePointFor( + (lead - 0xA1) * 94 + (bite - 0xA1), + index(!eucjp_jis0212_flag ? 'jis0208' : 'jis0212')); + } + + // 3. Unset the euc-jp jis0212 flag. + eucjp_jis0212_flag = false; + + // 4. If byte is not in the range 0xA1 to 0xFE, inclusive, + // prepend byte to stream. + if (!inRange(bite, 0xA1, 0xFE)) + stream.prepend(bite); + + // 5. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 6. Return a code point whose value is code point. + return code_point; + } + + // 6. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 7. If byte is 0x8E, 0x8F, or in the range 0xA1 to 0xFE, + // inclusive, set euc-jp lead to byte and return continue. + if (bite === 0x8E || bite === 0x8F || inRange(bite, 0xA1, 0xFE)) { + eucjp_lead = bite; + return null; + } + + // 8. Return error. + return decoderError(fatal); + }; + } + + // 13.1.2 euc-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function EUCJPEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 4. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + + // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return two bytes whose values are 0x8E and code point − + // 0xFF61 + 0xA1. + if (inRange(code_point, 0xFF61, 0xFF9F)) + return [0x8E, code_point - 0xFF61 + 0xA1]; + + // 6. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 7. Let pointer be the index pointer for code point in index + // jis0208. + var pointer = indexPointerFor(code_point, index('jis0208')); + + // 8. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 9. Let lead be floor(pointer / 94) + 0xA1. + var lead = floor(pointer / 94) + 0xA1; + + // 10. Let trail be pointer % 94 + 0xA1. + var trail = pointer % 94 + 0xA1; + + // 11. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['EUC-JP'] = function(options) { + return new EUCJPEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['EUC-JP'] = function(options) { + return new EUCJPDecoder(options); + }; + + // 13.2 iso-2022-jp + + // 13.2.1 iso-2022-jp decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function ISO2022JPDecoder(options) { + var fatal = options.fatal; + /** @enum */ + var states = { + ASCII: 0, + Roman: 1, + Katakana: 2, + LeadByte: 3, + TrailByte: 4, + EscapeStart: 5, + Escape: 6 + }; + // iso-2022-jp's decoder has an associated iso-2022-jp decoder + // state (initially ASCII), iso-2022-jp decoder output state + // (initially ASCII), iso-2022-jp lead (initially 0x00), and + // iso-2022-jp output flag (initially unset). + var /** @type {number} */ iso2022jp_decoder_state = states.ASCII, + /** @type {number} */ iso2022jp_decoder_output_state = states.ASCII, + /** @type {number} */ iso2022jp_lead = 0x00, + /** @type {boolean} */ iso2022jp_output_flag = false; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // switching on iso-2022-jp decoder state: + switch (iso2022jp_decoder_state) { + default: + case states.ASCII: + // ASCII + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x00 to 0x7F, excluding 0x0E, 0x0F, and 0x1B + if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E + && bite !== 0x0F && bite !== 0x1B) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag = false; + return bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.Roman: + // Roman + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x5C + if (bite === 0x5C) { + // Unset the iso-2022-jp output flag and return code point + // U+00A5. + iso2022jp_output_flag = false; + return 0x00A5; + } + + // 0x7E + if (bite === 0x7E) { + // Unset the iso-2022-jp output flag and return code point + // U+203E. + iso2022jp_output_flag = false; + return 0x203E; + } + + // 0x00 to 0x7F, excluding 0x0E, 0x0F, 0x1B, 0x5C, and 0x7E + if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E && bite !== 0x0F + && bite !== 0x1B && bite !== 0x5C && bite !== 0x7E) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is byte. + iso2022jp_output_flag = false; + return bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.Katakana: + // Katakana + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x21 to 0x5F + if (inRange(bite, 0x21, 0x5F)) { + // Unset the iso-2022-jp output flag and return a code point + // whose value is 0xFF61 − 0x21 + byte. + iso2022jp_output_flag = false; + return 0xFF61 - 0x21 + bite; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.LeadByte: + // Lead byte + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return null; + } + + // 0x21 to 0x7E + if (inRange(bite, 0x21, 0x7E)) { + // Unset the iso-2022-jp output flag, set iso-2022-jp lead + // to byte, iso-2022-jp decoder state to trail byte, and + // return continue. + iso2022jp_output_flag = false; + iso2022jp_lead = bite; + iso2022jp_decoder_state = states.TrailByte; + return null; + } + + // end-of-stream + if (bite === end_of_stream) { + // Return finished. + return finished; + } + + // Otherwise + // Unset the iso-2022-jp output flag and return error. + iso2022jp_output_flag = false; + return decoderError(fatal); + + case states.TrailByte: + // Trail byte + // Based on byte: + + // 0x1B + if (bite === 0x1B) { + // Set iso-2022-jp decoder state to escape start and return + // continue. + iso2022jp_decoder_state = states.EscapeStart; + return decoderError(fatal); + } + + // 0x21 to 0x7E + if (inRange(bite, 0x21, 0x7E)) { + // 1. Set the iso-2022-jp decoder state to lead byte. + iso2022jp_decoder_state = states.LeadByte; + + // 2. Let pointer be (iso-2022-jp lead − 0x21) × 94 + byte − 0x21. + var pointer = (iso2022jp_lead - 0x21) * 94 + bite - 0x21; + + // 3. Let code point be the index code point for pointer in + // index jis0208. + var code_point = indexCodePointFor(pointer, index('jis0208')); + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + } + + // end-of-stream + if (bite === end_of_stream) { + // Set the iso-2022-jp decoder state to lead byte, prepend + // byte to stream, and return error. + iso2022jp_decoder_state = states.LeadByte; + stream.prepend(bite); + return decoderError(fatal); + } + + // Otherwise + // Set iso-2022-jp decoder state to lead byte and return + // error. + iso2022jp_decoder_state = states.LeadByte; + return decoderError(fatal); + + case states.EscapeStart: + // Escape start + + // 1. If byte is either 0x24 or 0x28, set iso-2022-jp lead to + // byte, iso-2022-jp decoder state to escape, and return + // continue. + if (bite === 0x24 || bite === 0x28) { + iso2022jp_lead = bite; + iso2022jp_decoder_state = states.Escape; + return null; + } + + // 2. Prepend byte to stream. + stream.prepend(bite); + + // 3. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state, and + // return error. + iso2022jp_output_flag = false; + iso2022jp_decoder_state = iso2022jp_decoder_output_state; + return decoderError(fatal); + + case states.Escape: + // Escape + + // 1. Let lead be iso-2022-jp lead and set iso-2022-jp lead to + // 0x00. + var lead = iso2022jp_lead; + iso2022jp_lead = 0x00; + + // 2. Let state be null. + var state = null; + + // 3. If lead is 0x28 and byte is 0x42, set state to ASCII. + if (lead === 0x28 && bite === 0x42) + state = states.ASCII; + + // 4. If lead is 0x28 and byte is 0x4A, set state to Roman. + if (lead === 0x28 && bite === 0x4A) + state = states.Roman; + + // 5. If lead is 0x28 and byte is 0x49, set state to Katakana. + if (lead === 0x28 && bite === 0x49) + state = states.Katakana; + + // 6. If lead is 0x24 and byte is either 0x40 or 0x42, set + // state to lead byte. + if (lead === 0x24 && (bite === 0x40 || bite === 0x42)) + state = states.LeadByte; + + // 7. If state is non-null, run these substeps: + if (state !== null) { + // 1. Set iso-2022-jp decoder state and iso-2022-jp decoder + // output state to states. + iso2022jp_decoder_state = iso2022jp_decoder_state = state; + + // 2. Let output flag be the iso-2022-jp output flag. + var output_flag = iso2022jp_output_flag; + + // 3. Set the iso-2022-jp output flag. + iso2022jp_output_flag = true; + + // 4. Return continue, if output flag is unset, and error + // otherwise. + return !output_flag ? null : decoderError(fatal); + } + + // 8. Prepend lead and byte to stream. + stream.prepend([lead, bite]); + + // 9. Unset the iso-2022-jp output flag, set iso-2022-jp + // decoder state to iso-2022-jp decoder output state and + // return error. + iso2022jp_output_flag = false; + iso2022jp_decoder_state = iso2022jp_decoder_output_state; + return decoderError(fatal); + } + }; + } + + // 13.2.2 iso-2022-jp encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function ISO2022JPEncoder(options) { + options.fatal; + // iso-2022-jp's encoder has an associated iso-2022-jp encoder + // state which is one of ASCII, Roman, and jis0208 (initially + // ASCII). + /** @enum */ + var states = { + ASCII: 0, + Roman: 1, + jis0208: 2 + }; + var /** @type {number} */ iso2022jp_state = states.ASCII; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream and iso-2022-jp encoder + // state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if (code_point === end_of_stream && + iso2022jp_state !== states.ASCII) { + stream.prepend(code_point); + iso2022jp_state = states.ASCII; + return [0x1B, 0x28, 0x42]; + } + + // 2. If code point is end-of-stream and iso-2022-jp encoder + // state is ASCII, return finished. + if (code_point === end_of_stream && iso2022jp_state === states.ASCII) + return finished; + + // 3. If ISO-2022-JP encoder state is ASCII or Roman, and code + // point is U+000E, U+000F, or U+001B, return error with U+FFFD. + if ((iso2022jp_state === states.ASCII || + iso2022jp_state === states.Roman) && + (code_point === 0x000E || code_point === 0x000F || + code_point === 0x001B)) { + return encoderError(0xFFFD); + } + + // 4. If iso-2022-jp encoder state is ASCII and code point is an + // ASCII code point, return a byte whose value is code point. + if (iso2022jp_state === states.ASCII && + isASCIICodePoint(code_point)) + return code_point; + + // 5. If iso-2022-jp encoder state is Roman and code point is an + // ASCII code point, excluding U+005C and U+007E, or is U+00A5 + // or U+203E, run these substeps: + if (iso2022jp_state === states.Roman && + ((isASCIICodePoint(code_point) && + code_point !== 0x005C && code_point !== 0x007E) || + (code_point == 0x00A5 || code_point == 0x203E))) { + + // 1. If code point is an ASCII code point, return a byte + // whose value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 2. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 3. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + } + + // 6. If code point is an ASCII code point, and iso-2022-jp + // encoder state is not ASCII, prepend code point to stream, set + // iso-2022-jp encoder state to ASCII, and return three bytes + // 0x1B 0x28 0x42. + if (isASCIICodePoint(code_point) && + iso2022jp_state !== states.ASCII) { + stream.prepend(code_point); + iso2022jp_state = states.ASCII; + return [0x1B, 0x28, 0x42]; + } + + // 7. If code point is either U+00A5 or U+203E, and iso-2022-jp + // encoder state is not Roman, prepend code point to stream, set + // iso-2022-jp encoder state to Roman, and return three bytes + // 0x1B 0x28 0x4A. + if ((code_point === 0x00A5 || code_point === 0x203E) && + iso2022jp_state !== states.Roman) { + stream.prepend(code_point); + iso2022jp_state = states.Roman; + return [0x1B, 0x28, 0x4A]; + } + + // 8. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 9. Let pointer be the index pointer for code point in index + // jis0208. + var pointer = indexPointerFor(code_point, index('jis0208')); + + // 10. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 11. If iso-2022-jp encoder state is not jis0208, prepend code + // point to stream, set iso-2022-jp encoder state to jis0208, + // and return three bytes 0x1B 0x24 0x42. + if (iso2022jp_state !== states.jis0208) { + stream.prepend(code_point); + iso2022jp_state = states.jis0208; + return [0x1B, 0x24, 0x42]; + } + + // 12. Let lead be floor(pointer / 94) + 0x21. + var lead = floor(pointer / 94) + 0x21; + + // 13. Let trail be pointer % 94 + 0x21. + var trail = pointer % 94 + 0x21; + + // 14. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['ISO-2022-JP'] = function(options) { + return new ISO2022JPEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['ISO-2022-JP'] = function(options) { + return new ISO2022JPDecoder(options); + }; + + // 13.3 Shift_JIS + + // 13.3.1 Shift_JIS decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function ShiftJISDecoder(options) { + var fatal = options.fatal; + // Shift_JIS's decoder has an associated Shift_JIS lead (initially + // 0x00). + var /** @type {number} */ Shift_JIS_lead = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and Shift_JIS lead is not 0x00, + // set Shift_JIS lead to 0x00 and return error. + if (bite === end_of_stream && Shift_JIS_lead !== 0x00) { + Shift_JIS_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and Shift_JIS lead is 0x00, + // return finished. + if (bite === end_of_stream && Shift_JIS_lead === 0x00) + return finished; + + // 3. If Shift_JIS lead is not 0x00, let lead be Shift_JIS lead, + // let pointer be null, set Shift_JIS lead to 0x00, and then run + // these substeps: + if (Shift_JIS_lead !== 0x00) { + var lead = Shift_JIS_lead; + var pointer = null; + Shift_JIS_lead = 0x00; + + // 1. Let offset be 0x40, if byte is less than 0x7F, and 0x41 + // otherwise. + var offset = (bite < 0x7F) ? 0x40 : 0x41; + + // 2. Let lead offset be 0x81, if lead is less than 0xA0, and + // 0xC1 otherwise. + var lead_offset = (lead < 0xA0) ? 0x81 : 0xC1; + + // 3. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 + // to 0xFC, inclusive, set pointer to (lead − lead offset) × + // 188 + byte − offset. + if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFC)) + pointer = (lead - lead_offset) * 188 + bite - offset; + + // 4. If pointer is in the range 8836 to 10715, inclusive, + // return a code point whose value is 0xE000 − 8836 + pointer. + if (inRange(pointer, 8836, 10715)) + return 0xE000 - 8836 + pointer; + + // 5. Let code point be null, if pointer is null, and the + // index code point for pointer in index jis0208 otherwise. + var code_point = (pointer === null) ? null : + indexCodePointFor(pointer, index('jis0208')); + + // 6. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (code_point === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 7. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 8. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte or 0x80, return a code point + // whose value is byte. + if (isASCIIByte(bite) || bite === 0x80) + return bite; + + // 5. If byte is in the range 0xA1 to 0xDF, inclusive, return a + // code point whose value is 0xFF61 − 0xA1 + byte. + if (inRange(bite, 0xA1, 0xDF)) + return 0xFF61 - 0xA1 + bite; + + // 6. If byte is in the range 0x81 to 0x9F, inclusive, or 0xE0 + // to 0xFC, inclusive, set Shift_JIS lead to byte and return + // continue. + if (inRange(bite, 0x81, 0x9F) || inRange(bite, 0xE0, 0xFC)) { + Shift_JIS_lead = bite; + return null; + } + + // 7. Return error. + return decoderError(fatal); + }; + } + + // 13.3.2 Shift_JIS encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function ShiftJISEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point or U+0080, return a + // byte whose value is code point. + if (isASCIICodePoint(code_point) || code_point === 0x0080) + return code_point; + + // 3. If code point is U+00A5, return byte 0x5C. + if (code_point === 0x00A5) + return 0x5C; + + // 4. If code point is U+203E, return byte 0x7E. + if (code_point === 0x203E) + return 0x7E; + + // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, + // return a byte whose value is code point − 0xFF61 + 0xA1. + if (inRange(code_point, 0xFF61, 0xFF9F)) + return code_point - 0xFF61 + 0xA1; + + // 6. If code point is U+2212, set it to U+FF0D. + if (code_point === 0x2212) + code_point = 0xFF0D; + + // 7. Let pointer be the index Shift_JIS pointer for code point. + var pointer = indexShiftJISPointerFor(code_point); + + // 8. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 9. Let lead be floor(pointer / 188). + var lead = floor(pointer / 188); + + // 10. Let lead offset be 0x81, if lead is less than 0x1F, and + // 0xC1 otherwise. + var lead_offset = (lead < 0x1F) ? 0x81 : 0xC1; + + // 11. Let trail be pointer % 188. + var trail = pointer % 188; + + // 12. Let offset be 0x40, if trail is less than 0x3F, and 0x41 + // otherwise. + var offset = (trail < 0x3F) ? 0x40 : 0x41; + + // 13. Return two bytes whose values are lead + lead offset and + // trail + offset. + return [lead + lead_offset, trail + offset]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['Shift_JIS'] = function(options) { + return new ShiftJISEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['Shift_JIS'] = function(options) { + return new ShiftJISDecoder(options); + }; + + // + // 14. Legacy multi-byte Korean encodings + // + + // 14.1 euc-kr + + // 14.1.1 euc-kr decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function EUCKRDecoder(options) { + var fatal = options.fatal; + + // euc-kr's decoder has an associated euc-kr lead (initially 0x00). + var /** @type {number} */ euckr_lead = 0x00; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and euc-kr lead is not 0x00, set + // euc-kr lead to 0x00 and return error. + if (bite === end_of_stream && euckr_lead !== 0) { + euckr_lead = 0x00; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and euc-kr lead is 0x00, return + // finished. + if (bite === end_of_stream && euckr_lead === 0) + return finished; + + // 3. If euc-kr lead is not 0x00, let lead be euc-kr lead, let + // pointer be null, set euc-kr lead to 0x00, and then run these + // substeps: + if (euckr_lead !== 0x00) { + var lead = euckr_lead; + var pointer = null; + euckr_lead = 0x00; + + // 1. If byte is in the range 0x41 to 0xFE, inclusive, set + // pointer to (lead − 0x81) × 190 + (byte − 0x41). + if (inRange(bite, 0x41, 0xFE)) + pointer = (lead - 0x81) * 190 + (bite - 0x41); + + // 2. Let code point be null, if pointer is null, and the + // index code point for pointer in index euc-kr otherwise. + var code_point = (pointer === null) + ? null : indexCodePointFor(pointer, index('euc-kr')); + + // 3. If code point is null and byte is an ASCII byte, prepend + // byte to stream. + if (pointer === null && isASCIIByte(bite)) + stream.prepend(bite); + + // 4. If code point is null, return error. + if (code_point === null) + return decoderError(fatal); + + // 5. Return a code point whose value is code point. + return code_point; + } + + // 4. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 5. If byte is in the range 0x81 to 0xFE, inclusive, set + // euc-kr lead to byte and return continue. + if (inRange(bite, 0x81, 0xFE)) { + euckr_lead = bite; + return null; + } + + // 6. Return error. + return decoderError(fatal); + }; + } + + // 14.1.2 euc-kr encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function EUCKREncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. Let pointer be the index pointer for code point in index + // euc-kr. + var pointer = indexPointerFor(code_point, index('euc-kr')); + + // 4. If pointer is null, return error with code point. + if (pointer === null) + return encoderError(code_point); + + // 5. Let lead be floor(pointer / 190) + 0x81. + var lead = floor(pointer / 190) + 0x81; + + // 6. Let trail be pointer % 190 + 0x41. + var trail = (pointer % 190) + 0x41; + + // 7. Return two bytes whose values are lead and trail. + return [lead, trail]; + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['EUC-KR'] = function(options) { + return new EUCKREncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['EUC-KR'] = function(options) { + return new EUCKRDecoder(options); + }; + + + // + // 15. Legacy miscellaneous encodings + // + + // 15.1 replacement + + // Not needed - API throws RangeError + + // 15.2 Common infrastructure for utf-16be and utf-16le + + /** + * @param {number} code_unit + * @param {boolean} utf16be + * @return {!Array.} bytes + */ + function convertCodeUnitToBytes(code_unit, utf16be) { + // 1. Let byte1 be code unit >> 8. + var byte1 = code_unit >> 8; + + // 2. Let byte2 be code unit & 0x00FF. + var byte2 = code_unit & 0x00FF; + + // 3. Then return the bytes in order: + // utf-16be flag is set: byte1, then byte2. + if (utf16be) + return [byte1, byte2]; + // utf-16be flag is unset: byte2, then byte1. + return [byte2, byte1]; + } + + // 15.2.1 shared utf-16 decoder + /** + * @constructor + * @implements {Decoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */ + function UTF16Decoder(utf16_be, options) { + var fatal = options.fatal; + var /** @type {?number} */ utf16_lead_byte = null, + /** @type {?number} */ utf16_lead_surrogate = null; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and either utf-16 lead byte or + // utf-16 lead surrogate is not null, set utf-16 lead byte and + // utf-16 lead surrogate to null, and return error. + if (bite === end_of_stream && (utf16_lead_byte !== null || + utf16_lead_surrogate !== null)) { + return decoderError(fatal); + } + + // 2. If byte is end-of-stream and utf-16 lead byte and utf-16 + // lead surrogate are null, return finished. + if (bite === end_of_stream && utf16_lead_byte === null && + utf16_lead_surrogate === null) { + return finished; + } + + // 3. If utf-16 lead byte is null, set utf-16 lead byte to byte + // and return continue. + if (utf16_lead_byte === null) { + utf16_lead_byte = bite; + return null; + } + + // 4. Let code unit be the result of: + var code_unit; + if (utf16_be) { + // utf-16be decoder flag is set + // (utf-16 lead byte << 8) + byte. + code_unit = (utf16_lead_byte << 8) + bite; + } else { + // utf-16be decoder flag is unset + // (byte << 8) + utf-16 lead byte. + code_unit = (bite << 8) + utf16_lead_byte; + } + // Then set utf-16 lead byte to null. + utf16_lead_byte = null; + + // 5. If utf-16 lead surrogate is not null, let lead surrogate + // be utf-16 lead surrogate, set utf-16 lead surrogate to null, + // and then run these substeps: + if (utf16_lead_surrogate !== null) { + var lead_surrogate = utf16_lead_surrogate; + utf16_lead_surrogate = null; + + // 1. If code unit is in the range U+DC00 to U+DFFF, + // inclusive, return a code point whose value is 0x10000 + + // ((lead surrogate − 0xD800) << 10) + (code unit − 0xDC00). + if (inRange(code_unit, 0xDC00, 0xDFFF)) { + return 0x10000 + (lead_surrogate - 0xD800) * 0x400 + + (code_unit - 0xDC00); + } + + // 2. Prepend the sequence resulting of converting code unit + // to bytes using utf-16be decoder flag to stream and return + // error. + stream.prepend(convertCodeUnitToBytes(code_unit, utf16_be)); + return decoderError(fatal); + } + + // 6. If code unit is in the range U+D800 to U+DBFF, inclusive, + // set utf-16 lead surrogate to code unit and return continue. + if (inRange(code_unit, 0xD800, 0xDBFF)) { + utf16_lead_surrogate = code_unit; + return null; + } + + // 7. If code unit is in the range U+DC00 to U+DFFF, inclusive, + // return error. + if (inRange(code_unit, 0xDC00, 0xDFFF)) + return decoderError(fatal); + + // 8. Return code point code unit. + return code_unit; + }; + } + + // 15.2.2 shared utf-16 encoder + /** + * @constructor + * @implements {Encoder} + * @param {boolean} utf16_be True if big-endian, false if little-endian. + * @param {{fatal: boolean}} options + */ + function UTF16Encoder(utf16_be, options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is in the range U+0000 to U+FFFF, inclusive, + // return the sequence resulting of converting code point to + // bytes using utf-16be encoder flag. + if (inRange(code_point, 0x0000, 0xFFFF)) + return convertCodeUnitToBytes(code_point, utf16_be); + + // 3. Let lead be ((code point − 0x10000) >> 10) + 0xD800, + // converted to bytes using utf-16be encoder flag. + var lead = convertCodeUnitToBytes( + ((code_point - 0x10000) >> 10) + 0xD800, utf16_be); + + // 4. Let trail be ((code point − 0x10000) & 0x3FF) + 0xDC00, + // converted to bytes using utf-16be encoder flag. + var trail = convertCodeUnitToBytes( + ((code_point - 0x10000) & 0x3FF) + 0xDC00, utf16_be); + + // 5. Return a byte sequence of lead followed by trail. + return lead.concat(trail); + }; + } + + // 15.3 utf-16be + // 15.3.1 utf-16be decoder + /** @param {{fatal: boolean}} options */ + encoders['UTF-16BE'] = function(options) { + return new UTF16Encoder(true, options); + }; + // 15.3.2 utf-16be encoder + /** @param {{fatal: boolean}} options */ + decoders['UTF-16BE'] = function(options) { + return new UTF16Decoder(true, options); + }; + + // 15.4 utf-16le + // 15.4.1 utf-16le decoder + /** @param {{fatal: boolean}} options */ + encoders['UTF-16LE'] = function(options) { + return new UTF16Encoder(false, options); + }; + // 15.4.2 utf-16le encoder + /** @param {{fatal: boolean}} options */ + decoders['UTF-16LE'] = function(options) { + return new UTF16Decoder(false, options); + }; + + // 15.5 x-user-defined + + // 15.5.1 x-user-defined decoder + /** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ + function XUserDefinedDecoder(options) { + options.fatal; + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 2. If byte is an ASCII byte, return a code point whose value + // is byte. + if (isASCIIByte(bite)) + return bite; + + // 3. Return a code point whose value is 0xF780 + byte − 0x80. + return 0xF780 + bite - 0x80; + }; + } + + // 15.5.2 x-user-defined encoder + /** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ + function XUserDefinedEncoder(options) { + options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1.If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is an ASCII code point, return a byte whose + // value is code point. + if (isASCIICodePoint(code_point)) + return code_point; + + // 3. If code point is in the range U+F780 to U+F7FF, inclusive, + // return a byte whose value is code point − 0xF780 + 0x80. + if (inRange(code_point, 0xF780, 0xF7FF)) + return code_point - 0xF780 + 0x80; + + // 4. Return error with code point. + return encoderError(code_point); + }; + } + + /** @param {{fatal: boolean}} options */ + encoders['x-user-defined'] = function(options) { + return new XUserDefinedEncoder(options); + }; + /** @param {{fatal: boolean}} options */ + decoders['x-user-defined'] = function(options) { + return new XUserDefinedDecoder(options); + }; + + if (!global['TextEncoder']) + global['TextEncoder'] = TextEncoder; + if (!global['TextDecoder']) + global['TextDecoder'] = TextDecoder; + + if (typeof module !== "undefined" && module.exports) { + module.exports = { + TextEncoder: global['TextEncoder'], + TextDecoder: global['TextDecoder'], + EncodingIndexes: global["encoding-indexes"] + }; + } + + // For strict environments where `this` inside the global scope + // is `undefined`, take a pure object instead + }(this || {})); + },{"./encoding-indexes.js":109}],111:[function(require,module,exports){ + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; + } + + },{}],112:[function(require,module,exports){ + module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; + }; + },{}],113:[function(require,module,exports){ + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var formatRegExp = /%[sdj%]/g; + exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; + }; + + + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. + exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; + }; + + + var debugs = {}; + var debugEnviron; + exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; + }; + + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ + /* legacy: obj, showHidden, depth, colors*/ + function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); + } + exports.inspect = inspect; + + + // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] + }; + + // Don't use 'blue' not visible on cmd.exe + inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' + }; + + + function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } + } + + + function stylizeNoColor(str, styleType) { + return str; + } + + + function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; + } + + + function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); + } + + + function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; + } + + + function reduceToSingleString(output, base, braces) { + var length = output.reduce(function(prev, cur) { + if (cur.indexOf('\n') >= 0) ; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { + return Array.isArray(ar); + } + exports.isArray = isArray; + + function isBoolean(arg) { + return typeof arg === 'boolean'; + } + exports.isBoolean = isBoolean; + + function isNull(arg) { + return arg === null; + } + exports.isNull = isNull; + + function isNullOrUndefined(arg) { + return arg == null; + } + exports.isNullOrUndefined = isNullOrUndefined; + + function isNumber(arg) { + return typeof arg === 'number'; + } + exports.isNumber = isNumber; + + function isString(arg) { + return typeof arg === 'string'; + } + exports.isString = isString; + + function isSymbol(arg) { + return typeof arg === 'symbol'; + } + exports.isSymbol = isSymbol; + + function isUndefined(arg) { + return arg === void 0; + } + exports.isUndefined = isUndefined; + + function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; + } + exports.isRegExp = isRegExp; + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + exports.isObject = isObject; + + function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; + } + exports.isDate = isDate; + + function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); + } + exports.isError = isError; + + function isFunction(arg) { + return typeof arg === 'function'; + } + exports.isFunction = isFunction; + + function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; + } + exports.isPrimitive = isPrimitive; + + exports.isBuffer = require('./support/isBuffer'); + + function objectToString(o) { + return Object.prototype.toString.call(o); + } + + + function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); + } + + + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + + // 26 Feb 16:19:34 + function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); + } + + + // log is just a thin wrapper to console.log that prepends a timestamp + exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); + }; + + + /** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ + exports.inherits = require('inherits'); + + exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; + }; + + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + },{"./support/isBuffer":112,"inherits":111}],114:[function(require,module,exports){ + /*! + + diff v5.1.0 + + Software License Agreement (BSD License) + + Copyright (c) 2009-2015, Kevin Decker + + All rights reserved. + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of Kevin Decker nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + @license + */ + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.Diff = {})); + }(this, (function (exports) { + function Diff() {} + Diff.prototype = { + diff: function diff(oldString, newString) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var callback = options.callback; + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + this.options = options; + var self = this; + + function done(value) { + if (callback) { + setTimeout(function () { + callback(undefined, value); + }, 0); + return true; + } else { + return value; + } + } // Allow subclasses to massage the input prior to running + + + oldString = this.castInput(oldString); + newString = this.castInput(newString); + oldString = this.removeEmpty(this.tokenize(oldString)); + newString = this.removeEmpty(this.tokenize(newString)); + var newLen = newString.length, + oldLen = oldString.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + + if (options.maxEditLength) { + maxEditLength = Math.min(maxEditLength, options.maxEditLength); + } + + var bestPath = [{ + newPos: -1, + components: [] + }]; // Seed editLength = 0, i.e. the content starts with the same values + + var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + // Identity per the equality and tokenizer + return done([{ + value: this.join(newString), + count: newString.length + }]); + } // Main worker method. checks all permutations of a given edit length for acceptance. + + + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath = void 0; + + var addPath = bestPath[diagonalPath - 1], + removePath = bestPath[diagonalPath + 1], + _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + + if (addPath) { + // No one else is going to attempt to use this value, clear it + bestPath[diagonalPath - 1] = undefined; + } + + var canAdd = addPath && addPath.newPos + 1 < newLen, + canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen; + + if (!canAdd && !canRemove) { + // If this path is a terminal then prune + bestPath[diagonalPath] = undefined; + continue; + } // Select the diagonal that we want to branch from. We select the prior + // path whose position in the new string is the farthest from the origin + // and does not pass the bounds of the diff graph + + + if (!canAdd || canRemove && addPath.newPos < removePath.newPos) { + basePath = clonePath(removePath); + self.pushComponent(basePath.components, undefined, true); + } else { + basePath = addPath; // No need to clone, we've pulled it from the list + + basePath.newPos++; + self.pushComponent(basePath.components, true, undefined); + } + + _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done + + if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) { + return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken)); + } else { + // Otherwise track this path as a potential candidate and continue. + bestPath[diagonalPath] = basePath; + } + } + + editLength++; + } // Performs the length of edit iteration. Is a bit fugly as this has to support the + // sync and async mode which is never fun. Loops over execEditLength until a value + // is produced, or until the edit length exceeds options.maxEditLength (if given), + // in which case it will return undefined. + + + if (callback) { + (function exec() { + setTimeout(function () { + if (editLength > maxEditLength) { + return callback(); + } + + if (!execEditLength()) { + exec(); + } + }, 0); + })(); + } else { + while (editLength <= maxEditLength) { + var ret = execEditLength(); + + if (ret) { + return ret; + } + } + } + }, + pushComponent: function pushComponent(components, added, removed) { + var last = components[components.length - 1]; + + if (last && last.added === added && last.removed === removed) { + // We need to clone here as the component clone operation is just + // as shallow array clone + components[components.length - 1] = { + count: last.count + 1, + added: added, + removed: removed + }; + } else { + components.push({ + count: 1, + added: added, + removed: removed + }); + } + }, + extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) { + var newLen = newString.length, + oldLen = oldString.length, + newPos = basePath.newPos, + oldPos = newPos - diagonalPath, + commonCount = 0; + + while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + + if (commonCount) { + basePath.components.push({ + count: commonCount + }); + } + + basePath.newPos = newPos; + return oldPos; + }, + equals: function equals(left, right) { + if (this.options.comparator) { + return this.options.comparator(left, right); + } else { + return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase(); + } + }, + removeEmpty: function removeEmpty(array) { + var ret = []; + + for (var i = 0; i < array.length; i++) { + if (array[i]) { + ret.push(array[i]); + } + } + + return ret; + }, + castInput: function castInput(value) { + return value; + }, + tokenize: function tokenize(value) { + return value.split(''); + }, + join: function join(chars) { + return chars.join(''); + } + }; + + function buildValues(diff, components, newString, oldString, useLongestToken) { + var componentPos = 0, + componentLen = components.length, + newPos = 0, + oldPos = 0; + + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + + if (!component.removed) { + if (!component.added && useLongestToken) { + var value = newString.slice(newPos, newPos + component.count); + value = value.map(function (value, i) { + var oldValue = oldString[oldPos + i]; + return oldValue.length > value.length ? oldValue : value; + }); + component.value = diff.join(value); + } else { + component.value = diff.join(newString.slice(newPos, newPos + component.count)); + } + + newPos += component.count; // Common case + + if (!component.added) { + oldPos += component.count; + } + } else { + component.value = diff.join(oldString.slice(oldPos, oldPos + component.count)); + oldPos += component.count; // Reverse add and remove so removes are output first to match common convention + // The diffing algorithm is tied to add then remove output and this is the simplest + // route to get the desired output with minimal overhead. + + if (componentPos && components[componentPos - 1].added) { + var tmp = components[componentPos - 1]; + components[componentPos - 1] = components[componentPos]; + components[componentPos] = tmp; + } + } + } // Special case handle for when one terminal is ignored (i.e. whitespace). + // For this case we merge the terminal into the prior string and drop the change. + // This is only available for string mode. + + + var lastComponent = components[componentLen - 1]; + + if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { + components[componentLen - 2].value += lastComponent.value; + components.pop(); + } + + return components; + } + + function clonePath(path) { + return { + newPos: path.newPos, + components: path.components.slice(0) + }; + } + + var characterDiff = new Diff(); + function diffChars(oldStr, newStr, options) { + return characterDiff.diff(oldStr, newStr, options); + } + + function generateOptions(options, defaults) { + if (typeof options === 'function') { + defaults.callback = options; + } else if (options) { + for (var name in options) { + /* istanbul ignore else */ + if (options.hasOwnProperty(name)) { + defaults[name] = options[name]; + } + } + } + + return defaults; + } + + // + // Ranges and exceptions: + // Latin-1 Supplement, 0080–00FF + // - U+00D7 × Multiplication sign + // - U+00F7 ÷ Division sign + // Latin Extended-A, 0100–017F + // Latin Extended-B, 0180–024F + // IPA Extensions, 0250–02AF + // Spacing Modifier Letters, 02B0–02FF + // - U+02C7 ˇ ˇ Caron + // - U+02D8 ˘ ˘ Breve + // - U+02D9 ˙ ˙ Dot Above + // - U+02DA ˚ ˚ Ring Above + // - U+02DB ˛ ˛ Ogonek + // - U+02DC ˜ ˜ Small Tilde + // - U+02DD ˝ ˝ Double Acute Accent + // Latin Extended Additional, 1E00–1EFF + + var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/; + var reWhitespace = /\S/; + var wordDiff = new Diff(); + + wordDiff.equals = function (left, right) { + if (this.options.ignoreCase) { + left = left.toLowerCase(); + right = right.toLowerCase(); + } + + return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right); + }; + + wordDiff.tokenize = function (value) { + // All whitespace symbols except newline group into one token, each newline - in separate token + var tokens = value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + + for (var i = 0; i < tokens.length - 1; i++) { + // If we have an empty string in the next field and we have only word chars before and after, merge + if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) { + tokens[i] += tokens[i + 2]; + tokens.splice(i + 1, 2); + i--; + } + } + + return tokens; + }; + + function diffWords(oldStr, newStr, options) { + options = generateOptions(options, { + ignoreWhitespace: true + }); + return wordDiff.diff(oldStr, newStr, options); + } + function diffWordsWithSpace(oldStr, newStr, options) { + return wordDiff.diff(oldStr, newStr, options); + } + + var lineDiff = new Diff(); + + lineDiff.tokenize = function (value) { + var retLines = [], + linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line + + if (!linesAndNewlines[linesAndNewlines.length - 1]) { + linesAndNewlines.pop(); + } // Merge the content and line separators into single tokens + + + for (var i = 0; i < linesAndNewlines.length; i++) { + var line = linesAndNewlines[i]; + + if (i % 2 && !this.options.newlineIsToken) { + retLines[retLines.length - 1] += line; + } else { + if (this.options.ignoreWhitespace) { + line = line.trim(); + } + + retLines.push(line); + } + } + + return retLines; + }; + + function diffLines(oldStr, newStr, callback) { + return lineDiff.diff(oldStr, newStr, callback); + } + function diffTrimmedLines(oldStr, newStr, callback) { + var options = generateOptions(callback, { + ignoreWhitespace: true + }); + return lineDiff.diff(oldStr, newStr, options); + } + + var sentenceDiff = new Diff(); + + sentenceDiff.tokenize = function (value) { + return value.split(/(\S.+?[.!?])(?=\s+|$)/); + }; + + function diffSentences(oldStr, newStr, callback) { + return sentenceDiff.diff(oldStr, newStr, callback); + } + + var cssDiff = new Diff(); + + cssDiff.tokenize = function (value) { + return value.split(/([{}:;,]|\s+)/); + }; + + function diffCss(oldStr, newStr, callback) { + return cssDiff.diff(oldStr, newStr, callback); + } + + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var objectPrototypeToString = Object.prototype.toString; + var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a + // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: + + jsonDiff.useLongestToken = true; + jsonDiff.tokenize = lineDiff.tokenize; + + jsonDiff.castInput = function (value) { + var _this$options = this.options, + undefinedReplacement = _this$options.undefinedReplacement, + _this$options$stringi = _this$options.stringifyReplacer, + stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) { + return typeof v === 'undefined' ? undefinedReplacement : v; + } : _this$options$stringi; + return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); + }; + + jsonDiff.equals = function (left, right) { + return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); + }; + + function diffJson(oldObj, newObj, options) { + return jsonDiff.diff(oldObj, newObj, options); + } // This function handles the presence of circular references by bailing out when encountering an + // object that is already on the "stack" of items being processed. Accepts an optional replacer + + function canonicalize(obj, stack, replacementStack, replacer, key) { + stack = stack || []; + replacementStack = replacementStack || []; + + if (replacer) { + obj = replacer(key, obj); + } + + var i; + + for (i = 0; i < stack.length; i += 1) { + if (stack[i] === obj) { + return replacementStack[i]; + } + } + + var canonicalizedObj; + + if ('[object Array]' === objectPrototypeToString.call(obj)) { + stack.push(obj); + canonicalizedObj = new Array(obj.length); + replacementStack.push(canonicalizedObj); + + for (i = 0; i < obj.length; i += 1) { + canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key); + } + + stack.pop(); + replacementStack.pop(); + return canonicalizedObj; + } + + if (obj && obj.toJSON) { + obj = obj.toJSON(); + } + + if (_typeof(obj) === 'object' && obj !== null) { + stack.push(obj); + canonicalizedObj = {}; + replacementStack.push(canonicalizedObj); + + var sortedKeys = [], + _key; + + for (_key in obj) { + /* istanbul ignore else */ + if (obj.hasOwnProperty(_key)) { + sortedKeys.push(_key); + } + } + + sortedKeys.sort(); + + for (i = 0; i < sortedKeys.length; i += 1) { + _key = sortedKeys[i]; + canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key); + } + + stack.pop(); + replacementStack.pop(); + } else { + canonicalizedObj = obj; + } + + return canonicalizedObj; + } + + var arrayDiff = new Diff(); + + arrayDiff.tokenize = function (value) { + return value.slice(); + }; + + arrayDiff.join = arrayDiff.removeEmpty = function (value) { + return value; + }; + + function diffArrays(oldArr, newArr, callback) { + return arrayDiff.diff(oldArr, newArr, callback); + } + + function parsePatch(uniDiff) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [], + list = [], + i = 0; + + function parseIndex() { + var index = {}; + list.push(index); // Parse diff metadata + + while (i < diffstr.length) { + var line = diffstr[i]; // File header found, end parsing diff metadata + + if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) { + break; + } // Diff index + + + var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line); + + if (header) { + index.index = header[1]; + } + + i++; + } // Parse file headers if they are defined. Unified diff requires them, but + // there's no technical issues to have an isolated hunk without file header + + + parseFileHeader(index); + parseFileHeader(index); // Parse hunks + + index.hunks = []; + + while (i < diffstr.length) { + var _line = diffstr[i]; + + if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) { + break; + } else if (/^@@/.test(_line)) { + index.hunks.push(parseHunk()); + } else if (_line && options.strict) { + // Ignore unexpected content unless in strict mode + throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line)); + } else { + i++; + } + } + } // Parses the --- and +++ headers, if none are found, no lines + // are consumed. + + + function parseFileHeader(index) { + var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]); + + if (fileHeader) { + var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; + var data = fileHeader[2].split('\t', 2); + var fileName = data[0].replace(/\\\\/g, '\\'); + + if (/^".*"$/.test(fileName)) { + fileName = fileName.substr(1, fileName.length - 2); + } + + index[keyPrefix + 'FileName'] = fileName; + index[keyPrefix + 'Header'] = (data[1] || '').trim(); + i++; + } + } // Parses a hunk + // This assumes that we are at the start of a hunk. + + + function parseHunk() { + var chunkHeaderIndex = i, + chunkHeaderLine = diffstr[i++], + chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/); + var hunk = { + oldStart: +chunkHeader[1], + oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2], + newStart: +chunkHeader[3], + newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4], + lines: [], + linedelimiters: [] + }; // Unified Diff Format quirk: If the chunk size is 0, + // the first number is one lower than one would expect. + // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + + if (hunk.oldLines === 0) { + hunk.oldStart += 1; + } + + if (hunk.newLines === 0) { + hunk.newStart += 1; + } + + var addCount = 0, + removeCount = 0; + + for (; i < diffstr.length; i++) { + // Lines starting with '---' could be mistaken for the "remove line" operation + // But they could be the header for the next file. Therefore prune such cases out. + if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) { + break; + } + + var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0]; + + if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { + hunk.lines.push(diffstr[i]); + hunk.linedelimiters.push(delimiters[i] || '\n'); + + if (operation === '+') { + addCount++; + } else if (operation === '-') { + removeCount++; + } else if (operation === ' ') { + addCount++; + removeCount++; + } + } else { + break; + } + } // Handle the empty block count case + + + if (!addCount && hunk.newLines === 1) { + hunk.newLines = 0; + } + + if (!removeCount && hunk.oldLines === 1) { + hunk.oldLines = 0; + } // Perform optional sanity checking + + + if (options.strict) { + if (addCount !== hunk.newLines) { + throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + + if (removeCount !== hunk.oldLines) { + throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + } + } + + return hunk; + } + + while (i < diffstr.length) { + parseIndex(); + } + + return list; + } + + // Iterator that traverses in the range of [min, max], stepping + // by distance from a given start position. I.e. for [0, 4], with + // start of 2, this will iterate 2, 3, 1, 4, 0. + function distanceIterator (start, minLine, maxLine) { + var wantForward = true, + backwardExhausted = false, + forwardExhausted = false, + localOffset = 1; + return function iterator() { + if (wantForward && !forwardExhausted) { + if (backwardExhausted) { + localOffset++; + } else { + wantForward = false; + } // Check if trying to fit beyond text length, and if not, check it fits + // after offset location (or desired location on first iteration) + + + if (start + localOffset <= maxLine) { + return localOffset; + } + + forwardExhausted = true; + } + + if (!backwardExhausted) { + if (!forwardExhausted) { + wantForward = true; + } // Check if trying to fit before text beginning, and if not, check it fits + // before offset location + + + if (minLine <= start - localOffset) { + return -localOffset++; + } + + backwardExhausted = true; + return iterator(); + } // We tried to fit hunk before text beginning and beyond text length, then + // hunk can't fit on the text. Return undefined + + }; + } + + function applyPatch(source, uniDiff) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (typeof uniDiff === 'string') { + uniDiff = parsePatch(uniDiff); + } + + if (Array.isArray(uniDiff)) { + if (uniDiff.length > 1) { + throw new Error('applyPatch only works with a single input.'); + } + + uniDiff = uniDiff[0]; + } // Apply the diff to the input + + + var lines = source.split(/\r\n|[\n\v\f\r\x85]/), + delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [], + hunks = uniDiff.hunks, + compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) { + return line === patchContent; + }, + errorCount = 0, + fuzzFactor = options.fuzzFactor || 0, + minLine = 0, + offset = 0, + removeEOFNL, + addEOFNL; + /** + * Checks if the hunk exactly fits on the provided location + */ + + + function hunkFits(hunk, toPos) { + for (var j = 0; j < hunk.lines.length; j++) { + var line = hunk.lines[j], + operation = line.length > 0 ? line[0] : ' ', + content = line.length > 0 ? line.substr(1) : line; + + if (operation === ' ' || operation === '-') { + // Context sanity check + if (!compareLine(toPos + 1, lines[toPos], operation, content)) { + errorCount++; + + if (errorCount > fuzzFactor) { + return false; + } + } + + toPos++; + } + } + + return true; + } // Search best fit offsets for each hunk based on the previous ones + + + for (var i = 0; i < hunks.length; i++) { + var hunk = hunks[i], + maxLine = lines.length - hunk.oldLines, + localOffset = 0, + toPos = offset + hunk.oldStart - 1; + var iterator = distanceIterator(toPos, minLine, maxLine); + + for (; localOffset !== undefined; localOffset = iterator()) { + if (hunkFits(hunk, toPos + localOffset)) { + hunk.offset = offset += localOffset; + break; + } + } + + if (localOffset === undefined) { + return false; + } // Set lower text limit to end of the current hunk, so next ones don't try + // to fit over already patched text + + + minLine = hunk.offset + hunk.oldStart + hunk.oldLines; + } // Apply patch hunks + + + var diffOffset = 0; + + for (var _i = 0; _i < hunks.length; _i++) { + var _hunk = hunks[_i], + _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1; + + diffOffset += _hunk.newLines - _hunk.oldLines; + + for (var j = 0; j < _hunk.lines.length; j++) { + var line = _hunk.lines[j], + operation = line.length > 0 ? line[0] : ' ', + content = line.length > 0 ? line.substr(1) : line, + delimiter = _hunk.linedelimiters[j]; + + if (operation === ' ') { + _toPos++; + } else if (operation === '-') { + lines.splice(_toPos, 1); + delimiters.splice(_toPos, 1); + /* istanbul ignore else */ + } else if (operation === '+') { + lines.splice(_toPos, 0, content); + delimiters.splice(_toPos, 0, delimiter); + _toPos++; + } else if (operation === '\\') { + var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; + + if (previousOperation === '+') { + removeEOFNL = true; + } else if (previousOperation === '-') { + addEOFNL = true; + } + } + } + } // Handle EOFNL insertion/removal + + + if (removeEOFNL) { + while (!lines[lines.length - 1]) { + lines.pop(); + delimiters.pop(); + } + } else if (addEOFNL) { + lines.push(''); + delimiters.push('\n'); + } + + for (var _k = 0; _k < lines.length - 1; _k++) { + lines[_k] = lines[_k] + delimiters[_k]; + } + + return lines.join(''); + } // Wrapper that supports multiple file patches via callbacks. + + function applyPatches(uniDiff, options) { + if (typeof uniDiff === 'string') { + uniDiff = parsePatch(uniDiff); + } + + var currentIndex = 0; + + function processIndex() { + var index = uniDiff[currentIndex++]; + + if (!index) { + return options.complete(); + } + + options.loadFile(index, function (err, data) { + if (err) { + return options.complete(err); + } + + var updatedContent = applyPatch(data, index, options); + options.patched(index, updatedContent, function (err) { + if (err) { + return options.complete(err); + } + + processIndex(); + }); + }); + } + + processIndex(); + } + + function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + if (!options) { + options = {}; + } + + if (typeof options.context === 'undefined') { + options.context = 4; + } + + var diff = diffLines(oldStr, newStr, options); + + if (!diff) { + return; + } + + diff.push({ + value: '', + lines: [] + }); // Append an empty value to make cleanup easier + + function contextLines(lines) { + return lines.map(function (entry) { + return ' ' + entry; + }); + } + + var hunks = []; + var oldRangeStart = 0, + newRangeStart = 0, + curRange = [], + oldLine = 1, + newLine = 1; + + var _loop = function _loop(i) { + var current = diff[i], + lines = current.lines || current.value.replace(/\n$/, '').split('\n'); + current.lines = lines; + + if (current.added || current.removed) { + var _curRange; + + // If we have previous context, start with that + if (!oldRangeStart) { + var prev = diff[i - 1]; + oldRangeStart = oldLine; + newRangeStart = newLine; + + if (prev) { + curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; + oldRangeStart -= curRange.length; + newRangeStart -= curRange.length; + } + } // Output our changes + + + (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) { + return (current.added ? '+' : '-') + entry; + }))); // Track the updated file position + + + if (current.added) { + newLine += lines.length; + } else { + oldLine += lines.length; + } + } else { + // Identical context lines. Track line changes + if (oldRangeStart) { + // Close out any changes that have been output (or join overlapping) + if (lines.length <= options.context * 2 && i < diff.length - 2) { + var _curRange2; + + // Overlapping + (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines))); + } else { + var _curRange3; + + // end the range and output + var contextSize = Math.min(lines.length, options.context); + + (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize)))); + + var hunk = { + oldStart: oldRangeStart, + oldLines: oldLine - oldRangeStart + contextSize, + newStart: newRangeStart, + newLines: newLine - newRangeStart + contextSize, + lines: curRange + }; + + if (i >= diff.length - 2 && lines.length <= options.context) { + // EOF is inside this hunk + var oldEOFNewline = /\n$/.test(oldStr); + var newEOFNewline = /\n$/.test(newStr); + var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines; + + if (!oldEOFNewline && noNlBeforeAdds && oldStr.length > 0) { + // special case: old has no eol and no trailing context; no-nl can end up before adds + // however, if the old file is empty, do not output the no-nl line + curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file'); + } + + if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) { + curRange.push('\\ No newline at end of file'); + } + } + + hunks.push(hunk); + oldRangeStart = 0; + newRangeStart = 0; + curRange = []; + } + } + + oldLine += lines.length; + newLine += lines.length; + } + }; + + for (var i = 0; i < diff.length; i++) { + _loop(i); + } + + return { + oldFileName: oldFileName, + newFileName: newFileName, + oldHeader: oldHeader, + newHeader: newHeader, + hunks: hunks + }; + } + function formatPatch(diff) { + var ret = []; + + if (diff.oldFileName == diff.newFileName) { + ret.push('Index: ' + diff.oldFileName); + } + + ret.push('==================================================================='); + ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); + ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); + + for (var i = 0; i < diff.hunks.length; i++) { + var hunk = diff.hunks[i]; // Unified Diff Format quirk: If the chunk size is 0, + // the first number is one lower than one would expect. + // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + + if (hunk.oldLines === 0) { + hunk.oldStart -= 1; + } + + if (hunk.newLines === 0) { + hunk.newStart -= 1; + } + + ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@'); + ret.push.apply(ret, hunk.lines); + } + + return ret.join('\n') + '\n'; + } + function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { + return formatPatch(structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)); + } + function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { + return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); + } + + function arrayEqual(a, b) { + if (a.length !== b.length) { + return false; + } + + return arrayStartsWith(a, b); + } + function arrayStartsWith(array, start) { + if (start.length > array.length) { + return false; + } + + for (var i = 0; i < start.length; i++) { + if (start[i] !== array[i]) { + return false; + } + } + + return true; + } + + function calcLineCount(hunk) { + var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines), + oldLines = _calcOldNewLineCount.oldLines, + newLines = _calcOldNewLineCount.newLines; + + if (oldLines !== undefined) { + hunk.oldLines = oldLines; + } else { + delete hunk.oldLines; + } + + if (newLines !== undefined) { + hunk.newLines = newLines; + } else { + delete hunk.newLines; + } + } + function merge(mine, theirs, base) { + mine = loadPatch(mine, base); + theirs = loadPatch(theirs, base); + var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning. + // Leaving sanity checks on this to the API consumer that may know more about the + // meaning in their own context. + + if (mine.index || theirs.index) { + ret.index = mine.index || theirs.index; + } + + if (mine.newFileName || theirs.newFileName) { + if (!fileNameChanged(mine)) { + // No header or no change in ours, use theirs (and ours if theirs does not exist) + ret.oldFileName = theirs.oldFileName || mine.oldFileName; + ret.newFileName = theirs.newFileName || mine.newFileName; + ret.oldHeader = theirs.oldHeader || mine.oldHeader; + ret.newHeader = theirs.newHeader || mine.newHeader; + } else if (!fileNameChanged(theirs)) { + // No header or no change in theirs, use ours + ret.oldFileName = mine.oldFileName; + ret.newFileName = mine.newFileName; + ret.oldHeader = mine.oldHeader; + ret.newHeader = mine.newHeader; + } else { + // Both changed... figure it out + ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName); + ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName); + ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader); + ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader); + } + } + + ret.hunks = []; + var mineIndex = 0, + theirsIndex = 0, + mineOffset = 0, + theirsOffset = 0; + + while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) { + var mineCurrent = mine.hunks[mineIndex] || { + oldStart: Infinity + }, + theirsCurrent = theirs.hunks[theirsIndex] || { + oldStart: Infinity + }; + + if (hunkBefore(mineCurrent, theirsCurrent)) { + // This patch does not overlap with any of the others, yay. + ret.hunks.push(cloneHunk(mineCurrent, mineOffset)); + mineIndex++; + theirsOffset += mineCurrent.newLines - mineCurrent.oldLines; + } else if (hunkBefore(theirsCurrent, mineCurrent)) { + // This patch does not overlap with any of the others, yay. + ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset)); + theirsIndex++; + mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines; + } else { + // Overlap, merge as best we can + var mergedHunk = { + oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart), + oldLines: 0, + newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset), + newLines: 0, + lines: [] + }; + mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines); + theirsIndex++; + mineIndex++; + ret.hunks.push(mergedHunk); + } + } + + return ret; + } + + function loadPatch(param, base) { + if (typeof param === 'string') { + if (/^@@/m.test(param) || /^Index:/m.test(param)) { + return parsePatch(param)[0]; + } + + if (!base) { + throw new Error('Must provide a base reference or pass in a patch'); + } + + return structuredPatch(undefined, undefined, base, param); + } + + return param; + } + + function fileNameChanged(patch) { + return patch.newFileName && patch.newFileName !== patch.oldFileName; + } + + function selectField(index, mine, theirs) { + if (mine === theirs) { + return mine; + } else { + index.conflict = true; + return { + mine: mine, + theirs: theirs + }; + } + } + + function hunkBefore(test, check) { + return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart; + } + + function cloneHunk(hunk, offset) { + return { + oldStart: hunk.oldStart, + oldLines: hunk.oldLines, + newStart: hunk.newStart + offset, + newLines: hunk.newLines, + lines: hunk.lines + }; + } + + function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) { + // This will generally result in a conflicted hunk, but there are cases where the context + // is the only overlap where we can successfully merge the content here. + var mine = { + offset: mineOffset, + lines: mineLines, + index: 0 + }, + their = { + offset: theirOffset, + lines: theirLines, + index: 0 + }; // Handle any leading content + + insertLeading(hunk, mine, their); + insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each. + + while (mine.index < mine.lines.length && their.index < their.lines.length) { + var mineCurrent = mine.lines[mine.index], + theirCurrent = their.lines[their.index]; + + if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) { + // Both modified ... + mutualChange(hunk, mine, their); + } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') { + var _hunk$lines; + + // Mine inserted + (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine))); + } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') { + var _hunk$lines2; + + // Theirs inserted + (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their))); + } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') { + // Mine removed or edited + removal(hunk, mine, their); + } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') { + // Their removed or edited + removal(hunk, their, mine, true); + } else if (mineCurrent === theirCurrent) { + // Context identity + hunk.lines.push(mineCurrent); + mine.index++; + their.index++; + } else { + // Context mismatch + conflict(hunk, collectChange(mine), collectChange(their)); + } + } // Now push anything that may be remaining + + + insertTrailing(hunk, mine); + insertTrailing(hunk, their); + calcLineCount(hunk); + } + + function mutualChange(hunk, mine, their) { + var myChanges = collectChange(mine), + theirChanges = collectChange(their); + + if (allRemoves(myChanges) && allRemoves(theirChanges)) { + // Special case for remove changes that are supersets of one another + if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) { + var _hunk$lines3; + + (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges)); + + return; + } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) { + var _hunk$lines4; + + (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges)); + + return; + } + } else if (arrayEqual(myChanges, theirChanges)) { + var _hunk$lines5; + + (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges)); + + return; + } + + conflict(hunk, myChanges, theirChanges); + } + + function removal(hunk, mine, their, swap) { + var myChanges = collectChange(mine), + theirChanges = collectContext(their, myChanges); + + if (theirChanges.merged) { + var _hunk$lines6; + + (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged)); + } else { + conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges); + } + } + + function conflict(hunk, mine, their) { + hunk.conflict = true; + hunk.lines.push({ + conflict: true, + mine: mine, + theirs: their + }); + } + + function insertLeading(hunk, insert, their) { + while (insert.offset < their.offset && insert.index < insert.lines.length) { + var line = insert.lines[insert.index++]; + hunk.lines.push(line); + insert.offset++; + } + } + + function insertTrailing(hunk, insert) { + while (insert.index < insert.lines.length) { + var line = insert.lines[insert.index++]; + hunk.lines.push(line); + } + } + + function collectChange(state) { + var ret = [], + operation = state.lines[state.index][0]; + + while (state.index < state.lines.length) { + var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change. + + if (operation === '-' && line[0] === '+') { + operation = '+'; + } + + if (operation === line[0]) { + ret.push(line); + state.index++; + } else { + break; + } + } + + return ret; + } + + function collectContext(state, matchChanges) { + var changes = [], + merged = [], + matchIndex = 0, + contextChanges = false, + conflicted = false; + + while (matchIndex < matchChanges.length && state.index < state.lines.length) { + var change = state.lines[state.index], + match = matchChanges[matchIndex]; // Once we've hit our add, then we are done + + if (match[0] === '+') { + break; + } + + contextChanges = contextChanges || change[0] !== ' '; + merged.push(match); + matchIndex++; // Consume any additions in the other block as a conflict to attempt + // to pull in the remaining context after this + + if (change[0] === '+') { + conflicted = true; + + while (change[0] === '+') { + changes.push(change); + change = state.lines[++state.index]; + } + } + + if (match.substr(1) === change.substr(1)) { + changes.push(change); + state.index++; + } else { + conflicted = true; + } + } + + if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) { + conflicted = true; + } + + if (conflicted) { + return changes; + } + + while (matchIndex < matchChanges.length) { + merged.push(matchChanges[matchIndex++]); + } + + return { + merged: merged, + changes: changes + }; + } + + function allRemoves(changes) { + return changes.reduce(function (prev, change) { + return prev && change[0] === '-'; + }, true); + } + + function skipRemoveSuperset(state, removeChanges, delta) { + for (var i = 0; i < delta; i++) { + var changeContent = removeChanges[removeChanges.length - delta + i].substr(1); + + if (state.lines[state.index + i] !== ' ' + changeContent) { + return false; + } + } + + state.index += delta; + return true; + } + + function calcOldNewLineCount(lines) { + var oldLines = 0; + var newLines = 0; + lines.forEach(function (line) { + if (typeof line !== 'string') { + var myCount = calcOldNewLineCount(line.mine); + var theirCount = calcOldNewLineCount(line.theirs); + + if (oldLines !== undefined) { + if (myCount.oldLines === theirCount.oldLines) { + oldLines += myCount.oldLines; + } else { + oldLines = undefined; + } + } + + if (newLines !== undefined) { + if (myCount.newLines === theirCount.newLines) { + newLines += myCount.newLines; + } else { + newLines = undefined; + } + } + } else { + if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) { + newLines++; + } + + if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) { + oldLines++; + } + } + }); + return { + oldLines: oldLines, + newLines: newLines + }; + } + + // See: http://code.google.com/p/google-diff-match-patch/wiki/API + function convertChangesToDMP(changes) { + var ret = [], + change, + operation; + + for (var i = 0; i < changes.length; i++) { + change = changes[i]; + + if (change.added) { + operation = 1; + } else if (change.removed) { + operation = -1; + } else { + operation = 0; + } + + ret.push([operation, change.value]); + } + + return ret; + } + + function convertChangesToXML(changes) { + var ret = []; + + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + + ret.push(escapeHTML(change.value)); + + if (change.added) { + ret.push(''); + } else if (change.removed) { + ret.push(''); + } + } + + return ret.join(''); + } + + function escapeHTML(s) { + var n = s; + n = n.replace(/&/g, '&'); + n = n.replace(//g, '>'); + n = n.replace(/"/g, '"'); + return n; + } + + exports.Diff = Diff; + exports.applyPatch = applyPatch; + exports.applyPatches = applyPatches; + exports.canonicalize = canonicalize; + exports.convertChangesToDMP = convertChangesToDMP; + exports.convertChangesToXML = convertChangesToXML; + exports.createPatch = createPatch; + exports.createTwoFilesPatch = createTwoFilesPatch; + exports.diffArrays = diffArrays; + exports.diffChars = diffChars; + exports.diffCss = diffCss; + exports.diffJson = diffJson; + exports.diffLines = diffLines; + exports.diffSentences = diffSentences; + exports.diffTrimmedLines = diffTrimmedLines; + exports.diffWords = diffWords; + exports.diffWordsWithSpace = diffWordsWithSpace; + exports.merge = merge; + exports.parsePatch = parsePatch; + exports.structuredPatch = structuredPatch; + + Object.defineProperty(exports, '__esModule', { value: true }); + + }))); + + },{}],115:[function(require,module,exports){ + module.exports = extend; + + /* + var obj = {a: 3, b: 5}; + extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 4, b: 5, c: 8} + + var obj = {a: 3, b: 5}; + extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} + obj; // {a: 3, b: 5} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} + + var arr = [1, 2, 3]; + var obj = {a: 3, b: 5}; + extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} + arr.push(4); + obj; // {a: 3, b: 5, c: [1, 2, 3]} + + extend({a: 4, b: 5}); // {a: 4, b: 5} + extend({a: 4, b: 5}, 3); {a: 4, b: 5} + extend({a: 4, b: 5}, true); {a: 4, b: 5} + extend('hello', {a: 4, b: 5}); // throws + extend(3, {a: 4, b: 5}); // throws + */ + + function extend(/* [deep], obj1, obj2, [objn] */) { + var args = [].slice.call(arguments); + var deep = false; + if (typeof args[0] == 'boolean') { + deep = args.shift(); + } + var result = args[0]; + if (isUnextendable(result)) { + throw new Error('extendee must be an object'); + } + var extenders = args.slice(1); + var len = extenders.length; + for (var i = 0; i < len; i++) { + var extender = extenders[i]; + for (var key in extender) { + if (Object.prototype.hasOwnProperty.call(extender, key)) { + var value = extender[key]; + if (deep && isCloneable(value)) { + var base = Array.isArray(value) ? [] : {}; + result[key] = extend( + true, + Object.prototype.hasOwnProperty.call(result, key) && !isUnextendable(result[key]) + ? result[key] + : base, + value + ); + } else { + result[key] = value; + } + } + } + } + return result; + } + + function isCloneable(obj) { + return Array.isArray(obj) || {}.toString.call(obj) == '[object Object]'; + } + + function isUnextendable(val) { + return !val || (typeof val != 'object' && typeof val != 'function'); + } + + },{}],116:[function(require,module,exports){ + /** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0; + + /** `Object#toString` result references. */ + var funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ + function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) {} + } + return result; + } + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = root['__core-js_shared__']; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Symbol = root.Symbol, + splice = arrayProto.splice; + + /* Built-in method references that are verified to be native. */ + var Map = getNative(root, 'Map'), + nativeCreate = getNative(Object, 'create'); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + return getMapData(this, key)['delete'](key); + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + getMapData(this, key).set(key, value); + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value) { + return isArray(value) ? value : stringToPath(value); + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoize(function(string) { + string = toString(string); + + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Assign cache to `_.memoize`. + memoize.Cache = MapCache; + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return !!value && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + module.exports = get; + + },{}],117:[function(require,module,exports){ + + // cache a reference to setTimeout, so that our reference won't be stubbed out + // when using fake timers and errors will still get logged + // https://github.com/cjohansen/Sinon.JS/issues/381 + var realSetTimeout = setTimeout; + + function configureLogger(config) { + // eslint-disable-next-line no-param-reassign + config = config || {}; + // Function which prints errors. + if (!config.hasOwnProperty("logger")) { + // eslint-disable-next-line no-empty-function + config.logger = function() {}; + } + // When set to true, any errors logged will be thrown immediately; + // If set to false, the errors will be thrown in separate execution frame. + if (!config.hasOwnProperty("useImmediateExceptions")) { + config.useImmediateExceptions = true; + } + // wrap realSetTimeout with something we can stub in tests + if (!config.hasOwnProperty("setTimeout")) { + config.setTimeout = realSetTimeout; + } + + return function logError(label, e) { + var msg = `${label} threw exception: `; + var err = { + name: e.name || label, + message: e.message || e.toString(), + stack: e.stack + }; + + function throwLoggedError() { + err.message = msg + err.message; + throw err; + } + + config.logger(`${msg}[${err.name}] ${err.message}`); + + if (err.stack) { + config.logger(err.stack); + } + + if (config.useImmediateExceptions) { + throwLoggedError(); + } else { + config.setTimeout(throwLoggedError, 0); + } + }; + } + + module.exports = configureLogger; + + },{}],118:[function(require,module,exports){ + + var Event = require("./event"); + + function CustomEvent(type, customData, target) { + this.initEvent(type, false, false, target); + this.detail = customData.detail || null; + } + + CustomEvent.prototype = new Event(); + + CustomEvent.prototype.constructor = CustomEvent; + + module.exports = CustomEvent; + + },{"./event":120}],119:[function(require,module,exports){ + + function flattenOptions(options) { + if (options !== Object(options)) { + return { + capture: Boolean(options), + once: false, + passive: false + }; + } + return { + capture: Boolean(options.capture), + once: Boolean(options.once), + passive: Boolean(options.passive) + }; + } + function not(fn) { + return function() { + return !fn.apply(this, arguments); + }; + } + function hasListenerFilter(listener, capture) { + return function(listenerSpec) { + return ( + listenerSpec.capture === capture && + listenerSpec.listener === listener + ); + }; + } + + var EventTarget = { + // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener + addEventListener: function addEventListener( + event, + listener, + providedOptions + ) { + // 3. Let capture, passive, and once be the result of flattening more options. + // Flatten property before executing step 2, + // feture detection is usually based on registering handler with options object, + // that has getter defined + // addEventListener("load", () => {}, { + // get once() { supportsOnce = true; } + // }); + var options = flattenOptions(providedOptions); + + // 2. If callback is null, then return. + if (listener === null || listener === undefined) { + return; + } + + this.eventListeners = this.eventListeners || {}; + this.eventListeners[event] = this.eventListeners[event] || []; + + // 4. If context object’s associated list of event listener + // does not contain an event listener whose type is type, + // callback is callback, and capture is capture, then append + // a new event listener to it, whose type is type, callback is + // callback, capture is capture, passive is passive, and once is once. + if ( + !this.eventListeners[event].some( + hasListenerFilter(listener, options.capture) + ) + ) { + this.eventListeners[event].push({ + listener: listener, + capture: options.capture, + once: options.once + }); + } + }, + + // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener + removeEventListener: function removeEventListener( + event, + listener, + providedOptions + ) { + if (!this.eventListeners || !this.eventListeners[event]) { + return; + } + + // 2. Let capture be the result of flattening options. + var options = flattenOptions(providedOptions); + + // 3. If there is an event listener in the associated list of + // event listeners whose type is type, callback is callback, + // and capture is capture, then set that event listener’s + // removed to true and remove it from the associated list of event listeners. + this.eventListeners[event] = this.eventListeners[event].filter( + not(hasListenerFilter(listener, options.capture)) + ); + }, + + dispatchEvent: function dispatchEvent(event) { + if (!this.eventListeners || !this.eventListeners[event.type]) { + return Boolean(event.defaultPrevented); + } + + var self = this; + var type = event.type; + var listeners = self.eventListeners[type]; + + // Remove listeners, that should be dispatched once + // before running dispatch loop to avoid nested dispatch issues + self.eventListeners[type] = listeners.filter(function(listenerSpec) { + return !listenerSpec.once; + }); + listeners.forEach(function(listenerSpec) { + var listener = listenerSpec.listener; + if (typeof listener === "function") { + listener.call(self, event); + } else { + listener.handleEvent(event); + } + }); + + return Boolean(event.defaultPrevented); + } + }; + + module.exports = EventTarget; + + },{}],120:[function(require,module,exports){ + + function Event(type, bubbles, cancelable, target) { + this.initEvent(type, bubbles, cancelable, target); + } + + Event.prototype = { + initEvent: function(type, bubbles, cancelable, target) { + this.type = type; + this.bubbles = bubbles; + this.cancelable = cancelable; + this.target = target; + this.currentTarget = target; + }, + + // eslint-disable-next-line no-empty-function + stopPropagation: function() {}, + + preventDefault: function() { + this.defaultPrevented = true; + } + }; + + module.exports = Event; + + },{}],121:[function(require,module,exports){ + + module.exports = { + Event: require("./event"), + ProgressEvent: require("./progress-event"), + CustomEvent: require("./custom-event"), + EventTarget: require("./event-target") + }; + + },{"./custom-event":118,"./event":120,"./event-target":119,"./progress-event":122}],122:[function(require,module,exports){ + + var Event = require("./event"); + + function ProgressEvent(type, progressEventRaw, target) { + this.initEvent(type, false, false, target); + this.loaded = + typeof progressEventRaw.loaded === "number" + ? progressEventRaw.loaded + : null; + this.total = + typeof progressEventRaw.total === "number" + ? progressEventRaw.total + : null; + this.lengthComputable = Boolean(progressEventRaw.total); + } + + ProgressEvent.prototype = new Event(); + + ProgressEvent.prototype.constructor = ProgressEvent; + + module.exports = ProgressEvent; + + },{"./event":120}],123:[function(require,module,exports){ + + var FakeTimers = require("@sinonjs/fake-timers"); + var fakeServer = require("./index"); + + // eslint-disable-next-line no-empty-function + function Server() {} + Server.prototype = fakeServer; + + var fakeServerWithClock = new Server(); + + fakeServerWithClock.addRequest = function addRequest(xhr) { + if (xhr.async) { + if (typeof setTimeout.clock === "object") { + this.clock = setTimeout.clock; + } else { + this.clock = FakeTimers.install(); + this.resetClock = true; + } + + if (!this.longestTimeout) { + var clockSetTimeout = this.clock.setTimeout; + var clockSetInterval = this.clock.setInterval; + var server = this; + + this.clock.setTimeout = function(fn, timeout) { + server.longestTimeout = Math.max( + timeout, + server.longestTimeout || 0 + ); + + return clockSetTimeout.apply(this, arguments); + }; + + this.clock.setInterval = function(fn, timeout) { + server.longestTimeout = Math.max( + timeout, + server.longestTimeout || 0 + ); + + return clockSetInterval.apply(this, arguments); + }; + } + } + + return fakeServer.addRequest.call(this, xhr); + }; + + fakeServerWithClock.respond = function respond() { + var returnVal = fakeServer.respond.apply(this, arguments); + + if (this.clock) { + this.clock.tick(this.longestTimeout || 0); + this.longestTimeout = 0; + + if (this.resetClock) { + this.clock.uninstall(); + this.resetClock = false; + } + } + + return returnVal; + }; + + fakeServerWithClock.restore = function restore() { + if (this.clock) { + this.clock.uninstall(); + } + + return fakeServer.restore.apply(this, arguments); + }; + + module.exports = fakeServerWithClock; + + },{"./index":124,"@sinonjs/fake-timers":61}],124:[function(require,module,exports){ + + var fakeXhr = require("../fake-xhr"); + var push = [].push; + var log = require("./log"); + var configureLogError = require("../configure-logger"); + var pathToRegexp = require("path-to-regexp"); + + var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + + function responseArray(handler) { + var response = handler; + + if (Object.prototype.toString.call(handler) !== "[object Array]") { + response = [200, {}, handler]; + } + + if (typeof response[2] !== "string") { + if (!supportsArrayBuffer) { + throw new TypeError( + `Fake server response body should be a string, but was ${typeof response[2]}` + ); + } else if (!(response[2] instanceof ArrayBuffer)) { + throw new TypeError( + `Fake server response body should be a string or ArrayBuffer, but was ${typeof response[2]}` + ); + } + } + + return response; + } + + function getDefaultWindowLocation() { + var winloc = { + hostname: "localhost", + port: process.env.PORT || 80, + protocol: "http:" + }; + winloc.host = + winloc.hostname + + (String(winloc.port) === "80" ? "" : `:${winloc.port}`); + return winloc; + } + + function getWindowLocation() { + if (typeof window === "undefined") { + // Fallback + return getDefaultWindowLocation(); + } + + if (typeof window.location !== "undefined") { + // Browsers place location on window + return window.location; + } + + if ( + typeof window.window !== "undefined" && + typeof window.window.location !== "undefined" + ) { + // React Native on Android places location on window.window + return window.window.location; + } + + return getDefaultWindowLocation(); + } + + function matchOne(response, reqMethod, reqUrl) { + var rmeth = response.method; + var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase(); + var url = response.url; + var matchUrl = + !url || + url === reqUrl || + (typeof url.test === "function" && url.test(reqUrl)) || + (typeof url === "function" && url(reqUrl) === true); + + return matchMethod && matchUrl; + } + + function match(response, request) { + var wloc = getWindowLocation(); + + var rCurrLoc = new RegExp(`^${wloc.protocol}//${wloc.host}/`); + + var requestUrl = request.url; + + if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) { + requestUrl = requestUrl.replace(rCurrLoc, "/"); + } + + if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { + if (typeof response.response === "function") { + var ru = response.url; + var args = [request].concat( + ru && typeof ru.exec === "function" + ? ru.exec(requestUrl).slice(1) + : [] + ); + return response.response.apply(response, args); } - ], - "heading": "Legacy single-byte encodings" + + return true; + } + + return false; + } + + function incrementRequestCount() { + var count = ++this.requestCount; + + this.requested = true; + + this.requestedOnce = count === 1; + this.requestedTwice = count === 2; + this.requestedThrice = count === 3; + + this.firstRequest = this.getRequest(0); + this.secondRequest = this.getRequest(1); + this.thirdRequest = this.getRequest(2); + + this.lastRequest = this.getRequest(count - 1); + } + + var fakeServer = { + create: function(config) { + var server = Object.create(this); + server.configure(config); + this.xhr = fakeXhr.useFakeXMLHttpRequest(); + server.requests = []; + server.requestCount = 0; + server.queue = []; + server.responses = []; + + this.xhr.onCreate = function(xhrObj) { + xhrObj.unsafeHeadersEnabled = function() { + return !(server.unsafeHeadersEnabled === false); + }; + server.addRequest(xhrObj); + }; + + return server; }, - { - "encodings": [ - { - "labels": [ - "chinese", - "csgb2312", - "csiso58gb231280", - "gb2312", - "gb_2312", - "gb_2312-80", - "gbk", - "iso-ir-58", - "x-gbk" - ], - "name": "GBK" - }, - { - "labels": [ - "gb18030" - ], - "name": "gb18030" + + configure: function(config) { + var self = this; + var allowlist = { + autoRespond: true, + autoRespondAfter: true, + respondImmediately: true, + fakeHTTPMethods: true, + logger: true, + unsafeHeadersEnabled: true + }; + + // eslint-disable-next-line no-param-reassign + config = config || {}; + + Object.keys(config).forEach(function(setting) { + if (setting in allowlist) { + self[setting] = config[setting]; + } + }); + + self.logError = configureLogError(config); + }, + + addRequest: function addRequest(xhrObj) { + var server = this; + push.call(this.requests, xhrObj); + + incrementRequestCount.call(this); + + xhrObj.onSend = function() { + server.handleRequest(this); + + if (server.respondImmediately) { + server.respond(); + } else if (server.autoRespond && !server.responding) { + setTimeout(function() { + server.responding = false; + server.respond(); + }, server.autoRespondAfter || 10); + + server.responding = true; + } + }; + }, + + getHTTPMethod: function getHTTPMethod(request) { + if (this.fakeHTTPMethods && /post/i.test(request.method)) { + var matches = (request.requestBody || "").match( + /_method=([^\b;]+)/ + ); + return matches ? matches[1] : request.method; } - ], - "heading": "Legacy multi-byte Chinese (simplified) encodings" + + return request.method; }, - { - "encodings": [ - { - "labels": [ - "big5", - "big5-hkscs", - "cn-big5", - "csbig5", - "x-x-big5" - ], - "name": "Big5" + + handleRequest: function handleRequest(xhr) { + if (xhr.async) { + push.call(this.queue, xhr); + } else { + this.processRequest(xhr); } - ], - "heading": "Legacy multi-byte Chinese (traditional) encodings" }, - { - "encodings": [ - { - "labels": [ - "cseucpkdfmtjapanese", - "euc-jp", - "x-euc-jp" - ], - "name": "EUC-JP" - }, - { - "labels": [ - "csiso2022jp", - "iso-2022-jp" - ], - "name": "ISO-2022-JP" - }, - { - "labels": [ - "csshiftjis", - "ms932", - "ms_kanji", - "shift-jis", - "shift_jis", - "sjis", - "windows-31j", - "x-sjis" - ], - "name": "Shift_JIS" + + logger: function() { + // no-op; override via configure() + }, + + logError: configureLogError({}), + + log: log, + + respondWith: function respondWith(method, url, body) { + if (arguments.length === 1 && typeof method !== "function") { + this.response = responseArray(method); + return; + } + + if (arguments.length === 1) { + // eslint-disable-next-line no-param-reassign + body = method; + // eslint-disable-next-line no-param-reassign + url = method = null; + } + + if (arguments.length === 2) { + // eslint-disable-next-line no-param-reassign + body = url; + // eslint-disable-next-line no-param-reassign + url = method; + // eslint-disable-next-line no-param-reassign + method = null; + } + + // Escape port number to prevent "named" parameters in 'path-to-regexp' module + if (typeof url === "string" && url !== "" && /:[0-9]+\//.test(url)) { + var m = url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/); + // eslint-disable-next-line no-param-reassign + url = `${m[1]}\\:${m[2]}`; } - ], - "heading": "Legacy multi-byte Japanese encodings" + + push.call(this.responses, { + method: method, + url: + typeof url === "string" && url !== "" ? pathToRegexp(url) : url, + response: typeof body === "function" ? body : responseArray(body) + }); }, - { - "encodings": [ - { - "labels": [ - "cseuckr", - "csksc56011987", - "euc-kr", - "iso-ir-149", - "korean", - "ks_c_5601-1987", - "ks_c_5601-1989", - "ksc5601", - "ksc_5601", - "windows-949" - ], - "name": "EUC-KR" + + respond: function respond() { + if (arguments.length > 0) { + this.respondWith.apply(this, arguments); } - ], - "heading": "Legacy multi-byte Korean encodings" + + var queue = this.queue || []; + var requests = queue.splice(0, queue.length); + var self = this; + + requests.forEach(function(request) { + self.processRequest(request); + }); }, - { - "encodings": [ - { - "labels": [ - "csiso2022kr", - "hz-gb-2312", - "iso-2022-cn", - "iso-2022-cn-ext", - "iso-2022-kr" - ], - "name": "replacement" - }, - { - "labels": [ - "utf-16be" - ], - "name": "UTF-16BE" - }, - { - "labels": [ - "utf-16", - "utf-16le" - ], - "name": "UTF-16LE" - }, - { - "labels": [ - "x-user-defined" - ], - "name": "x-user-defined" + + respondAll: function respondAll() { + if (this.respondImmediately) { + return; } - ], - "heading": "Legacy miscellaneous encodings" + + this.queue = this.requests.slice(0); + + var request; + while ((request = this.queue.shift())) { + this.processRequest(request); + } + }, + + processRequest: function processRequest(request) { + try { + if (request.aborted) { + return; + } + + var response = this.response || [404, {}, ""]; + + if (this.responses) { + for (var l = this.responses.length, i = l - 1; i >= 0; i--) { + if (match.call(this, this.responses[i], request)) { + response = this.responses[i].response; + break; + } + } + } + + if (request.readyState !== 4) { + this.log(response, request); + + request.respond(response[0], response[1], response[2]); + } + } catch (e) { + this.logError("Fake server request processing", e); + } + }, + + restore: function restore() { + return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments); + }, + + getRequest: function getRequest(index) { + return this.requests[index] || null; + }, + + reset: function reset() { + this.resetBehavior(); + this.resetHistory(); + }, + + resetBehavior: function resetBehavior() { + this.responses.length = this.queue.length = 0; + }, + + resetHistory: function resetHistory() { + this.requests.length = this.requestCount = 0; + + this.requestedOnce = this.requestedTwice = this.requestedThrice = this.requested = false; + + this.firstRequest = this.secondRequest = this.thirdRequest = this.lastRequest = null; } - ]; + }; + + module.exports = fakeServer; + + },{"../configure-logger":117,"../fake-xhr":127,"./log":125,"path-to-regexp":148}],125:[function(require,module,exports){ + var inspect = require("util").inspect; + + function log(response, request) { + var str; + + str = `Request:\n${inspect(request)}\n\n`; + str += `Response:\n${inspect(response)}\n\n`; + + /* istanbul ignore else: when this.logger is not a function, it can't be called */ + if (typeof this.logger === "function") { + this.logger(str); + } + } + + module.exports = log; + + },{"util":113}],126:[function(require,module,exports){ + + exports.isSupported = (function() { + try { + return Boolean(new Blob()); + } catch (e) { + return false; + } + })(); + + },{}],127:[function(require,module,exports){ + + var GlobalTextEncoder = + typeof TextEncoder !== "undefined" + ? TextEncoder + : require("@sinonjs/text-encoding").TextEncoder; + var globalObject = require("@sinonjs/commons").global; + var configureLogError = require("../configure-logger"); + var sinonEvent = require("../event"); + var extend = require("just-extend"); + + var supportsProgress = typeof ProgressEvent !== "undefined"; + var supportsCustomEvent = typeof CustomEvent !== "undefined"; + var supportsFormData = typeof FormData !== "undefined"; + var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + var supportsBlob = require("./blob").isSupported; + + function getWorkingXHR(globalScope) { + var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined"; + if (supportsXHR) { + return globalScope.XMLHttpRequest; + } + + var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined"; + if (supportsActiveX) { + return function() { + return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0"); + }; + } + + return false; + } + + // Ref: https://fetch.spec.whatwg.org/#forbidden-header-name + var unsafeHeaders = { + "Accept-Charset": true, + "Access-Control-Request-Headers": true, + "Access-Control-Request-Method": true, + "Accept-Encoding": true, + Connection: true, + "Content-Length": true, + Cookie: true, + Cookie2: true, + "Content-Transfer-Encoding": true, + Date: true, + DNT: true, + Expect: true, + Host: true, + "Keep-Alive": true, + Origin: true, + Referer: true, + TE: true, + Trailer: true, + "Transfer-Encoding": true, + Upgrade: true, + "User-Agent": true, + Via: true + }; + + function EventTargetHandler() { + var self = this; + var events = [ + "loadstart", + "progress", + "abort", + "error", + "load", + "timeout", + "loadend" + ]; + + function addEventListener(eventName) { + self.addEventListener(eventName, function(event) { + var listener = self[`on${eventName}`]; + + if (listener && typeof listener === "function") { + listener.call(this, event); + } + }); + } + + events.forEach(addEventListener); + } + + EventTargetHandler.prototype = sinonEvent.EventTarget; + + function normalizeHeaderValue(value) { + // Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes + /*eslint no-control-regex: "off"*/ + return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g, ""); + } - // Label to encoding registry. - /** @type {Object.}>} */ - var label_to_encoding = {}; - encodings.forEach(function(category) { - category.encodings.forEach(function(encoding) { - encoding.labels.forEach(function(label) { - label_to_encoding[label] = encoding; - }); + function getHeader(headers, header) { + var foundHeader = Object.keys(headers).filter(function(h) { + return h.toLowerCase() === header.toLowerCase(); }); - }); - - // Registry of of encoder/decoder factories, by encoding name. - /** @type {Object.} */ - var encoders = {}; - /** @type {Object.} */ - var decoders = {}; - // - // 6. Indexes - // + return foundHeader[0] || null; + } - /** - * @param {number} pointer The |pointer| to search for. - * @param {(!Array.|undefined)} index The |index| to search within. - * @return {?number} The code point corresponding to |pointer| in |index|, - * or null if |code point| is not in |index|. - */ - function indexCodePointFor(pointer, index) { - if (!index) return null; - return index[pointer] || null; - } + function excludeSetCookie2Header(header) { + return !/^Set-Cookie2?$/i.test(header); + } - /** - * @param {number} code_point The |code point| to search for. - * @param {!Array.} index The |index| to search within. - * @return {?number} The first pointer corresponding to |code point| in - * |index|, or null if |code point| is not in |index|. - */ - function indexPointerFor(code_point, index) { - var pointer = index.indexOf(code_point); - return pointer === -1 ? null : pointer; - } + function verifyResponseBodyType(body, responseType) { + var error = null; + var isString = typeof body === "string"; - /** - * @param {string} name Name of the index. - * @return {(!Array.|!Array.>)} - * */ - function index(name) { - if (!('encoding-indexes' in global)) { - throw Error("Indexes missing." + - " Did you forget to include encoding-indexes.js first?"); + if (responseType === "arraybuffer") { + if (!isString && !(body instanceof ArrayBuffer)) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string or ArrayBuffer.` + ); + error.name = "InvalidBodyException"; + } + } else if (responseType === "blob") { + if ( + !isString && + !(body instanceof ArrayBuffer) && + supportsBlob && + !(body instanceof Blob) + ) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string, ArrayBuffer, or Blob.` + ); + error.name = "InvalidBodyException"; + } + } else if (!isString) { + error = new Error( + `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string.` + ); + error.name = "InvalidBodyException"; } - return global['encoding-indexes'][name]; - } - - /** - * @param {number} pointer The |pointer| to search for in the gb18030 index. - * @return {?number} The code point corresponding to |pointer| in |index|, - * or null if |code point| is not in the gb18030 index. - */ - function indexGB18030RangesCodePointFor(pointer) { - // 1. If pointer is greater than 39419 and less than 189000, or - // pointer is greater than 1237575, return null. - if ((pointer > 39419 && pointer < 189000) || (pointer > 1237575)) - return null; - // 2. If pointer is 7457, return code point U+E7C7. - if (pointer === 7457) return 0xE7C7; + if (error) { + throw error; + } + } - // 3. Let offset be the last pointer in index gb18030 ranges that - // is equal to or less than pointer and let code point offset be - // its corresponding code point. - var offset = 0; - var code_point_offset = 0; - var idx = index('gb18030-ranges'); - var i; - for (i = 0; i < idx.length; ++i) { - /** @type {!Array.} */ - var entry = idx[i]; - if (entry[0] <= pointer) { - offset = entry[0]; - code_point_offset = entry[1]; - } else { - break; - } + function convertToArrayBuffer(body, encoding) { + if (body instanceof ArrayBuffer) { + return body; } - // 4. Return a code point whose value is code point offset + - // pointer − offset. - return code_point_offset + pointer - offset; - } + return new GlobalTextEncoder(encoding || "utf-8").encode(body).buffer; + } - /** - * @param {number} code_point The |code point| to locate in the gb18030 index. - * @return {number} The first pointer corresponding to |code point| in the - * gb18030 index. - */ - function indexGB18030RangesPointerFor(code_point) { - // 1. If code point is U+E7C7, return pointer 7457. - if (code_point === 0xE7C7) return 7457; + function isXmlContentType(contentType) { + return ( + !contentType || + /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType) + ); + } - // 2. Let offset be the last code point in index gb18030 ranges - // that is equal to or less than code point and let pointer offset - // be its corresponding pointer. - var offset = 0; - var pointer_offset = 0; - var idx = index('gb18030-ranges'); - var i; - for (i = 0; i < idx.length; ++i) { - /** @type {!Array.} */ - var entry = idx[i]; - if (entry[1] <= code_point) { - offset = entry[1]; - pointer_offset = entry[0]; - } else { - break; - } + function clearResponse(xhr) { + if (xhr.responseType === "" || xhr.responseType === "text") { + xhr.response = xhr.responseText = ""; + } else { + xhr.response = xhr.responseText = null; } + xhr.responseXML = null; + } - // 3. Return a pointer whose value is pointer offset + code point - // − offset. - return pointer_offset + code_point - offset; - } + function fakeXMLHttpRequestFor(globalScope) { + var isReactNative = + globalScope.navigator && + globalScope.navigator.product === "ReactNative"; + var sinonXhr = { XMLHttpRequest: globalScope.XMLHttpRequest }; + sinonXhr.GlobalXMLHttpRequest = globalScope.XMLHttpRequest; + sinonXhr.GlobalActiveXObject = globalScope.ActiveXObject; + sinonXhr.supportsActiveX = + typeof sinonXhr.GlobalActiveXObject !== "undefined"; + sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined"; + sinonXhr.workingXHR = getWorkingXHR(globalScope); + sinonXhr.supportsTimeout = + sinonXhr.supportsXHR && + "timeout" in new sinonXhr.GlobalXMLHttpRequest(); + sinonXhr.supportsCORS = + isReactNative || + (sinonXhr.supportsXHR && + "withCredentials" in new sinonXhr.GlobalXMLHttpRequest()); - /** - * @param {number} code_point The |code_point| to search for in the Shift_JIS - * index. - * @return {?number} The code point corresponding to |pointer| in |index|, - * or null if |code point| is not in the Shift_JIS index. - */ - function indexShiftJISPointerFor(code_point) { - // 1. Let index be index jis0208 excluding all entries whose - // pointer is in the range 8272 to 8835, inclusive. - shift_jis_index = shift_jis_index || - index('jis0208').map(function(code_point, pointer) { - return inRange(pointer, 8272, 8835) ? null : code_point; - }); - var index_ = shift_jis_index; + // Note that for FakeXMLHttpRequest to work pre ES5 + // we lose some of the alignment with the spec. + // To ensure as close a match as possible, + // set responseType before calling open, send or respond; + function FakeXMLHttpRequest(config) { + EventTargetHandler.call(this); + this.readyState = FakeXMLHttpRequest.UNSENT; + this.requestHeaders = {}; + this.requestBody = null; + this.status = 0; + this.statusText = ""; + this.upload = new EventTargetHandler(); + this.responseType = ""; + this.response = ""; + this.logError = configureLogError(config); - // 2. Return the index pointer for code point in index. - return index_.indexOf(code_point); - } - var shift_jis_index; + if (sinonXhr.supportsTimeout) { + this.timeout = 0; + } - /** - * @param {number} code_point The |code_point| to search for in the big5 - * index. - * @return {?number} The code point corresponding to |pointer| in |index|, - * or null if |code point| is not in the big5 index. - */ - function indexBig5PointerFor(code_point) { - // 1. Let index be index Big5 excluding all entries whose pointer - big5_index_no_hkscs = big5_index_no_hkscs || - index('big5').map(function(code_point, pointer) { - return (pointer < (0xA1 - 0x81) * 157) ? null : code_point; - }); - var index_ = big5_index_no_hkscs; + if (sinonXhr.supportsCORS) { + this.withCredentials = false; + } - // 2. If code point is U+2550, U+255E, U+2561, U+256A, U+5341, or - // U+5345, return the last pointer corresponding to code point in - // index. - if (code_point === 0x2550 || code_point === 0x255E || - code_point === 0x2561 || code_point === 0x256A || - code_point === 0x5341 || code_point === 0x5345) { - return index_.lastIndexOf(code_point); + if (typeof FakeXMLHttpRequest.onCreate === "function") { + FakeXMLHttpRequest.onCreate(this); + } + } + + function verifyState(xhr) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { + throw new Error("INVALID_STATE_ERR"); + } + + if (xhr.sendFlag) { + throw new Error("INVALID_STATE_ERR"); + } } - // 3. Return the index pointer for code point in index. - return indexPointerFor(code_point, index_); - } - var big5_index_no_hkscs; + // largest arity in XHR is 5 - XHR#open + var apply = function(obj, method, args) { + switch (args.length) { + case 0: + return obj[method](); + case 1: + return obj[method](args[0]); + case 2: + return obj[method](args[0], args[1]); + case 3: + return obj[method](args[0], args[1], args[2]); + case 4: + return obj[method](args[0], args[1], args[2], args[3]); + case 5: + return obj[method](args[0], args[1], args[2], args[3], args[4]); + default: + throw new Error("Unhandled case"); + } + }; - // - // 8. API - // + FakeXMLHttpRequest.filters = []; + FakeXMLHttpRequest.addFilter = function addFilter(fn) { + this.filters.push(fn); + }; + FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) { + var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap - /** @const */ var DEFAULT_ENCODING = 'utf-8'; + [ + "open", + "setRequestHeader", + "abort", + "getResponseHeader", + "getAllResponseHeaders", + "addEventListener", + "overrideMimeType", + "removeEventListener" + ].forEach(function(method) { + fakeXhr[method] = function() { + return apply(xhr, method, arguments); + }; + }); - // 8.1 Interface TextDecoder + fakeXhr.send = function() { + // Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute + if (xhr.responseType !== fakeXhr.responseType) { + xhr.responseType = fakeXhr.responseType; + } + return apply(xhr, "send", arguments); + }; - /** - * @constructor - * @param {string=} label The label of the encoding; - * defaults to 'utf-8'. - * @param {Object=} options - */ - function TextDecoder(label, options) { - // Web IDL conventions - if (!(this instanceof TextDecoder)) - throw TypeError('Called as a function. Did you forget \'new\'?'); - label = label !== undefined ? String(label) : DEFAULT_ENCODING; - options = ToDictionary(options); + var copyAttrs = function(args) { + args.forEach(function(attr) { + fakeXhr[attr] = xhr[attr]; + }); + }; - // A TextDecoder object has an associated encoding, decoder, - // stream, ignore BOM flag (initially unset), BOM seen flag - // (initially unset), error mode (initially replacement), and do - // not flush flag (initially unset). + var stateChangeStart = function() { + fakeXhr.readyState = xhr.readyState; + if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) { + copyAttrs(["status", "statusText"]); + } + if (xhr.readyState >= FakeXMLHttpRequest.LOADING) { + copyAttrs(["response"]); + if (xhr.responseType === "" || xhr.responseType === "text") { + copyAttrs(["responseText"]); + } + } + if ( + xhr.readyState === FakeXMLHttpRequest.DONE && + (xhr.responseType === "" || xhr.responseType === "document") + ) { + copyAttrs(["responseXML"]); + } + }; - /** @private */ - this._encoding = null; - /** @private @type {?Decoder} */ - this._decoder = null; - /** @private @type {boolean} */ - this._ignoreBOM = false; - /** @private @type {boolean} */ - this._BOMseen = false; - /** @private @type {string} */ - this._error_mode = 'replacement'; - /** @private @type {boolean} */ - this._do_not_flush = false; + var stateChangeEnd = function() { + if (fakeXhr.onreadystatechange) { + // eslint-disable-next-line no-useless-call + fakeXhr.onreadystatechange.call(fakeXhr, { + target: fakeXhr, + currentTarget: fakeXhr + }); + } + }; + var stateChange = function stateChange() { + stateChangeStart(); + stateChangeEnd(); + }; - // 1. Let encoding be the result of getting an encoding from - // label. - var encoding = getEncoding(label); + if (xhr.addEventListener) { + xhr.addEventListener("readystatechange", stateChangeStart); - // 2. If encoding is failure or replacement, throw a RangeError. - if (encoding === null || encoding.name === 'replacement') - throw RangeError('Unknown encoding: ' + label); - if (!decoders[encoding.name]) { - throw Error('Decoder not present.' + - ' Did you forget to include encoding-indexes.js first?'); - } + Object.keys(fakeXhr.eventListeners).forEach(function(event) { + /*eslint-disable no-loop-func*/ + fakeXhr.eventListeners[event].forEach(function(handler) { + xhr.addEventListener(event, handler.listener, { + capture: handler.capture, + once: handler.once + }); + }); + /*eslint-enable no-loop-func*/ + }); - // 3. Let dec be a new TextDecoder object. - var dec = this; + xhr.addEventListener("readystatechange", stateChangeEnd); + } else { + xhr.onreadystatechange = stateChange; + } + apply(xhr, "open", xhrArgs); + }; + FakeXMLHttpRequest.useFilters = false; - // 4. Set dec's encoding to encoding. - dec._encoding = encoding; + function verifyRequestOpened(xhr) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { + const errorMessage = + xhr.readyState === FakeXMLHttpRequest.UNSENT + ? "INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first..." + : `INVALID_STATE_ERR - ${xhr.readyState}`; + throw new Error(errorMessage); + } + } - // 5. If options's fatal member is true, set dec's error mode to - // fatal. - if (Boolean(options['fatal'])) - dec._error_mode = 'fatal'; + function verifyRequestSent(xhr) { + if (xhr.readyState === FakeXMLHttpRequest.DONE) { + throw new Error("Request done"); + } + } - // 6. If options's ignoreBOM member is true, set dec's ignore BOM - // flag. - if (Boolean(options['ignoreBOM'])) - dec._ignoreBOM = true; + function verifyHeadersReceived(xhr) { + if ( + xhr.async && + xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED + ) { + throw new Error("No headers received"); + } + } - // For pre-ES5 runtimes: - if (!Object.defineProperty) { - this.encoding = dec._encoding.name.toLowerCase(); - this.fatal = dec._error_mode === 'fatal'; - this.ignoreBOM = dec._ignoreBOM; + function convertResponseBody(responseType, contentType, body) { + if (responseType === "" || responseType === "text") { + return body; + } else if (supportsArrayBuffer && responseType === "arraybuffer") { + return convertToArrayBuffer(body); + } else if (responseType === "json") { + try { + return JSON.parse(body); + } catch (e) { + // Return parsing failure as null + return null; + } + } else if (supportsBlob && responseType === "blob") { + if (body instanceof Blob) { + return body; + } + + var blobOptions = {}; + if (contentType) { + blobOptions.type = contentType; + } + return new Blob([convertToArrayBuffer(body)], blobOptions); + } else if (responseType === "document") { + if (isXmlContentType(contentType)) { + return FakeXMLHttpRequest.parseXML(body); + } + return null; + } + throw new Error(`Invalid responseType ${responseType}`); } - // 7. Return dec. - return dec; - } + /** + * Steps to follow when there is an error, according to: + * https://xhr.spec.whatwg.org/#request-error-steps + */ + function requestErrorSteps(xhr) { + clearResponse(xhr); + xhr.errorFlag = true; + xhr.requestHeaders = {}; + xhr.responseHeaders = {}; - if (Object.defineProperty) { - // The encoding attribute's getter must return encoding's name. - Object.defineProperty(TextDecoder.prototype, 'encoding', { - /** @this {TextDecoder} */ - get: function() { return this._encoding.name.toLowerCase(); } - }); + if ( + xhr.readyState !== FakeXMLHttpRequest.UNSENT && + xhr.sendFlag && + xhr.readyState !== FakeXMLHttpRequest.DONE + ) { + xhr.readyStateChange(FakeXMLHttpRequest.DONE); + xhr.sendFlag = false; + } + } - // The fatal attribute's getter must return true if error mode - // is fatal, and false otherwise. - Object.defineProperty(TextDecoder.prototype, 'fatal', { - /** @this {TextDecoder} */ - get: function() { return this._error_mode === 'fatal'; } - }); + FakeXMLHttpRequest.parseXML = function parseXML(text) { + // Treat empty string as parsing failure + if (text !== "") { + try { + if (typeof DOMParser !== "undefined") { + var parser = new DOMParser(); + var parsererrorNS = ""; - // The ignoreBOM attribute's getter must return true if ignore - // BOM flag is set, and false otherwise. - Object.defineProperty(TextDecoder.prototype, 'ignoreBOM', { - /** @this {TextDecoder} */ - get: function() { return this._ignoreBOM; } - }); - } + try { + var parsererrors = parser + .parseFromString("INVALID", "text/xml") + .getElementsByTagName("parsererror"); + if (parsererrors.length) { + parsererrorNS = parsererrors[0].namespaceURI; + } + } catch (e) { + // passing invalid XML makes IE11 throw + // so no namespace needs to be determined + } - /** - * @param {BufferSource=} input The buffer of bytes to decode. - * @param {Object=} options - * @return {string} The decoded string. - */ - TextDecoder.prototype.decode = function decode(input, options) { - var bytes; - if (typeof input === 'object' && input instanceof ArrayBuffer) { - bytes = new Uint8Array(input); - } else if (typeof input === 'object' && 'buffer' in input && - input.buffer instanceof ArrayBuffer) { - bytes = new Uint8Array(input.buffer, - input.byteOffset, - input.byteLength); - } else { - bytes = new Uint8Array(0); - } + var result; + try { + result = parser.parseFromString(text, "text/xml"); + } catch (err) { + return null; + } - options = ToDictionary(options); + return result.getElementsByTagNameNS( + parsererrorNS, + "parsererror" + ).length + ? null + : result; + } + var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(text); + return xmlDoc.parseError.errorCode !== 0 ? null : xmlDoc; + } catch (e) { + // Unable to parse XML - no biggie + } + } - // 1. If the do not flush flag is unset, set decoder to a new - // encoding's decoder, set stream to a new stream, and unset the - // BOM seen flag. - if (!this._do_not_flush) { - this._decoder = decoders[this._encoding.name]({ - fatal: this._error_mode === 'fatal'}); - this._BOMseen = false; - } + return null; + }; - // 2. If options's stream is true, set the do not flush flag, and - // unset the do not flush flag otherwise. - this._do_not_flush = Boolean(options['stream']); + FakeXMLHttpRequest.statusCodes = { + 100: "Continue", + 101: "Switching Protocols", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 300: "Multiple Choice", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 307: "Temporary Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported" + }; - // 3. If input is given, push a copy of input to stream. - // TODO: Align with spec algorithm - maintain stream on instance. - var input_stream = new Stream(bytes); + extend(FakeXMLHttpRequest.prototype, sinonEvent.EventTarget, { + async: true, - // 4. Let output be a new stream. - var output = []; + open: function open(method, url, async, username, password) { + this.method = method; + this.url = url; + this.async = typeof async === "boolean" ? async : true; + this.username = username; + this.password = password; + clearResponse(this); + this.requestHeaders = {}; + this.sendFlag = false; - /** @type {?(number|!Array.)} */ - var result; + if (FakeXMLHttpRequest.useFilters === true) { + var xhrArgs = arguments; + var defake = FakeXMLHttpRequest.filters.some(function(filter) { + return filter.apply(this, xhrArgs); + }); + if (defake) { + FakeXMLHttpRequest.defake(this, arguments); + return; + } + } + this.readyStateChange(FakeXMLHttpRequest.OPENED); + }, - // 5. While true: - while (true) { - // 1. Let token be the result of reading from stream. - var token = input_stream.read(); + readyStateChange: function readyStateChange(state) { + this.readyState = state; - // 2. If token is end-of-stream and the do not flush flag is - // set, return output, serialized. - // TODO: Align with spec algorithm. - if (token === end_of_stream) - break; + var readyStateChangeEvent = new sinonEvent.Event( + "readystatechange", + false, + false, + this + ); + if (typeof this.onreadystatechange === "function") { + try { + this.onreadystatechange(readyStateChangeEvent); + } catch (e) { + this.logError("Fake XHR onreadystatechange handler", e); + } + } - // 3. Otherwise, run these subsubsteps: + if (this.readyState !== FakeXMLHttpRequest.DONE) { + this.dispatchEvent(readyStateChangeEvent); + } else { + var event, progress; - // 1. Let result be the result of processing token for decoder, - // stream, output, and error mode. - result = this._decoder.handler(input_stream, token); + if (this.timedOut || this.aborted || this.status === 0) { + progress = { loaded: 0, total: 0 }; + event = + (this.timedOut && "timeout") || + (this.aborted && "abort") || + "error"; + } else { + progress = { loaded: 100, total: 100 }; + event = "load"; + } - // 2. If result is finished, return output, serialized. - if (result === finished) - break; + if (supportsProgress) { + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent("progress", progress, this) + ); + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent(event, progress, this) + ); + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent("loadend", progress, this) + ); + } - if (result !== null) { - if (Array.isArray(result)) - output.push.apply(output, /**@type {!Array.}*/(result)); - else - output.push(result); - } + this.dispatchEvent( + new sinonEvent.ProgressEvent("progress", progress, this) + ); + this.dispatchEvent( + new sinonEvent.ProgressEvent(event, progress, this) + ); + this.dispatchEvent(readyStateChangeEvent); + this.dispatchEvent( + new sinonEvent.ProgressEvent("loadend", progress, this) + ); + } + }, - // 3. Otherwise, if result is error, throw a TypeError. - // (Thrown in handler) + // Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method + setRequestHeader: function setRequestHeader(header, value) { + if (typeof value !== "string") { + throw new TypeError( + `By RFC7230, section 3.2.4, header values should be strings. Got ${typeof value}` + ); + } + verifyState(this); - // 4. Otherwise, do nothing. - } - // TODO: Align with spec algorithm. - if (!this._do_not_flush) { - do { - result = this._decoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (result === null) - continue; - if (Array.isArray(result)) - output.push.apply(output, /**@type {!Array.}*/(result)); - else - output.push(result); - } while (!input_stream.endOfStream()); - this._decoder = null; - } + var checkUnsafeHeaders = true; + if (typeof this.unsafeHeadersEnabled === "function") { + checkUnsafeHeaders = this.unsafeHeadersEnabled(); + } + + if ( + checkUnsafeHeaders && + (getHeader(unsafeHeaders, header) !== null || + /^(Sec-|Proxy-)/i.test(header)) + ) { + throw new Error( + // eslint-disable-next-line quotes + `Refused to set unsafe header "${header}"` + ); + } - // A TextDecoder object also has an associated serialize stream - // algorithm... - /** - * @param {!Array.} stream - * @return {string} - * @this {TextDecoder} - */ - function serializeStream(stream) { - // 1. Let token be the result of reading from stream. - // (Done in-place on array, rather than as a stream) + // eslint-disable-next-line no-param-reassign + value = normalizeHeaderValue(value); - // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore - // BOM flag and BOM seen flag are unset, run these subsubsteps: - if (includes(['UTF-8', 'UTF-16LE', 'UTF-16BE'], this._encoding.name) && - !this._ignoreBOM && !this._BOMseen) { - if (stream.length > 0 && stream[0] === 0xFEFF) { - // 1. If token is U+FEFF, set BOM seen flag. - this._BOMseen = true; - stream.shift(); - } else if (stream.length > 0) { - // 2. Otherwise, if token is not end-of-stream, set BOM seen - // flag and append token to stream. - this._BOMseen = true; - } else ; - } - // 4. Otherwise, return output. - return codePointsToString(stream); - } + var existingHeader = getHeader(this.requestHeaders, header); + if (existingHeader) { + this.requestHeaders[existingHeader] += `, ${value}`; + } else { + this.requestHeaders[header] = value; + } + }, - return serializeStream.call(this, output); - }; + setStatus: function setStatus(status) { + var sanitizedStatus = typeof status === "number" ? status : 200; - // 8.2 Interface TextEncoder + verifyRequestOpened(this); + this.status = sanitizedStatus; + this.statusText = FakeXMLHttpRequest.statusCodes[sanitizedStatus]; + }, - /** - * @constructor - * @param {string=} label The label of the encoding. NONSTANDARD. - * @param {Object=} options NONSTANDARD. - */ - function TextEncoder(label, options) { - // Web IDL conventions - if (!(this instanceof TextEncoder)) - throw TypeError('Called as a function. Did you forget \'new\'?'); - options = ToDictionary(options); + // Helps testing + setResponseHeaders: function setResponseHeaders(headers) { + verifyRequestOpened(this); - // A TextEncoder object has an associated encoding and encoder. + var responseHeaders = (this.responseHeaders = {}); - /** @private */ - this._encoding = null; - /** @private @type {?Encoder} */ - this._encoder = null; + Object.keys(headers).forEach(function(header) { + responseHeaders[header] = headers[header]; + }); - // Non-standard - /** @private @type {boolean} */ - this._do_not_flush = false; - /** @private @type {string} */ - this._fatal = Boolean(options['fatal']) ? 'fatal' : 'replacement'; + if (this.async) { + this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); + } else { + this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; + } + }, - // 1. Let enc be a new TextEncoder object. - var enc = this; + // Currently treats ALL data as a DOMString (i.e. no Document) + send: function send(data) { + verifyState(this); - // 2. Set enc's encoding to UTF-8's encoder. - if (Boolean(options['NONSTANDARD_allowLegacyEncoding'])) { - // NONSTANDARD behavior. - label = label !== undefined ? String(label) : DEFAULT_ENCODING; - var encoding = getEncoding(label); - if (encoding === null || encoding.name === 'replacement') - throw RangeError('Unknown encoding: ' + label); - if (!encoders[encoding.name]) { - throw Error('Encoder not present.' + - ' Did you forget to include encoding-indexes.js first?'); - } - enc._encoding = encoding; - } else { - // Standard behavior. - enc._encoding = getEncoding('utf-8'); + if (!/^(head)$/i.test(this.method)) { + var contentType = getHeader( + this.requestHeaders, + "Content-Type" + ); + if (this.requestHeaders[contentType]) { + var value = this.requestHeaders[contentType].split(";"); + this.requestHeaders[ + contentType + ] = `${value[0]};charset=utf-8`; + } else if (supportsFormData && !(data instanceof FormData)) { + this.requestHeaders["Content-Type"] = + "text/plain;charset=utf-8"; + } - if (label !== undefined && 'console' in global) { - console.warn('TextEncoder constructor called with encoding label, ' - + 'which is ignored.'); - } - } + this.requestBody = data; + } - // For pre-ES5 runtimes: - if (!Object.defineProperty) - this.encoding = enc._encoding.name.toLowerCase(); + this.errorFlag = false; + this.sendFlag = this.async; + clearResponse(this); - // 3. Return enc. - return enc; - } + if (typeof this.onSend === "function") { + this.onSend(this); + } - if (Object.defineProperty) { - // The encoding attribute's getter must return encoding's name. - Object.defineProperty(TextEncoder.prototype, 'encoding', { - /** @this {TextEncoder} */ - get: function() { return this._encoding.name.toLowerCase(); } - }); - } + // Only listen if setInterval and Date are a stubbed. + if ( + sinonXhr.supportsTimeout && + typeof setInterval.clock === "object" && + typeof Date.clock === "object" + ) { + var initiatedTime = Date.now(); + var self = this; - /** - * @param {string=} opt_string The string to encode. - * @param {Object=} options - * @return {!Uint8Array} Encoded bytes, as a Uint8Array. - */ - TextEncoder.prototype.encode = function encode(opt_string, options) { - opt_string = opt_string === undefined ? '' : String(opt_string); - options = ToDictionary(options); + // Listen to any possible tick by fake timers and check to see if timeout has + // been exceeded. It's important to note that timeout can be changed while a request + // is in flight, so we must check anytime the end user forces a clock tick to make + // sure timeout hasn't changed. + // https://xhr.spec.whatwg.org/#dfnReturnLink-2 + var clearIntervalId = setInterval(function() { + // Check if the readyState has been reset or is done. If this is the case, there + // should be no timeout. This will also prevent aborted requests and + // fakeServerWithClock from triggering unnecessary responses. + if ( + self.readyState === FakeXMLHttpRequest.UNSENT || + self.readyState === FakeXMLHttpRequest.DONE + ) { + clearInterval(clearIntervalId); + } else if ( + typeof self.timeout === "number" && + self.timeout > 0 + ) { + if (Date.now() >= initiatedTime + self.timeout) { + self.triggerTimeout(); + clearInterval(clearIntervalId); + } + } + }, 1); + } - // NOTE: This option is nonstandard. None of the encodings - // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when - // the input is a USVString so streaming is not necessary. - if (!this._do_not_flush) - this._encoder = encoders[this._encoding.name]({ - fatal: this._fatal === 'fatal'}); - this._do_not_flush = Boolean(options['stream']); + this.dispatchEvent( + new sinonEvent.Event("loadstart", false, false, this) + ); + }, - // 1. Convert input to a stream. - var input = new Stream(stringToCodePoints(opt_string)); + abort: function abort() { + this.aborted = true; + requestErrorSteps(this); + this.readyState = FakeXMLHttpRequest.UNSENT; + }, - // 2. Let output be a new stream - var output = []; + error: function() { + clearResponse(this); + this.errorFlag = true; + this.requestHeaders = {}; + this.responseHeaders = {}; - /** @type {?(number|!Array.)} */ - var result; - // 3. While true, run these substeps: - while (true) { - // 1. Let token be the result of reading from input. - var token = input.read(); - if (token === end_of_stream) - break; - // 2. Let result be the result of processing token for encoder, - // input, output. - result = this._encoder.handler(input, token); - if (result === finished) - break; - if (Array.isArray(result)) - output.push.apply(output, /**@type {!Array.}*/(result)); - else - output.push(result); - } - // TODO: Align with spec algorithm. - if (!this._do_not_flush) { - while (true) { - result = this._encoder.handler(input, input.read()); - if (result === finished) - break; - if (Array.isArray(result)) - output.push.apply(output, /**@type {!Array.}*/(result)); - else - output.push(result); - } - this._encoder = null; - } - // 3. If result is finished, convert output into a byte sequence, - // and then return a Uint8Array object wrapping an ArrayBuffer - // containing output. - return new Uint8Array(output); - }; + this.readyStateChange(FakeXMLHttpRequest.DONE); + }, + + triggerTimeout: function triggerTimeout() { + if (sinonXhr.supportsTimeout) { + this.timedOut = true; + requestErrorSteps(this); + } + }, + + getResponseHeader: function getResponseHeader(header) { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return null; + } + if (/^Set-Cookie2?$/i.test(header)) { + return null; + } - // - // 9. The encoding - // + // eslint-disable-next-line no-param-reassign + header = getHeader(this.responseHeaders, header); - // 9.1 utf-8 + return this.responseHeaders[header] || null; + }, - // 9.1.1 utf-8 decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ - function UTF8Decoder(options) { - var fatal = options.fatal; + getAllResponseHeaders: function getAllResponseHeaders() { + if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { + return ""; + } - // utf-8's decoder's has an associated utf-8 code point, utf-8 - // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 - // lower boundary (initially 0x80), and a utf-8 upper boundary - // (initially 0xBF). - var /** @type {number} */ utf8_code_point = 0, - /** @type {number} */ utf8_bytes_seen = 0, - /** @type {number} */ utf8_bytes_needed = 0, - /** @type {number} */ utf8_lower_boundary = 0x80, - /** @type {number} */ utf8_upper_boundary = 0xBF; + var responseHeaders = this.responseHeaders; + var headers = Object.keys(responseHeaders) + .filter(excludeSetCookie2Header) + .reduce(function(prev, header) { + var value = responseHeaders[header]; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, - // set utf-8 bytes needed to 0 and return error. - if (bite === end_of_stream && utf8_bytes_needed !== 0) { - utf8_bytes_needed = 0; - return decoderError(fatal); - } + return `${prev}${header}: ${value}\r\n`; + }, ""); - // 2. If byte is end-of-stream, return finished. - if (bite === end_of_stream) - return finished; + return headers; + }, - // 3. If utf-8 bytes needed is 0, based on byte: - if (utf8_bytes_needed === 0) { + setResponseBody: function setResponseBody(body) { + verifyRequestSent(this); + verifyHeadersReceived(this); + verifyResponseBodyType(body, this.responseType); + var contentType = + this.overriddenMimeType || + this.getResponseHeader("Content-Type"); - // 0x00 to 0x7F - if (inRange(bite, 0x00, 0x7F)) { - // Return a code point whose value is byte. - return bite; - } + var isTextResponse = + this.responseType === "" || this.responseType === "text"; + clearResponse(this); + if (this.async) { + var chunkSize = this.chunkSize || 10; + var index = 0; - // 0xC2 to 0xDF - else if (inRange(bite, 0xC2, 0xDF)) { - // 1. Set utf-8 bytes needed to 1. - utf8_bytes_needed = 1; + do { + this.readyStateChange(FakeXMLHttpRequest.LOADING); - // 2. Set UTF-8 code point to byte & 0x1F. - utf8_code_point = bite & 0x1F; - } + if (isTextResponse) { + this.responseText = this.response += body.substring( + index, + index + chunkSize + ); + } + index += chunkSize; + } while (index < body.length); + } - // 0xE0 to 0xEF - else if (inRange(bite, 0xE0, 0xEF)) { - // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. - if (bite === 0xE0) - utf8_lower_boundary = 0xA0; - // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. - if (bite === 0xED) - utf8_upper_boundary = 0x9F; - // 3. Set utf-8 bytes needed to 2. - utf8_bytes_needed = 2; - // 4. Set UTF-8 code point to byte & 0xF. - utf8_code_point = bite & 0xF; - } + this.response = convertResponseBody( + this.responseType, + contentType, + body + ); + if (isTextResponse) { + this.responseText = this.response; + } - // 0xF0 to 0xF4 - else if (inRange(bite, 0xF0, 0xF4)) { - // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. - if (bite === 0xF0) - utf8_lower_boundary = 0x90; - // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. - if (bite === 0xF4) - utf8_upper_boundary = 0x8F; - // 3. Set utf-8 bytes needed to 3. - utf8_bytes_needed = 3; - // 4. Set UTF-8 code point to byte & 0x7. - utf8_code_point = bite & 0x7; - } + if (this.responseType === "document") { + this.responseXML = this.response; + } else if ( + this.responseType === "" && + isXmlContentType(contentType) + ) { + this.responseXML = FakeXMLHttpRequest.parseXML( + this.responseText + ); + } + this.readyStateChange(FakeXMLHttpRequest.DONE); + }, - // Otherwise - else { - // Return error. - return decoderError(fatal); - } + respond: function respond(status, headers, body) { + this.responseURL = this.url; - // Return continue. - return null; - } + this.setStatus(status); + this.setResponseHeaders(headers || {}); + this.setResponseBody(body || ""); + }, - // 4. If byte is not in the range utf-8 lower boundary to utf-8 - // upper boundary, inclusive, run these substeps: - if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { + uploadProgress: function uploadProgress(progressEventRaw) { + if (supportsProgress) { + this.upload.dispatchEvent( + new sinonEvent.ProgressEvent( + "progress", + progressEventRaw, + this.upload + ) + ); + } + }, - // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 - // bytes seen to 0, set utf-8 lower boundary to 0x80, and set - // utf-8 upper boundary to 0xBF. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; + downloadProgress: function downloadProgress(progressEventRaw) { + if (supportsProgress) { + this.dispatchEvent( + new sinonEvent.ProgressEvent( + "progress", + progressEventRaw, + this + ) + ); + } + }, - // 2. Prepend byte to stream. - stream.prepend(bite); + uploadError: function uploadError(error) { + if (supportsCustomEvent) { + this.upload.dispatchEvent( + new sinonEvent.CustomEvent("error", { detail: error }) + ); + } + }, - // 3. Return error. - return decoderError(fatal); - } + overrideMimeType: function overrideMimeType(type) { + if (this.readyState >= FakeXMLHttpRequest.LOADING) { + throw new Error("INVALID_STATE_ERR"); + } + this.overriddenMimeType = type; + } + }); - // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary - // to 0xBF. - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; + var states = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4 + }; - // 6. Set UTF-8 code point to (UTF-8 code point << 6) | (byte & - // 0x3F) - utf8_code_point = (utf8_code_point << 6) | (bite & 0x3F); + extend(FakeXMLHttpRequest, states); + extend(FakeXMLHttpRequest.prototype, states); - // 7. Increase utf-8 bytes seen by one. - utf8_bytes_seen += 1; + function useFakeXMLHttpRequest() { + FakeXMLHttpRequest.restore = function restore(keepOnCreate) { + if (sinonXhr.supportsXHR) { + globalScope.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest; + } - // 8. If utf-8 bytes seen is not equal to utf-8 bytes needed, - // continue. - if (utf8_bytes_seen !== utf8_bytes_needed) - return null; + if (sinonXhr.supportsActiveX) { + globalScope.ActiveXObject = sinonXhr.GlobalActiveXObject; + } + + delete FakeXMLHttpRequest.restore; + + if (keepOnCreate !== true) { + delete FakeXMLHttpRequest.onCreate; + } + }; + if (sinonXhr.supportsXHR) { + globalScope.XMLHttpRequest = FakeXMLHttpRequest; + } + + if (sinonXhr.supportsActiveX) { + globalScope.ActiveXObject = function ActiveXObject(objId) { + if ( + objId === "Microsoft.XMLHTTP" || + /^Msxml2\.XMLHTTP/i.test(objId) + ) { + return new FakeXMLHttpRequest(); + } - // 9. Let code point be utf-8 code point. - var code_point = utf8_code_point; + return new sinonXhr.GlobalActiveXObject(objId); + }; + } - // 10. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes - // seen to 0. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + return FakeXMLHttpRequest; + } - // 11. Return a code point whose value is code point. - return code_point; + return { + xhr: sinonXhr, + FakeXMLHttpRequest: FakeXMLHttpRequest, + useFakeXMLHttpRequest: useFakeXMLHttpRequest }; - } - - // 9.1.2 utf-8 encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ - function UTF8Encoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; + } - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + module.exports = extend(fakeXMLHttpRequestFor(globalObject), { + fakeXMLHttpRequestFor: fakeXMLHttpRequestFor + }); - // 3. Set count and offset based on the range code point is in: - var count, offset; - // U+0080 to U+07FF, inclusive: - if (inRange(code_point, 0x0080, 0x07FF)) { - // 1 and 0xC0 - count = 1; - offset = 0xC0; - } - // U+0800 to U+FFFF, inclusive: - else if (inRange(code_point, 0x0800, 0xFFFF)) { - // 2 and 0xE0 - count = 2; - offset = 0xE0; - } - // U+10000 to U+10FFFF, inclusive: - else if (inRange(code_point, 0x10000, 0x10FFFF)) { - // 3 and 0xF0 - count = 3; - offset = 0xF0; - } + },{"../configure-logger":117,"../event":121,"./blob":126,"@sinonjs/commons":135,"@sinonjs/text-encoding":108,"just-extend":115}],128:[function(require,module,exports){ - // 4. Let bytes be a byte sequence whose first byte is (code - // point >> (6 × count)) + offset. - var bytes = [(code_point >> (6 * count)) + offset]; + module.exports = { + fakeServer: require("./fake-server"), + fakeServerWithClock: require("./fake-server/fake-server-with-clock"), + fakeXhr: require("./fake-xhr") + }; - // 5. Run these substeps while count is greater than 0: - while (count > 0) { + },{"./fake-server":124,"./fake-server/fake-server-with-clock":123,"./fake-xhr":127}],129:[function(require,module,exports){ + arguments[4][42][0].apply(exports,arguments); + },{"./prototypes/array":137,"dup":42}],130:[function(require,module,exports){ + arguments[4][43][0].apply(exports,arguments); + },{"./function-name":133,"dup":43}],131:[function(require,module,exports){ + arguments[4][44][0].apply(exports,arguments); + },{"dup":44}],132:[function(require,module,exports){ + arguments[4][45][0].apply(exports,arguments); + },{"dup":45}],133:[function(require,module,exports){ + arguments[4][46][0].apply(exports,arguments); + },{"dup":46}],134:[function(require,module,exports){ + arguments[4][47][0].apply(exports,arguments); + },{"dup":47}],135:[function(require,module,exports){ + arguments[4][48][0].apply(exports,arguments); + },{"./called-in-order":129,"./class-name":130,"./deprecated":131,"./every":132,"./function-name":133,"./global":134,"./order-by-first-call":136,"./prototypes":140,"./type-of":146,"./value-to-string":147,"dup":48}],136:[function(require,module,exports){ + arguments[4][49][0].apply(exports,arguments); + },{"./prototypes/array":137,"dup":49}],137:[function(require,module,exports){ + arguments[4][50][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":50}],138:[function(require,module,exports){ + arguments[4][51][0].apply(exports,arguments); + },{"./throws-on-proto":145,"dup":51}],139:[function(require,module,exports){ + arguments[4][52][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":52}],140:[function(require,module,exports){ + arguments[4][53][0].apply(exports,arguments); + },{"./array":137,"./function":139,"./map":141,"./object":142,"./set":143,"./string":144,"dup":53}],141:[function(require,module,exports){ + arguments[4][54][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":54}],142:[function(require,module,exports){ + arguments[4][55][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":55}],143:[function(require,module,exports){ + arguments[4][56][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":56}],144:[function(require,module,exports){ + arguments[4][57][0].apply(exports,arguments); + },{"./copy-prototype-methods":138,"dup":57}],145:[function(require,module,exports){ + arguments[4][58][0].apply(exports,arguments); + },{"dup":58}],146:[function(require,module,exports){ + arguments[4][59][0].apply(exports,arguments); + },{"dup":59,"type-detect":151}],147:[function(require,module,exports){ + arguments[4][60][0].apply(exports,arguments); + },{"dup":60}],148:[function(require,module,exports){ + var isarray = require('isarray'); - // 1. Set temp to code point >> (6 × (count − 1)). - var temp = code_point >> (6 * (count - 1)); + /** + * Expose `pathToRegexp`. + */ + module.exports = pathToRegexp; + module.exports.parse = parse; + module.exports.compile = compile; + module.exports.tokensToFunction = tokensToFunction; + module.exports.tokensToRegExp = tokensToRegExp; - // 2. Append to bytes 0x80 | (temp & 0x3F). - bytes.push(0x80 | (temp & 0x3F)); + /** + * The main path matching regexp utility. + * + * @type {RegExp} + */ + var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' + ].join('|'), 'g'); - // 3. Decrease count by one. - count -= 1; - } + /** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */ + function parse (str, options) { + var tokens = []; + var key = 0; + var index = 0; + var path = ''; + var defaultDelimiter = options && options.delimiter || '/'; + var res; - // 6. Return bytes bytes, in order. - return bytes; - }; - } + while ((res = PATH_REGEXP.exec(str)) != null) { + var m = res[0]; + var escaped = res[1]; + var offset = res.index; + path += str.slice(index, offset); + index = offset + m.length; - /** @param {{fatal: boolean}} options */ - encoders['UTF-8'] = function(options) { - return new UTF8Encoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['UTF-8'] = function(options) { - return new UTF8Decoder(options); - }; + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1]; + continue + } - // - // 10. Legacy single-byte encodings - // + var next = str[index]; + var prefix = res[2]; + var name = res[3]; + var capture = res[4]; + var group = res[5]; + var modifier = res[6]; + var asterisk = res[7]; - // 10.1 single-byte decoder - /** - * @constructor - * @implements {Decoder} - * @param {!Array.} index The encoding index. - * @param {{fatal: boolean}} options - */ - function SingleByteDecoder(index, options) { - var fatal = options.fatal; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream, return finished. - if (bite === end_of_stream) - return finished; + // Push the current path onto the tokens. + if (path) { + tokens.push(path); + path = ''; + } - // 2. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + var partial = prefix != null && next != null && next !== prefix; + var repeat = modifier === '+' || modifier === '*'; + var optional = modifier === '?' || modifier === '*'; + var delimiter = res[2] || defaultDelimiter; + var pattern = capture || group; - // 3. Let code point be the index code point for byte − 0x80 in - // index single-byte. - var code_point = index[bite - 0x80]; + tokens.push({ + name: name || key++, + prefix: prefix || '', + delimiter: delimiter, + optional: optional, + repeat: repeat, + partial: partial, + asterisk: !!asterisk, + pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') + }); + } - // 4. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + // Match any characters still remaining. + if (index < str.length) { + path += str.substr(index); + } - // 5. Return a code point whose value is code point. - return code_point; - }; + // If the path exists, push it onto the end. + if (path) { + tokens.push(path); } - // 10.2 single-byte encoder - /** - * @constructor - * @implements {Encoder} - * @param {!Array.} index The encoding index. - * @param {{fatal: boolean}} options - */ - function SingleByteEncoder(index, options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; + return tokens + } - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + /** + * Compile a string to a template function for the path. + * + * @param {string} str + * @param {Object=} options + * @return {!function(Object=, Object=)} + */ + function compile (str, options) { + return tokensToFunction(parse(str, options), options) + } - // 3. Let pointer be the index pointer for code point in index - // single-byte. - var pointer = indexPointerFor(code_point, index); + /** + * Prettier encoding of URI path segments. + * + * @param {string} + * @return {string} + */ + function encodeURIComponentPretty (str) { + return encodeURI(str).replace(/[\/?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } - // 4. If pointer is null, return error with code point. - if (pointer === null) - encoderError(code_point); + /** + * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. + * + * @param {string} + * @return {string} + */ + function encodeAsterisk (str) { + return encodeURI(str).replace(/[?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } - // 5. Return a byte whose value is pointer + 0x80. - return pointer + 0x80; - }; + /** + * Expose a method for transforming tokens into the path function. + */ + function tokensToFunction (tokens, options) { + // Compile all the tokens into regexps. + var matches = new Array(tokens.length); + + // Compile all the patterns before compilation. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] === 'object') { + matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options)); + } } - (function() { - if (!('encoding-indexes' in global)) - return; - encodings.forEach(function(category) { - if (category.heading !== 'Legacy single-byte encodings') - return; - category.encodings.forEach(function(encoding) { - var name = encoding.name; - var idx = index(name.toLowerCase()); - /** @param {{fatal: boolean}} options */ - decoders[name] = function(options) { - return new SingleByteDecoder(idx, options); - }; - /** @param {{fatal: boolean}} options */ - encoders[name] = function(options) { - return new SingleByteEncoder(idx, options); - }; - }); - }); - }()); + return function (obj, opts) { + var path = ''; + var data = obj || {}; + var options = opts || {}; + var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent; - // - // 11. Legacy multi-byte Chinese (simplified) encodings - // + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; - // 11.1 gbk + if (typeof token === 'string') { + path += token; - // 11.1.1 gbk decoder - // gbk's decoder is gb18030's decoder. - /** @param {{fatal: boolean}} options */ - decoders['GBK'] = function(options) { - return new GB18030Decoder(options); - }; + continue + } - // 11.1.2 gbk encoder - // gbk's encoder is gb18030's encoder with its gbk flag set. - /** @param {{fatal: boolean}} options */ - encoders['GBK'] = function(options) { - return new GB18030Encoder(options, true); - }; + var value = data[token.name]; + var segment; - // 11.2 gb18030 + if (value == null) { + if (token.optional) { + // Prepend partial segment prefixes. + if (token.partial) { + path += token.prefix; + } - // 11.2.1 gb18030 decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ - function GB18030Decoder(options) { - var fatal = options.fatal; - // gb18030's decoder has an associated gb18030 first, gb18030 - // second, and gb18030 third (all initially 0x00). - var /** @type {number} */ gb18030_first = 0x00, - /** @type {number} */ gb18030_second = 0x00, - /** @type {number} */ gb18030_third = 0x00; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and gb18030 first, gb18030 - // second, and gb18030 third are 0x00, return finished. - if (bite === end_of_stream && gb18030_first === 0x00 && - gb18030_second === 0x00 && gb18030_third === 0x00) { - return finished; - } - // 2. If byte is end-of-stream, and gb18030 first, gb18030 - // second, or gb18030 third is not 0x00, set gb18030 first, - // gb18030 second, and gb18030 third to 0x00, and return error. - if (bite === end_of_stream && - (gb18030_first !== 0x00 || gb18030_second !== 0x00 || - gb18030_third !== 0x00)) { - gb18030_first = 0x00; - gb18030_second = 0x00; - gb18030_third = 0x00; - decoderError(fatal); + continue + } else { + throw new TypeError('Expected "' + token.name + '" to be defined') + } } - var code_point; - // 3. If gb18030 third is not 0x00, run these substeps: - if (gb18030_third !== 0x00) { - // 1. Let code point be null. - code_point = null; - // 2. If byte is in the range 0x30 to 0x39, inclusive, set - // code point to the index gb18030 ranges code point for - // (((gb18030 first − 0x81) × 10 + gb18030 second − 0x30) × - // 126 + gb18030 third − 0x81) × 10 + byte − 0x30. - if (inRange(bite, 0x30, 0x39)) { - code_point = indexGB18030RangesCodePointFor( - (((gb18030_first - 0x81) * 10 + gb18030_second - 0x30) * 126 + - gb18030_third - 0x81) * 10 + bite - 0x30); + + if (isarray(value)) { + if (!token.repeat) { + throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') } - // 3. Let buffer be a byte sequence consisting of gb18030 - // second, gb18030 third, and byte, in order. - var buffer = [gb18030_second, gb18030_third, bite]; + if (value.length === 0) { + if (token.optional) { + continue + } else { + throw new TypeError('Expected "' + token.name + '" to not be empty') + } + } - // 4. Set gb18030 first, gb18030 second, and gb18030 third to - // 0x00. - gb18030_first = 0x00; - gb18030_second = 0x00; - gb18030_third = 0x00; + for (var j = 0; j < value.length; j++) { + segment = encode(value[j]); - // 5. If code point is null, prepend buffer to stream and - // return error. - if (code_point === null) { - stream.prepend(buffer); - return decoderError(fatal); + if (!matches[i].test(segment)) { + throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') + } + + path += (j === 0 ? token.prefix : token.delimiter) + segment; } - // 6. Return a code point whose value is code point. - return code_point; + continue } - // 4. If gb18030 second is not 0x00, run these substeps: - if (gb18030_second !== 0x00) { - - // 1. If byte is in the range 0x81 to 0xFE, inclusive, set - // gb18030 third to byte and return continue. - if (inRange(bite, 0x81, 0xFE)) { - gb18030_third = bite; - return null; - } + segment = token.asterisk ? encodeAsterisk(value) : encode(value); - // 2. Prepend gb18030 second followed by byte to stream, set - // gb18030 first and gb18030 second to 0x00, and return error. - stream.prepend([gb18030_second, bite]); - gb18030_first = 0x00; - gb18030_second = 0x00; - return decoderError(fatal); + if (!matches[i].test(segment)) { + throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') } - // 5. If gb18030 first is not 0x00, run these substeps: - if (gb18030_first !== 0x00) { + path += token.prefix + segment; + } + + return path + } + } + + /** + * Escape a regular expression string. + * + * @param {string} str + * @return {string} + */ + function escapeString (str) { + return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') + } - // 1. If byte is in the range 0x30 to 0x39, inclusive, set - // gb18030 second to byte and return continue. - if (inRange(bite, 0x30, 0x39)) { - gb18030_second = bite; - return null; - } + /** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {string} group + * @return {string} + */ + function escapeGroup (group) { + return group.replace(/([=!:$\/()])/g, '\\$1') + } - // 2. Let lead be gb18030 first, let pointer be null, and set - // gb18030 first to 0x00. - var lead = gb18030_first; - var pointer = null; - gb18030_first = 0x00; + /** + * Attach the keys as a property of the regexp. + * + * @param {!RegExp} re + * @param {Array} keys + * @return {!RegExp} + */ + function attachKeys (re, keys) { + re.keys = keys; + return re + } - // 3. Let offset be 0x40 if byte is less than 0x7F and 0x41 - // otherwise. - var offset = bite < 0x7F ? 0x40 : 0x41; + /** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {string} + */ + function flags (options) { + return options && options.sensitive ? '' : 'i' + } - // 4. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 - // to 0xFE, inclusive, set pointer to (lead − 0x81) × 190 + - // (byte − offset). - if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFE)) - pointer = (lead - 0x81) * 190 + (bite - offset); + /** + * Pull out keys from a regexp. + * + * @param {!RegExp} path + * @param {!Array} keys + * @return {!RegExp} + */ + function regexpToRegexp (path, keys) { + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g); - // 5. Let code point be null if pointer is null and the index - // code point for pointer in index gb18030 otherwise. - code_point = pointer === null ? null : - indexCodePointFor(pointer, index('gb18030')); + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + prefix: null, + delimiter: null, + optional: false, + repeat: false, + partial: false, + asterisk: false, + pattern: null + }); + } + } - // 6. If code point is null and byte is an ASCII byte, prepend - // byte to stream. - if (code_point === null && isASCIIByte(bite)) - stream.prepend(bite); + return attachKeys(path, keys) + } - // 7. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + /** + * Transform an array into a regexp. + * + * @param {!Array} path + * @param {Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function arrayToRegexp (path, keys, options) { + var parts = []; - // 8. Return a code point whose value is code point. - return code_point; - } + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source); + } - // 6. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); - // 7. If byte is 0x80, return code point U+20AC. - if (bite === 0x80) - return 0x20AC; + return attachKeys(regexp, keys) + } - // 8. If byte is in the range 0x81 to 0xFE, inclusive, set - // gb18030 first to byte and return continue. - if (inRange(bite, 0x81, 0xFE)) { - gb18030_first = bite; - return null; - } + /** + * Create a path regexp from string input. + * + * @param {string} path + * @param {!Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function stringToRegexp (path, keys, options) { + return tokensToRegExp(parse(path, options), keys, options) + } - // 9. Return error. - return decoderError(fatal); - }; + /** + * Expose a function for taking tokens and returning a RegExp. + * + * @param {!Array} tokens + * @param {(Array|Object)=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function tokensToRegExp (tokens, keys, options) { + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys || options); + keys = []; } - // 11.2.2 gb18030 encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - * @param {boolean=} gbk_flag - */ - function GB18030Encoder(options, gbk_flag) { - options.fatal; - // gb18030's decoder has an associated gbk flag (initially unset). - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; + options = options || {}; - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + var strict = options.strict; + var end = options.end !== false; + var route = ''; - // 3. If code point is U+E5E5, return error with code point. - if (code_point === 0xE5E5) - return encoderError(code_point); + // Iterate over the tokens and create our regexp string. + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; - // 4. If the gbk flag is set and code point is U+20AC, return - // byte 0x80. - if (gbk_flag && code_point === 0x20AC) - return 0x80; + if (typeof token === 'string') { + route += escapeString(token); + } else { + var prefix = escapeString(token.prefix); + var capture = '(?:' + token.pattern + ')'; - // 5. Let pointer be the index pointer for code point in index - // gb18030. - var pointer = indexPointerFor(code_point, index('gb18030')); + keys.push(token); - // 6. If pointer is not null, run these substeps: - if (pointer !== null) { + if (token.repeat) { + capture += '(?:' + prefix + capture + ')*'; + } - // 1. Let lead be floor(pointer / 190) + 0x81. - var lead = floor(pointer / 190) + 0x81; + if (token.optional) { + if (!token.partial) { + capture = '(?:' + prefix + '(' + capture + '))?'; + } else { + capture = prefix + '(' + capture + ')?'; + } + } else { + capture = prefix + '(' + capture + ')'; + } - // 2. Let trail be pointer % 190. - var trail = pointer % 190; + route += capture; + } + } - // 3. Let offset be 0x40 if trail is less than 0x3F and 0x41 otherwise. - var offset = trail < 0x3F ? 0x40 : 0x41; + var delimiter = escapeString(options.delimiter || '/'); + var endsWithDelimiter = route.slice(-delimiter.length) === delimiter; - // 4. Return two bytes whose values are lead and trail + offset. - return [lead, trail + offset]; - } + // In non-strict mode we allow a slash at the end of match. If the path to + // match already ends with a slash, we remove it for consistency. The slash + // is valid at the end of a path match, not in the middle. This is important + // in non-ending mode, where "/test/" shouldn't match "/test//route". + if (!strict) { + route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?'; + } - // 7. If gbk flag is set, return error with code point. - if (gbk_flag) - return encoderError(code_point); + if (end) { + route += '$'; + } else { + // In non-ending mode, we need the capturing groups to match as much as + // possible by using a positive lookahead to the end or next path segment. + route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)'; + } - // 8. Set pointer to the index gb18030 ranges pointer for code - // point. - pointer = indexGB18030RangesPointerFor(code_point); + return attachKeys(new RegExp('^' + route, flags(options)), keys) + } + + /** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(string|RegExp|Array)} path + * @param {(Array|Object)=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function pathToRegexp (path, keys, options) { + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys || options); + keys = []; + } - // 9. Let byte1 be floor(pointer / 10 / 126 / 10). - var byte1 = floor(pointer / 10 / 126 / 10); + options = options || {}; - // 10. Set pointer to pointer − byte1 × 10 × 126 × 10. - pointer = pointer - byte1 * 10 * 126 * 10; + if (path instanceof RegExp) { + return regexpToRegexp(path, /** @type {!Array} */ (keys)) + } - // 11. Let byte2 be floor(pointer / 10 / 126). - var byte2 = floor(pointer / 10 / 126); + if (isarray(path)) { + return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options) + } - // 12. Set pointer to pointer − byte2 × 10 × 126. - pointer = pointer - byte2 * 10 * 126; + return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options) + } - // 13. Let byte3 be floor(pointer / 10). - var byte3 = floor(pointer / 10); + },{"isarray":149}],149:[function(require,module,exports){ + module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; + }; - // 14. Let byte4 be pointer − byte3 × 10. - var byte4 = pointer - byte3 * 10; + },{}],150:[function(require,module,exports){ + module.exports = { + stdout: false, + stderr: false + }; - // 15. Return four bytes whose values are byte1 + 0x81, byte2 + - // 0x30, byte3 + 0x81, byte4 + 0x30. - return [byte1 + 0x81, - byte2 + 0x30, - byte3 + 0x81, - byte4 + 0x30]; - }; - } + },{}],151:[function(require,module,exports){ + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.typeDetect = factory()); + }(this, (function () { + /* ! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + var promiseExists = typeof Promise === 'function'; - /** @param {{fatal: boolean}} options */ - encoders['gb18030'] = function(options) { - return new GB18030Encoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['gb18030'] = function(options) { - return new GB18030Decoder(options); - }; + /* eslint-disable no-undef */ + var globalObject = typeof self === 'object' ? self : global; // eslint-disable-line id-blacklist + var symbolExists = typeof Symbol !== 'undefined'; + var mapExists = typeof Map !== 'undefined'; + var setExists = typeof Set !== 'undefined'; + var weakMapExists = typeof WeakMap !== 'undefined'; + var weakSetExists = typeof WeakSet !== 'undefined'; + var dataViewExists = typeof DataView !== 'undefined'; + var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; + var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; + var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; + var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; + var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); + var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); + var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; + var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); + var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; + var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); + var toStringLeftSliceLength = 8; + var toStringRightSliceLength = -1; + /** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ + function typeDetect(obj) { + /* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */ + var typeofObj = typeof obj; + if (typeofObj !== 'object') { + return typeofObj; + } - // - // 12. Legacy multi-byte Chinese (traditional) encodings - // + /* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */ + if (obj === null) { + return 'null'; + } - // 12.1 Big5 + /* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */ + if (obj === globalObject) { + return 'global'; + } - // 12.1.1 Big5 decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options + /* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) */ - function Big5Decoder(options) { - var fatal = options.fatal; - // Big5's decoder has an associated Big5 lead (initially 0x00). - var /** @type {number} */ Big5_lead = 0x00; + if ( + Array.isArray(obj) && + (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) + ) { + return 'Array'; + } - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. + // Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if (typeof window === 'object' && window !== null) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and Big5 lead is not 0x00, set - // Big5 lead to 0x00 and return error. - if (bite === end_of_stream && Big5_lead !== 0x00) { - Big5_lead = 0x00; - return decoderError(fatal); - } - - // 2. If byte is end-of-stream and Big5 lead is 0x00, return - // finished. - if (bite === end_of_stream && Big5_lead === 0x00) - return finished; - - // 3. If Big5 lead is not 0x00, let lead be Big5 lead, let - // pointer be null, set Big5 lead to 0x00, and then run these - // substeps: - if (Big5_lead !== 0x00) { - var lead = Big5_lead; - var pointer = null; - Big5_lead = 0x00; - - // 1. Let offset be 0x40 if byte is less than 0x7F and 0x62 - // otherwise. - var offset = bite < 0x7F ? 0x40 : 0x62; - - // 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1 - // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 + - // (byte − offset). - if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0xA1, 0xFE)) - pointer = (lead - 0x81) * 157 + (bite - offset); - - // 3. If there is a row in the table below whose first column - // is pointer, return the two code points listed in its second - // column - // Pointer | Code points - // --------+-------------- - // 1133 | U+00CA U+0304 - // 1135 | U+00CA U+030C - // 1164 | U+00EA U+0304 - // 1166 | U+00EA U+030C - switch (pointer) { - case 1133: return [0x00CA, 0x0304]; - case 1135: return [0x00CA, 0x030C]; - case 1164: return [0x00EA, 0x0304]; - case 1166: return [0x00EA, 0x030C]; - } - - // 4. Let code point be null if pointer is null and the index - // code point for pointer in index Big5 otherwise. - var code_point = (pointer === null) ? null : - indexCodePointFor(pointer, index('big5')); + if (typeof window.location === 'object' && obj === window.location) { + return 'Location'; + } - // 5. If code point is null and byte is an ASCII byte, prepend - // byte to stream. - if (code_point === null && isASCIIByte(bite)) - stream.prepend(bite); + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */ + if (typeof window.document === 'object' && obj === window.document) { + return 'Document'; + } - // 6. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + if (typeof window.navigator === 'object') { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */ + if (typeof window.navigator.mimeTypes === 'object' && + obj === window.navigator.mimeTypes) { + return 'MimeTypeArray'; + } - // 7. Return a code point whose value is code point. - return code_point; + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */ + if (typeof window.navigator.plugins === 'object' && + obj === window.navigator.plugins) { + return 'PluginArray'; } + } - // 4. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + if ((typeof window.HTMLElement === 'function' || + typeof window.HTMLElement === 'object') && + obj instanceof window.HTMLElement) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */ + if (obj.tagName === 'BLOCKQUOTE') { + return 'HTMLQuoteElement'; + } - // 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5 - // lead to byte and return continue. - if (inRange(bite, 0x81, 0xFE)) { - Big5_lead = bite; - return null; + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TD') { + return 'HTMLTableDataCellElement'; } - // 6. Return error. - return decoderError(fatal); - }; + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TH') { + return 'HTMLTableHeaderCellElement'; + } + } } - // 12.1.2 Big5 encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ - function Big5Encoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; - - // 3. Let pointer be the index Big5 pointer for code point. - var pointer = indexBig5PointerFor(code_point); - - // 4. If pointer is null, return error with code point. - if (pointer === null) - return encoderError(code_point); + /* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */ + var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); + if (typeof stringTag === 'string') { + return stringTag; + } - // 5. Let lead be floor(pointer / 157) + 0x81. - var lead = floor(pointer / 157) + 0x81; + var objPrototype = Object.getPrototypeOf(obj); + /* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */ + if (objPrototype === RegExp.prototype) { + return 'RegExp'; + } - // 6. If lead is less than 0xA1, return error with code point. - if (lead < 0xA1) - return encoderError(code_point); + /* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */ + if (objPrototype === Date.prototype) { + return 'Date'; + } - // 7. Let trail be pointer % 157. - var trail = pointer % 157; + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */ + if (promiseExists && objPrototype === Promise.prototype) { + return 'Promise'; + } - // 8. Let offset be 0x40 if trail is less than 0x3F and 0x62 - // otherwise. - var offset = trail < 0x3F ? 0x40 : 0x62; + /* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */ + if (setExists && objPrototype === Set.prototype) { + return 'Set'; + } - // Return two bytes whose values are lead and trail + offset. - return [lead, trail + offset]; - }; + /* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */ + if (mapExists && objPrototype === Map.prototype) { + return 'Map'; } - /** @param {{fatal: boolean}} options */ - encoders['Big5'] = function(options) { - return new Big5Encoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['Big5'] = function(options) { - return new Big5Decoder(options); - }; + /* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */ + if (weakSetExists && objPrototype === WeakSet.prototype) { + return 'WeakSet'; + } + /* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */ + if (weakMapExists && objPrototype === WeakMap.prototype) { + return 'WeakMap'; + } - // - // 13. Legacy multi-byte Japanese encodings - // + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */ + if (dataViewExists && objPrototype === DataView.prototype) { + return 'DataView'; + } - // 13.1 euc-jp + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */ + if (mapExists && objPrototype === mapIteratorPrototype) { + return 'Map Iterator'; + } - // 13.1.1 euc-jp decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" */ - function EUCJPDecoder(options) { - var fatal = options.fatal; - - // euc-jp's decoder has an associated euc-jp jis0212 flag - // (initially unset) and euc-jp lead (initially 0x00). - var /** @type {boolean} */ eucjp_jis0212_flag = false, - /** @type {number} */ eucjp_lead = 0x00; + if (setExists && objPrototype === setIteratorPrototype) { + return 'Set Iterator'; + } - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and euc-jp lead is not 0x00, set - // euc-jp lead to 0x00, and return error. - if (bite === end_of_stream && eucjp_lead !== 0x00) { - eucjp_lead = 0x00; - return decoderError(fatal); - } + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { + return 'Array Iterator'; + } - // 2. If byte is end-of-stream and euc-jp lead is 0x00, return - // finished. - if (bite === end_of_stream && eucjp_lead === 0x00) - return finished; + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (stringIteratorExists && objPrototype === stringIteratorPrototype) { + return 'String Iterator'; + } - // 3. If euc-jp lead is 0x8E and byte is in the range 0xA1 to - // 0xDF, inclusive, set euc-jp lead to 0x00 and return a code - // point whose value is 0xFF61 − 0xA1 + byte. - if (eucjp_lead === 0x8E && inRange(bite, 0xA1, 0xDF)) { - eucjp_lead = 0x00; - return 0xFF61 - 0xA1 + bite; - } + /* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */ + if (objPrototype === null) { + return 'Object'; + } - // 4. If euc-jp lead is 0x8F and byte is in the range 0xA1 to - // 0xFE, inclusive, set the euc-jp jis0212 flag, set euc-jp lead - // to byte, and return continue. - if (eucjp_lead === 0x8F && inRange(bite, 0xA1, 0xFE)) { - eucjp_jis0212_flag = true; - eucjp_lead = bite; - return null; - } + return Object + .prototype + .toString + .call(obj) + .slice(toStringLeftSliceLength, toStringRightSliceLength); + } - // 5. If euc-jp lead is not 0x00, let lead be euc-jp lead, set - // euc-jp lead to 0x00, and run these substeps: - if (eucjp_lead !== 0x00) { - var lead = eucjp_lead; - eucjp_lead = 0x00; + return typeDetect; - // 1. Let code point be null. - var code_point = null; + }))); - // 2. If lead and byte are both in the range 0xA1 to 0xFE, - // inclusive, set code point to the index code point for (lead - // − 0xA1) × 94 + byte − 0xA1 in index jis0208 if the euc-jp - // jis0212 flag is unset and in index jis0212 otherwise. - if (inRange(lead, 0xA1, 0xFE) && inRange(bite, 0xA1, 0xFE)) { - code_point = indexCodePointFor( - (lead - 0xA1) * 94 + (bite - 0xA1), - index(!eucjp_jis0212_flag ? 'jis0208' : 'jis0212')); - } + },{}]},{},[1]); - // 3. Unset the euc-jp jis0212 flag. - eucjp_jis0212_flag = false; + var sinon$1 = sinon; + sinon.leakThreshold; + sinon.assert; + sinon.serverPrototype; + sinon.getFakes; + sinon.createStubInstance; + sinon.inject; + sinon.mock; + sinon.reset; + sinon.resetBehavior; + sinon.resetHistory; + sinon.restore; + sinon.restoreContext; + sinon.replace; + sinon.define; + sinon.replaceGetter; + sinon.replaceSetter; + sinon.spy; + sinon.stub; + sinon.fake; + sinon.useFakeTimers; + sinon.verify; + sinon.verifyAndRestore; + sinon.useFakeServer; + sinon.useFakeXMLHttpRequest; + sinon.usingPromise; + sinon.createSandbox; + sinon.match; + sinon.restoreObject; + sinon.expectation; + sinon.defaultConfig; + sinon.timers; + sinon.xhr; + sinon.FakeXMLHttpRequest; + sinon.fakeServer; + sinon.fakeServerWithClock; + sinon.createFakeServer; + sinon.createFakeServerWithClock; + sinon.addBehavior; + sinon.promise; - // 4. If byte is not in the range 0xA1 to 0xFE, inclusive, - // prepend byte to stream. - if (!inRange(bite, 0xA1, 0xFE)) - stream.prepend(bite); + var SDKProductActionType; + (function (SDKProductActionType) { + SDKProductActionType[SDKProductActionType["Unknown"] = 0] = "Unknown"; + SDKProductActionType[SDKProductActionType["AddToCart"] = 1] = "AddToCart"; + SDKProductActionType[SDKProductActionType["RemoveFromCart"] = 2] = "RemoveFromCart"; + SDKProductActionType[SDKProductActionType["Checkout"] = 3] = "Checkout"; + SDKProductActionType[SDKProductActionType["CheckoutOption"] = 4] = "CheckoutOption"; + SDKProductActionType[SDKProductActionType["Click"] = 5] = "Click"; + SDKProductActionType[SDKProductActionType["ViewDetail"] = 6] = "ViewDetail"; + SDKProductActionType[SDKProductActionType["Purchase"] = 7] = "Purchase"; + SDKProductActionType[SDKProductActionType["Refund"] = 8] = "Refund"; + SDKProductActionType[SDKProductActionType["AddToWishlist"] = 9] = "AddToWishlist"; + SDKProductActionType[SDKProductActionType["RemoveFromWishlist"] = 10] = "RemoveFromWishlist"; + })(SDKProductActionType || (SDKProductActionType = {})); + var SDKIdentityTypeEnum; + (function (SDKIdentityTypeEnum) { + SDKIdentityTypeEnum["other"] = "other"; + SDKIdentityTypeEnum["customerId"] = "customerid"; + SDKIdentityTypeEnum["facebook"] = "facebook"; + SDKIdentityTypeEnum["twitter"] = "twitter"; + SDKIdentityTypeEnum["google"] = "google"; + SDKIdentityTypeEnum["microsoft"] = "microsoft"; + SDKIdentityTypeEnum["yahoo"] = "yahoo"; + SDKIdentityTypeEnum["email"] = "email"; + SDKIdentityTypeEnum["alias"] = "alias"; + SDKIdentityTypeEnum["facebookCustomAudienceId"] = "facebookcustomaudienceid"; + SDKIdentityTypeEnum["otherId2"] = "other2"; + SDKIdentityTypeEnum["otherId3"] = "other3"; + SDKIdentityTypeEnum["otherId4"] = "other4"; + SDKIdentityTypeEnum["otherId5"] = "other5"; + SDKIdentityTypeEnum["otherId6"] = "other6"; + SDKIdentityTypeEnum["otherId7"] = "other7"; + SDKIdentityTypeEnum["otherId8"] = "other8"; + SDKIdentityTypeEnum["otherId9"] = "other9"; + SDKIdentityTypeEnum["otherId10"] = "other10"; + SDKIdentityTypeEnum["mobileNumber"] = "mobile_number"; + SDKIdentityTypeEnum["phoneNumber2"] = "phone_number_2"; + SDKIdentityTypeEnum["phoneNumber3"] = "phone_number_3"; + })(SDKIdentityTypeEnum || (SDKIdentityTypeEnum = {})); + + var dist = {}; + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + (function (ApplicationInformationOsEnum) { + ApplicationInformationOsEnum["unknown"] = "Unknown"; + ApplicationInformationOsEnum["iOS"] = "IOS"; + ApplicationInformationOsEnum["android"] = "Android"; + ApplicationInformationOsEnum["windowsPhone"] = "WindowsPhone"; + ApplicationInformationOsEnum["mobileWeb"] = "MobileWeb"; + ApplicationInformationOsEnum["unityIOS"] = "UnityIOS"; + ApplicationInformationOsEnum["unityAndroid"] = "UnityAndroid"; + ApplicationInformationOsEnum["desktop"] = "Desktop"; + ApplicationInformationOsEnum["tvOS"] = "TVOS"; + ApplicationInformationOsEnum["roku"] = "Roku"; + ApplicationInformationOsEnum["outOfBand"] = "OutOfBand"; + ApplicationInformationOsEnum["alexa"] = "Alexa"; + ApplicationInformationOsEnum["smartTV"] = "SmartTV"; + ApplicationInformationOsEnum["fireTV"] = "FireTV"; + ApplicationInformationOsEnum["xbox"] = "Xbox"; + })(exports.ApplicationInformationOsEnum || (exports.ApplicationInformationOsEnum = {})); + (function (ApplicationStateTransitionEventEventTypeEnum) { + ApplicationStateTransitionEventEventTypeEnum["applicationStateTransition"] = "application_state_transition"; + })(exports.ApplicationStateTransitionEventEventTypeEnum || (exports.ApplicationStateTransitionEventEventTypeEnum = {})); + (function (ApplicationStateTransitionEventDataApplicationTransitionTypeEnum) { + ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationInitialized"] = "application_initialized"; + ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationExit"] = "application_exit"; + ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationBackground"] = "application_background"; + ApplicationStateTransitionEventDataApplicationTransitionTypeEnum["applicationForeground"] = "application_foreground"; + })(exports.ApplicationStateTransitionEventDataApplicationTransitionTypeEnum || (exports.ApplicationStateTransitionEventDataApplicationTransitionTypeEnum = {})); + (function (BatchEnvironmentEnum) { + BatchEnvironmentEnum["unknown"] = "unknown"; + BatchEnvironmentEnum["development"] = "development"; + BatchEnvironmentEnum["production"] = "production"; + })(exports.BatchEnvironmentEnum || (exports.BatchEnvironmentEnum = {})); + (function (BreadcrumbEventEventTypeEnum) { + BreadcrumbEventEventTypeEnum["breadcrumb"] = "breadcrumb"; + })(exports.BreadcrumbEventEventTypeEnum || (exports.BreadcrumbEventEventTypeEnum = {})); + (function (CommerceEventEventTypeEnum) { + CommerceEventEventTypeEnum["commerceEvent"] = "commerce_event"; + })(exports.CommerceEventEventTypeEnum || (exports.CommerceEventEventTypeEnum = {})); + (function (CommerceEventDataCustomEventTypeEnum) { + CommerceEventDataCustomEventTypeEnum["addToCart"] = "add_to_cart"; + CommerceEventDataCustomEventTypeEnum["removeFromCart"] = "remove_from_cart"; + CommerceEventDataCustomEventTypeEnum["checkout"] = "checkout"; + CommerceEventDataCustomEventTypeEnum["checkoutOption"] = "checkout_option"; + CommerceEventDataCustomEventTypeEnum["click"] = "click"; + CommerceEventDataCustomEventTypeEnum["viewDetail"] = "view_detail"; + CommerceEventDataCustomEventTypeEnum["purchase"] = "purchase"; + CommerceEventDataCustomEventTypeEnum["refund"] = "refund"; + CommerceEventDataCustomEventTypeEnum["promotionView"] = "promotion_view"; + CommerceEventDataCustomEventTypeEnum["promotionClick"] = "promotion_click"; + CommerceEventDataCustomEventTypeEnum["addToWishlist"] = "add_to_wishlist"; + CommerceEventDataCustomEventTypeEnum["removeFromWishlist"] = "remove_from_wishlist"; + CommerceEventDataCustomEventTypeEnum["impression"] = "impression"; + })(exports.CommerceEventDataCustomEventTypeEnum || (exports.CommerceEventDataCustomEventTypeEnum = {})); + (function (CrashReportEventEventTypeEnum) { + CrashReportEventEventTypeEnum["crashReport"] = "crash_report"; + })(exports.CrashReportEventEventTypeEnum || (exports.CrashReportEventEventTypeEnum = {})); + (function (CustomEventEventTypeEnum) { + CustomEventEventTypeEnum["customEvent"] = "custom_event"; + })(exports.CustomEventEventTypeEnum || (exports.CustomEventEventTypeEnum = {})); + (function (CustomEventDataCustomEventTypeEnum) { + CustomEventDataCustomEventTypeEnum["navigation"] = "navigation"; + CustomEventDataCustomEventTypeEnum["location"] = "location"; + CustomEventDataCustomEventTypeEnum["search"] = "search"; + CustomEventDataCustomEventTypeEnum["transaction"] = "transaction"; + CustomEventDataCustomEventTypeEnum["userContent"] = "user_content"; + CustomEventDataCustomEventTypeEnum["userPreference"] = "user_preference"; + CustomEventDataCustomEventTypeEnum["social"] = "social"; + CustomEventDataCustomEventTypeEnum["media"] = "media"; + CustomEventDataCustomEventTypeEnum["other"] = "other"; + CustomEventDataCustomEventTypeEnum["unknown"] = "unknown"; + })(exports.CustomEventDataCustomEventTypeEnum || (exports.CustomEventDataCustomEventTypeEnum = {})); + (function (DeviceCurrentStateDeviceOrientationEnum) { + DeviceCurrentStateDeviceOrientationEnum["portrait"] = "portrait"; + DeviceCurrentStateDeviceOrientationEnum["portraitUpsideDown"] = "portrait_upside_down"; + DeviceCurrentStateDeviceOrientationEnum["landscape"] = "landscape"; + DeviceCurrentStateDeviceOrientationEnum["landscapeLeft"] = "LandscapeLeft"; + DeviceCurrentStateDeviceOrientationEnum["landscapeRight"] = "LandscapeRight"; + DeviceCurrentStateDeviceOrientationEnum["faceUp"] = "FaceUp"; + DeviceCurrentStateDeviceOrientationEnum["faceDown"] = "FaceDown"; + DeviceCurrentStateDeviceOrientationEnum["square"] = "Square"; + })(exports.DeviceCurrentStateDeviceOrientationEnum || (exports.DeviceCurrentStateDeviceOrientationEnum = {})); + (function (DeviceCurrentStateStatusBarOrientationEnum) { + DeviceCurrentStateStatusBarOrientationEnum["portrait"] = "portrait"; + DeviceCurrentStateStatusBarOrientationEnum["portraitUpsideDown"] = "portrait_upside_down"; + DeviceCurrentStateStatusBarOrientationEnum["landscape"] = "landscape"; + DeviceCurrentStateStatusBarOrientationEnum["landscapeLeft"] = "LandscapeLeft"; + DeviceCurrentStateStatusBarOrientationEnum["landscapeRight"] = "LandscapeRight"; + DeviceCurrentStateStatusBarOrientationEnum["faceUp"] = "FaceUp"; + DeviceCurrentStateStatusBarOrientationEnum["faceDown"] = "FaceDown"; + DeviceCurrentStateStatusBarOrientationEnum["square"] = "Square"; + })(exports.DeviceCurrentStateStatusBarOrientationEnum || (exports.DeviceCurrentStateStatusBarOrientationEnum = {})); + (function (DeviceInformationPlatformEnum) { + DeviceInformationPlatformEnum["iOS"] = "iOS"; + DeviceInformationPlatformEnum["android"] = "Android"; + DeviceInformationPlatformEnum["web"] = "web"; + DeviceInformationPlatformEnum["desktop"] = "desktop"; + DeviceInformationPlatformEnum["tvOS"] = "tvOS"; + DeviceInformationPlatformEnum["roku"] = "roku"; + DeviceInformationPlatformEnum["outOfBand"] = "out_of_band"; + DeviceInformationPlatformEnum["smartTV"] = "smart_tv"; + DeviceInformationPlatformEnum["xbox"] = "xbox"; + })(exports.DeviceInformationPlatformEnum || (exports.DeviceInformationPlatformEnum = {})); + (function (EventTypeEnum) { + EventTypeEnum["unknown"] = "unknown"; + EventTypeEnum["sessionStart"] = "session_start"; + EventTypeEnum["sessionEnd"] = "session_end"; + EventTypeEnum["screenView"] = "screen_view"; + EventTypeEnum["customEvent"] = "custom_event"; + EventTypeEnum["crashReport"] = "crash_report"; + EventTypeEnum["optOut"] = "opt_out"; + EventTypeEnum["firstRun"] = "first_run"; + EventTypeEnum["preAttribution"] = "pre_attribution"; + EventTypeEnum["pushRegistration"] = "push_registration"; + EventTypeEnum["applicationStateTransition"] = "application_state_transition"; + EventTypeEnum["pushMessage"] = "push_message"; + EventTypeEnum["networkPerformance"] = "network_performance"; + EventTypeEnum["breadcrumb"] = "breadcrumb"; + EventTypeEnum["profile"] = "profile"; + EventTypeEnum["pushReaction"] = "push_reaction"; + EventTypeEnum["commerceEvent"] = "commerce_event"; + EventTypeEnum["userAttributeChange"] = "user_attribute_change"; + EventTypeEnum["userIdentityChange"] = "user_identity_change"; + EventTypeEnum["uninstall"] = "uninstall"; + EventTypeEnum["validationResult"] = "validation_result"; + })(exports.EventTypeEnum || (exports.EventTypeEnum = {})); + (function (IdentityTypeEnum) { + IdentityTypeEnum["other"] = "other"; + IdentityTypeEnum["customerId"] = "customer_id"; + IdentityTypeEnum["facebook"] = "facebook"; + IdentityTypeEnum["twitter"] = "twitter"; + IdentityTypeEnum["google"] = "google"; + IdentityTypeEnum["microsoft"] = "microsoft"; + IdentityTypeEnum["yahoo"] = "yahoo"; + IdentityTypeEnum["email"] = "email"; + IdentityTypeEnum["alias"] = "alias"; + IdentityTypeEnum["facebookCustomAudienceId"] = "facebook_custom_audience_id"; + IdentityTypeEnum["otherId2"] = "other_id_2"; + IdentityTypeEnum["otherId3"] = "other_id_3"; + IdentityTypeEnum["otherId4"] = "other_id_4"; + IdentityTypeEnum["otherId5"] = "other_id_5"; + IdentityTypeEnum["otherId6"] = "other_id_6"; + IdentityTypeEnum["otherId7"] = "other_id_7"; + IdentityTypeEnum["otherId8"] = "other_id_8"; + IdentityTypeEnum["otherId9"] = "other_id_9"; + IdentityTypeEnum["otherId10"] = "other_id_10"; + IdentityTypeEnum["mobileNumber"] = "mobile_number"; + IdentityTypeEnum["phoneNumber2"] = "phone_number_2"; + IdentityTypeEnum["phoneNumber3"] = "phone_number_3"; + })(exports.IdentityTypeEnum || (exports.IdentityTypeEnum = {})); + (function (NetworkPerformanceEventEventTypeEnum) { + NetworkPerformanceEventEventTypeEnum["networkPerformance"] = "network_performance"; + })(exports.NetworkPerformanceEventEventTypeEnum || (exports.NetworkPerformanceEventEventTypeEnum = {})); + (function (OptOutEventEnum) { + OptOutEventEnum["optOut"] = "opt_out"; + })(exports.OptOutEventEnum || (exports.OptOutEventEnum = {})); + (function (ProductActionActionEnum) { + ProductActionActionEnum["unknown"] = "unknown"; + ProductActionActionEnum["addToCart"] = "add_to_cart"; + ProductActionActionEnum["removeFromCart"] = "remove_from_cart"; + ProductActionActionEnum["checkout"] = "checkout"; + ProductActionActionEnum["checkoutOption"] = "checkout_option"; + ProductActionActionEnum["click"] = "click"; + ProductActionActionEnum["viewDetail"] = "view_detail"; + ProductActionActionEnum["purchase"] = "purchase"; + ProductActionActionEnum["refund"] = "refund"; + ProductActionActionEnum["addToWishlist"] = "add_to_wishlist"; + ProductActionActionEnum["removeFromWishlist"] = "remove_from_wish_list"; + })(exports.ProductActionActionEnum || (exports.ProductActionActionEnum = {})); + (function (ProfileEventEventTypeEnum) { + ProfileEventEventTypeEnum["profile"] = "profile"; + })(exports.ProfileEventEventTypeEnum || (exports.ProfileEventEventTypeEnum = {})); + (function (ProfileEventDataProfileEventTypeEnum) { + ProfileEventDataProfileEventTypeEnum["signup"] = "signup"; + ProfileEventDataProfileEventTypeEnum["login"] = "login"; + ProfileEventDataProfileEventTypeEnum["logout"] = "logout"; + ProfileEventDataProfileEventTypeEnum["update"] = "update"; + ProfileEventDataProfileEventTypeEnum["delete"] = "delete"; + })(exports.ProfileEventDataProfileEventTypeEnum || (exports.ProfileEventDataProfileEventTypeEnum = {})); + (function (PromotionActionActionEnum) { + PromotionActionActionEnum["view"] = "view"; + PromotionActionActionEnum["click"] = "click"; + })(exports.PromotionActionActionEnum || (exports.PromotionActionActionEnum = {})); + (function (PushMessageEventEventTypeEnum) { + PushMessageEventEventTypeEnum["pushMessage"] = "push_message"; + })(exports.PushMessageEventEventTypeEnum || (exports.PushMessageEventEventTypeEnum = {})); + (function (PushMessageEventDataPushMessageTypeEnum) { + PushMessageEventDataPushMessageTypeEnum["sent"] = "sent"; + PushMessageEventDataPushMessageTypeEnum["received"] = "received"; + PushMessageEventDataPushMessageTypeEnum["action"] = "action"; + })(exports.PushMessageEventDataPushMessageTypeEnum || (exports.PushMessageEventDataPushMessageTypeEnum = {})); + (function (PushMessageEventDataApplicationStateEnum) { + PushMessageEventDataApplicationStateEnum["notRunning"] = "not_running"; + PushMessageEventDataApplicationStateEnum["background"] = "background"; + PushMessageEventDataApplicationStateEnum["foreground"] = "foreground"; + })(exports.PushMessageEventDataApplicationStateEnum || (exports.PushMessageEventDataApplicationStateEnum = {})); + (function (PushMessageEventDataPushMessageBehaviorEnum) { + PushMessageEventDataPushMessageBehaviorEnum["received"] = "Received"; + PushMessageEventDataPushMessageBehaviorEnum["directOpen"] = "DirectOpen"; + PushMessageEventDataPushMessageBehaviorEnum["read"] = "Read"; + PushMessageEventDataPushMessageBehaviorEnum["influencedOpen"] = "InfluencedOpen"; + PushMessageEventDataPushMessageBehaviorEnum["displayed"] = "Displayed"; + })(exports.PushMessageEventDataPushMessageBehaviorEnum || (exports.PushMessageEventDataPushMessageBehaviorEnum = {})); + (function (PushRegistrationEventEventTypeEnum) { + PushRegistrationEventEventTypeEnum["pushRegistration"] = "push_registration"; + })(exports.PushRegistrationEventEventTypeEnum || (exports.PushRegistrationEventEventTypeEnum = {})); + (function (SessionEndEventEventTypeEnum) { + SessionEndEventEventTypeEnum["sessionEnd"] = "session_end"; + })(exports.SessionEndEventEventTypeEnum || (exports.SessionEndEventEventTypeEnum = {})); + (function (SessionStartEventEventTypeEnum) { + SessionStartEventEventTypeEnum["sessionStart"] = "session_start"; + })(exports.SessionStartEventEventTypeEnum || (exports.SessionStartEventEventTypeEnum = {})); + (function (SourceInformationChannelEnum) { + SourceInformationChannelEnum["native"] = "native"; + SourceInformationChannelEnum["javascript"] = "javascript"; + SourceInformationChannelEnum["pixel"] = "pixel"; + SourceInformationChannelEnum["desktop"] = "desktop"; + SourceInformationChannelEnum["partner"] = "partner"; + SourceInformationChannelEnum["serverToServer"] = "server_to_server"; + })(exports.SourceInformationChannelEnum || (exports.SourceInformationChannelEnum = {})); + (function (UserAttributeChangeEventEventTypeEnum) { + UserAttributeChangeEventEventTypeEnum["userAttributeChange"] = "user_attribute_change"; + })(exports.UserAttributeChangeEventEventTypeEnum || (exports.UserAttributeChangeEventEventTypeEnum = {})); + (function (UserIdentityChangeEventEventTypeEnum) { + UserIdentityChangeEventEventTypeEnum["userIdentityChange"] = "user_identity_change"; + })(exports.UserIdentityChangeEventEventTypeEnum || (exports.UserIdentityChangeEventEventTypeEnum = {})); + } (dist)); + + var _TriggerUploadType; + var MessageType$1 = { + SessionStart: 1, + SessionEnd: 2, + PageView: 3, + PageEvent: 4, + CrashReport: 5, + OptOut: 6, + AppStateTransition: 10, + Profile: 14, + Commerce: 16, + Media: 20, + UserAttributeChange: 17, + UserIdentityChange: 18 + }; - // 5. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + // Dictionary that contains MessageTypes that will + // trigger an immediate upload. + var TriggerUploadType = (_TriggerUploadType = {}, _defineProperty(_TriggerUploadType, MessageType$1.Commerce, 1), _defineProperty(_TriggerUploadType, MessageType$1.UserAttributeChange, 1), _defineProperty(_TriggerUploadType, MessageType$1.UserIdentityChange, 1), _TriggerUploadType); + var EventType = { + Unknown: 0, + Navigation: 1, + Location: 2, + Search: 3, + Transaction: 4, + UserContent: 5, + UserPreference: 6, + Social: 7, + Other: 8, + Media: 9, + getName: function getName(id) { + switch (id) { + case EventType.Unknown: + return 'Unknown'; + case EventType.Navigation: + return 'Navigation'; + case EventType.Location: + return 'Location'; + case EventType.Search: + return 'Search'; + case EventType.Transaction: + return 'Transaction'; + case EventType.UserContent: + return 'User Content'; + case EventType.UserPreference: + return 'User Preference'; + case EventType.Social: + return 'Social'; + case CommerceEventType.ProductAddToCart: + return 'Product Added to Cart'; + case CommerceEventType.ProductAddToWishlist: + return 'Product Added to Wishlist'; + case CommerceEventType.ProductCheckout: + return 'Product Checkout'; + case CommerceEventType.ProductCheckoutOption: + return 'Product Checkout Options'; + case CommerceEventType.ProductClick: + return 'Product Click'; + case CommerceEventType.ProductImpression: + return 'Product Impression'; + case CommerceEventType.ProductPurchase: + return 'Product Purchased'; + case CommerceEventType.ProductRefund: + return 'Product Refunded'; + case CommerceEventType.ProductRemoveFromCart: + return 'Product Removed From Cart'; + case CommerceEventType.ProductRemoveFromWishlist: + return 'Product Removed from Wishlist'; + case CommerceEventType.ProductViewDetail: + return 'Product View Details'; + case CommerceEventType.PromotionClick: + return 'Promotion Click'; + case CommerceEventType.PromotionView: + return 'Promotion View'; + default: + return 'Other'; + } + } + }; - // 6. Return a code point whose value is code point. - return code_point; + // Continuation of enum above, but in seperate object since we don't expose these to end user + var CommerceEventType = { + ProductAddToCart: 10, + ProductRemoveFromCart: 11, + ProductCheckout: 12, + ProductCheckoutOption: 13, + ProductClick: 14, + ProductViewDetail: 15, + ProductPurchase: 16, + ProductRefund: 17, + PromotionView: 18, + PromotionClick: 19, + ProductAddToWishlist: 20, + ProductRemoveFromWishlist: 21, + ProductImpression: 22 + }; + var IdentityType = { + Other: 0, + CustomerId: 1, + Facebook: 2, + Twitter: 3, + Google: 4, + Microsoft: 5, + Yahoo: 6, + Email: 7, + FacebookCustomAudienceId: 9, + Other2: 10, + Other3: 11, + Other4: 12, + Other5: 13, + Other6: 14, + Other7: 15, + Other8: 16, + Other9: 17, + Other10: 18, + MobileNumber: 19, + PhoneNumber2: 20, + PhoneNumber3: 21 + }; + IdentityType.isValid = function (identityType) { + if (typeof identityType === 'number') { + for (var prop in IdentityType) { + if (IdentityType.hasOwnProperty(prop)) { + if (IdentityType[prop] === identityType) { + return true; + } } + } + } + return false; + }; + IdentityType.getName = function (identityType) { + switch (identityType) { + case window.mParticle.IdentityType.CustomerId: + return 'Customer ID'; + case window.mParticle.IdentityType.Facebook: + return 'Facebook ID'; + case window.mParticle.IdentityType.Twitter: + return 'Twitter ID'; + case window.mParticle.IdentityType.Google: + return 'Google ID'; + case window.mParticle.IdentityType.Microsoft: + return 'Microsoft ID'; + case window.mParticle.IdentityType.Yahoo: + return 'Yahoo ID'; + case window.mParticle.IdentityType.Email: + return 'Email'; + case window.mParticle.IdentityType.FacebookCustomAudienceId: + return 'Facebook App User ID'; + default: + return 'Other ID'; + } + }; + IdentityType.getIdentityType = function (identityName) { + switch (identityName) { + case 'other': + return IdentityType.Other; + case 'customerid': + return IdentityType.CustomerId; + case 'facebook': + return IdentityType.Facebook; + case 'twitter': + return IdentityType.Twitter; + case 'google': + return IdentityType.Google; + case 'microsoft': + return IdentityType.Microsoft; + case 'yahoo': + return IdentityType.Yahoo; + case 'email': + return IdentityType.Email; + case 'facebookcustomaudienceid': + return IdentityType.FacebookCustomAudienceId; + case 'other2': + return IdentityType.Other2; + case 'other3': + return IdentityType.Other3; + case 'other4': + return IdentityType.Other4; + case 'other5': + return IdentityType.Other5; + case 'other6': + return IdentityType.Other6; + case 'other7': + return IdentityType.Other7; + case 'other8': + return IdentityType.Other8; + case 'other9': + return IdentityType.Other9; + case 'other10': + return IdentityType.Other10; + case 'mobile_number': + return IdentityType.MobileNumber; + case 'phone_number_2': + return IdentityType.PhoneNumber2; + case 'phone_number_3': + return IdentityType.PhoneNumber3; + default: + return false; + } + }; + IdentityType.getIdentityName = function (identityType) { + switch (identityType) { + case IdentityType.Other: + return 'other'; + case IdentityType.CustomerId: + return 'customerid'; + case IdentityType.Facebook: + return 'facebook'; + case IdentityType.Twitter: + return 'twitter'; + case IdentityType.Google: + return 'google'; + case IdentityType.Microsoft: + return 'microsoft'; + case IdentityType.Yahoo: + return 'yahoo'; + case IdentityType.Email: + return 'email'; + case IdentityType.FacebookCustomAudienceId: + return 'facebookcustomaudienceid'; + case IdentityType.Other2: + return 'other2'; + case IdentityType.Other3: + return 'other3'; + case IdentityType.Other4: + return 'other4'; + case IdentityType.Other5: + return 'other5'; + case IdentityType.Other6: + return 'other6'; + case IdentityType.Other7: + return 'other7'; + case IdentityType.Other8: + return 'other8'; + case IdentityType.Other9: + return 'other9'; + case IdentityType.Other10: + return 'other10'; + case IdentityType.MobileNumber: + return 'mobile_number'; + case IdentityType.PhoneNumber2: + return 'phone_number_2'; + case IdentityType.PhoneNumber3: + return 'phone_number_3'; + } + }; + var ProductActionType = { + Unknown: 0, + AddToCart: 1, + RemoveFromCart: 2, + Checkout: 3, + CheckoutOption: 4, + Click: 5, + ViewDetail: 6, + Purchase: 7, + Refund: 8, + AddToWishlist: 9, + RemoveFromWishlist: 10 + }; + ProductActionType.getName = function (id) { + switch (id) { + case ProductActionType.AddToCart: + return 'Add to Cart'; + case ProductActionType.RemoveFromCart: + return 'Remove from Cart'; + case ProductActionType.Checkout: + return 'Checkout'; + case ProductActionType.CheckoutOption: + return 'Checkout Option'; + case ProductActionType.Click: + return 'Click'; + case ProductActionType.ViewDetail: + return 'View Detail'; + case ProductActionType.Purchase: + return 'Purchase'; + case ProductActionType.Refund: + return 'Refund'; + case ProductActionType.AddToWishlist: + return 'Add to Wishlist'; + case ProductActionType.RemoveFromWishlist: + return 'Remove from Wishlist'; + default: + return 'Unknown'; + } + }; - // 6. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + // these are the action names used by server and mobile SDKs when expanding a CommerceEvent + ProductActionType.getExpansionName = function (id) { + switch (id) { + case ProductActionType.AddToCart: + return 'add_to_cart'; + case ProductActionType.RemoveFromCart: + return 'remove_from_cart'; + case ProductActionType.Checkout: + return 'checkout'; + case ProductActionType.CheckoutOption: + return 'checkout_option'; + case ProductActionType.Click: + return 'click'; + case ProductActionType.ViewDetail: + return 'view_detail'; + case ProductActionType.Purchase: + return 'purchase'; + case ProductActionType.Refund: + return 'refund'; + case ProductActionType.AddToWishlist: + return 'add_to_wishlist'; + case ProductActionType.RemoveFromWishlist: + return 'remove_from_wishlist'; + default: + return 'unknown'; + } + }; + var PromotionActionType = { + Unknown: 0, + PromotionView: 1, + PromotionClick: 2 + }; + PromotionActionType.getName = function (id) { + switch (id) { + case PromotionActionType.PromotionView: + return 'view'; + case PromotionActionType.PromotionClick: + return 'click'; + default: + return 'unknown'; + } + }; - // 7. If byte is 0x8E, 0x8F, or in the range 0xA1 to 0xFE, - // inclusive, set euc-jp lead to byte and return continue. - if (bite === 0x8E || bite === 0x8F || inRange(bite, 0xA1, 0xFE)) { - eucjp_lead = bite; - return null; + // these are the names that the server and mobile SDKs use while expanding CommerceEvent + PromotionActionType.getExpansionName = function (id) { + switch (id) { + case PromotionActionType.PromotionView: + return 'view'; + case PromotionActionType.PromotionClick: + return 'click'; + default: + return 'unknown'; + } + }; + var ProfileMessageType = { + Logout: 3 + }; + var ApplicationTransitionType$1 = { + AppInit: 1 + }; + var Environment = { + Production: 'production', + Development: 'development' + }; + var Types = { + MessageType: MessageType$1, + EventType: EventType, + CommerceEventType: CommerceEventType, + IdentityType: IdentityType, + ProfileMessageType: ProfileMessageType, + ApplicationTransitionType: ApplicationTransitionType$1, + ProductActionType: ProductActionType, + PromotionActionType: PromotionActionType, + TriggerUploadType: TriggerUploadType, + Environment: Environment + }; + + function convertEvents(mpid, sdkEvents, mpInstance) { + if (!mpid) { + return null; + } + if (!sdkEvents || sdkEvents.length < 1) { + return null; + } + var user = mpInstance.Identity.getCurrentUser(); + var uploadEvents = []; + var lastEvent = null; + for (var _i = 0, sdkEvents_1 = sdkEvents; _i < sdkEvents_1.length; _i++) { + var sdkEvent = sdkEvents_1[_i]; + if (sdkEvent) { + lastEvent = sdkEvent; + var baseEvent = convertEvent(sdkEvent); + if (baseEvent) { + uploadEvents.push(baseEvent); + } + } + } + if (!lastEvent) { + return null; + } + var currentConsentState = null; + // Add the consent state from either the Last Event or the user + if (!isEmpty(lastEvent.ConsentState)) { + currentConsentState = lastEvent.ConsentState; + } else if (!isEmpty(user)) { + currentConsentState = user.getConsentState(); + } + var upload = { + source_request_id: mpInstance._Helpers.generateUniqueId(), + mpid: mpid, + timestamp_unixtime_ms: new Date().getTime(), + environment: lastEvent.Debug ? dist.BatchEnvironmentEnum.development : dist.BatchEnvironmentEnum.production, + events: uploadEvents, + mp_deviceid: lastEvent.DeviceId, + sdk_version: lastEvent.SDKVersion, + // TODO: Refactor this to read from _Store or a global config + application_info: { + application_version: lastEvent.AppVersion, + application_name: lastEvent.AppName, + "package": lastEvent.Package, + sideloaded_kits_count: mpInstance._Store.sideloadedKitsCount + }, + device_info: { + platform: dist.DeviceInformationPlatformEnum.web, + screen_width: window.screen.width, + screen_height: window.screen.height + }, + user_attributes: lastEvent.UserAttributes, + user_identities: convertUserIdentities(lastEvent.UserIdentities), + consent_state: convertConsentState(currentConsentState), + integration_attributes: lastEvent.IntegrationAttributes + }; + if (lastEvent.DataPlan && lastEvent.DataPlan.PlanId) { + upload.context = { + data_plan: { + plan_id: lastEvent.DataPlan.PlanId, + plan_version: lastEvent.DataPlan.PlanVersion || undefined } + }; + } + return upload; + } + function convertConsentState(sdkConsentState) { + if (isEmpty(sdkConsentState)) { + return null; + } + var consentState = { + gdpr: convertGdprConsentState(sdkConsentState.getGDPRConsentState()), + ccpa: convertCcpaConsentState(sdkConsentState.getCCPAConsentState()) + }; + return consentState; + } + function convertGdprConsentState(sdkGdprConsentState) { + if (!sdkGdprConsentState) { + return null; + } + var state = {}; + for (var purpose in sdkGdprConsentState) { + if (sdkGdprConsentState.hasOwnProperty(purpose)) { + state[purpose] = { + consented: sdkGdprConsentState[purpose].Consented, + hardware_id: sdkGdprConsentState[purpose].HardwareId, + document: sdkGdprConsentState[purpose].ConsentDocument, + timestamp_unixtime_ms: sdkGdprConsentState[purpose].Timestamp, + location: sdkGdprConsentState[purpose].Location + }; + } + } + return state; + } + function convertCcpaConsentState(sdkCcpaConsentState) { + if (!sdkCcpaConsentState) { + return null; + } + var state = { + data_sale_opt_out: { + consented: sdkCcpaConsentState.Consented, + hardware_id: sdkCcpaConsentState.HardwareId, + document: sdkCcpaConsentState.ConsentDocument, + timestamp_unixtime_ms: sdkCcpaConsentState.Timestamp, + location: sdkCcpaConsentState.Location + } + }; + return state; + } + function convertUserIdentities(sdkUserIdentities) { + if (!sdkUserIdentities || !sdkUserIdentities.length) { + return null; + } + var batchIdentities = {}; + for (var _i = 0, sdkUserIdentities_1 = sdkUserIdentities; _i < sdkUserIdentities_1.length; _i++) { + var identity = sdkUserIdentities_1[_i]; + switch (identity.Type) { + case Types.IdentityType.CustomerId: + batchIdentities.customer_id = identity.Identity; + break; + case Types.IdentityType.Email: + batchIdentities.email = identity.Identity; + break; + case Types.IdentityType.Facebook: + batchIdentities.facebook = identity.Identity; + break; + case Types.IdentityType.FacebookCustomAudienceId: + batchIdentities.facebook_custom_audience_id = identity.Identity; + break; + case Types.IdentityType.Google: + batchIdentities.google = identity.Identity; + break; + case Types.IdentityType.Microsoft: + batchIdentities.microsoft = identity.Identity; + break; + case Types.IdentityType.Other: + batchIdentities.other = identity.Identity; + break; + case Types.IdentityType.Other2: + batchIdentities.other_id_2 = identity.Identity; + break; + case Types.IdentityType.Other3: + batchIdentities.other_id_3 = identity.Identity; + break; + case Types.IdentityType.Other4: + batchIdentities.other_id_4 = identity.Identity; + break; + case Types.IdentityType.Other5: + batchIdentities.other_id_5 = identity.Identity; + break; + case Types.IdentityType.Other6: + batchIdentities.other_id_6 = identity.Identity; + break; + case Types.IdentityType.Other7: + batchIdentities.other_id_7 = identity.Identity; + break; + case Types.IdentityType.Other8: + batchIdentities.other_id_8 = identity.Identity; + break; + case Types.IdentityType.Other9: + batchIdentities.other_id_9 = identity.Identity; + break; + case Types.IdentityType.Other10: + batchIdentities.other_id_10 = identity.Identity; + break; + case Types.IdentityType.MobileNumber: + batchIdentities.mobile_number = identity.Identity; + break; + case Types.IdentityType.PhoneNumber2: + batchIdentities.phone_number_2 = identity.Identity; + break; + case Types.IdentityType.PhoneNumber3: + batchIdentities.phone_number_3 = identity.Identity; + break; + } + } + return batchIdentities; + } + function convertEvent(sdkEvent) { + if (!sdkEvent) { + return null; + } + switch (sdkEvent.EventDataType) { + case Types.MessageType.AppStateTransition: + return convertAST(sdkEvent); + case Types.MessageType.Commerce: + return convertCommerceEvent(sdkEvent); + case Types.MessageType.CrashReport: + return convertCrashReportEvent(sdkEvent); + case Types.MessageType.OptOut: + return convertOptOutEvent(sdkEvent); + case Types.MessageType.PageEvent: + // Note: Media Events are also sent as PageEvents/CustomEvents + return convertCustomEvent(sdkEvent); + case Types.MessageType.PageView: + return convertPageViewEvent(sdkEvent); + case Types.MessageType.Profile: + //deprecated and not supported by the web SDK + return null; + case Types.MessageType.SessionEnd: + return convertSessionEndEvent(sdkEvent); + case Types.MessageType.SessionStart: + return convertSessionStartEvent(sdkEvent); + case Types.MessageType.UserAttributeChange: + return convertUserAttributeChangeEvent(sdkEvent); + case Types.MessageType.UserIdentityChange: + return convertUserIdentityChangeEvent(sdkEvent); + } + return null; + } + function convertProductActionType(actionType) { + if (!actionType) { + return dist.ProductActionActionEnum.unknown; + } + switch (actionType) { + case SDKProductActionType.AddToCart: + return dist.ProductActionActionEnum.addToCart; + case SDKProductActionType.AddToWishlist: + return dist.ProductActionActionEnum.addToWishlist; + case SDKProductActionType.Checkout: + return dist.ProductActionActionEnum.checkout; + case SDKProductActionType.CheckoutOption: + return dist.ProductActionActionEnum.checkoutOption; + case SDKProductActionType.Click: + return dist.ProductActionActionEnum.click; + case SDKProductActionType.Purchase: + return dist.ProductActionActionEnum.purchase; + case SDKProductActionType.Refund: + return dist.ProductActionActionEnum.refund; + case SDKProductActionType.RemoveFromCart: + return dist.ProductActionActionEnum.removeFromCart; + case SDKProductActionType.RemoveFromWishlist: + return dist.ProductActionActionEnum.removeFromWishlist; + case SDKProductActionType.ViewDetail: + return dist.ProductActionActionEnum.viewDetail; + default: + return dist.ProductActionActionEnum.unknown; + } + } + function convertProductAction(sdkEvent) { + if (!sdkEvent.ProductAction) { + return null; + } + var productAction = { + action: convertProductActionType(sdkEvent.ProductAction.ProductActionType), + checkout_step: sdkEvent.ProductAction.CheckoutStep, + checkout_options: sdkEvent.ProductAction.CheckoutOptions, + transaction_id: sdkEvent.ProductAction.TransactionId, + affiliation: sdkEvent.ProductAction.Affiliation, + total_amount: sdkEvent.ProductAction.TotalAmount, + tax_amount: sdkEvent.ProductAction.TaxAmount, + shipping_amount: sdkEvent.ProductAction.ShippingAmount, + coupon_code: sdkEvent.ProductAction.CouponCode, + products: convertProducts(sdkEvent.ProductAction.ProductList) + }; + return productAction; + } + function convertProducts(sdkProducts) { + if (!sdkProducts || !sdkProducts.length) { + return null; + } + var products = []; + for (var _i = 0, sdkProducts_1 = sdkProducts; _i < sdkProducts_1.length; _i++) { + var sdkProduct = sdkProducts_1[_i]; + var product = { + id: sdkProduct.Sku, + name: sdkProduct.Name, + brand: sdkProduct.Brand, + category: sdkProduct.Category, + variant: sdkProduct.Variant, + total_product_amount: sdkProduct.TotalAmount, + position: sdkProduct.Position, + price: sdkProduct.Price, + quantity: sdkProduct.Quantity, + coupon_code: sdkProduct.CouponCode, + custom_attributes: sdkProduct.Attributes + }; + products.push(product); + } + return products; + } + function convertPromotionAction(sdkEvent) { + if (!sdkEvent.PromotionAction) { + return null; + } + var promotionAction = { + action: sdkEvent.PromotionAction.PromotionActionType, + promotions: convertPromotions(sdkEvent.PromotionAction.PromotionList) + }; + return promotionAction; + } + function convertPromotions(sdkPromotions) { + if (!sdkPromotions || !sdkPromotions.length) { + return null; + } + var promotions = []; + for (var _i = 0, sdkPromotions_1 = sdkPromotions; _i < sdkPromotions_1.length; _i++) { + var sdkPromotion = sdkPromotions_1[_i]; + var promotion = { + id: sdkPromotion.Id, + name: sdkPromotion.Name, + creative: sdkPromotion.Creative, + position: sdkPromotion.Position + }; + promotions.push(promotion); + } + return promotions; + } + function convertImpressions(sdkEvent) { + if (!sdkEvent.ProductImpressions) { + return null; + } + var impressions = []; + for (var _i = 0, _a = sdkEvent.ProductImpressions; _i < _a.length; _i++) { + var sdkImpression = _a[_i]; + var impression = { + product_impression_list: sdkImpression.ProductImpressionList, + products: convertProducts(sdkImpression.ProductList) + }; + impressions.push(impression); + } + return impressions; + } + function convertShoppingCart(sdkEvent) { + if (!sdkEvent.ShoppingCart || !sdkEvent.ShoppingCart.ProductList || !sdkEvent.ShoppingCart.ProductList.length) { + return null; + } + var shoppingCart = { + products: convertProducts(sdkEvent.ShoppingCart.ProductList) + }; + return shoppingCart; + } + function convertCommerceEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var commerceEventData = { + custom_flags: sdkEvent.CustomFlags, + product_action: convertProductAction(sdkEvent), + promotion_action: convertPromotionAction(sdkEvent), + product_impressions: convertImpressions(sdkEvent), + shopping_cart: convertShoppingCart(sdkEvent), + currency_code: sdkEvent.CurrencyCode + }; + commerceEventData = Object.assign(commerceEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.commerceEvent, + data: commerceEventData + }; + } + function convertCrashReportEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var crashReportEventData = { + message: sdkEvent.EventName + }; + crashReportEventData = Object.assign(crashReportEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.crashReport, + data: crashReportEventData + }; + } + function convertAST(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var astEventData = { + application_transition_type: dist.ApplicationStateTransitionEventDataApplicationTransitionTypeEnum.applicationInitialized, + is_first_run: sdkEvent.IsFirstRun, + is_upgrade: false, + launch_referral: sdkEvent.LaunchReferral + }; + astEventData = Object.assign(astEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.applicationStateTransition, + data: astEventData + }; + } + function convertSessionEndEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var sessionEndEventData = { + session_duration_ms: sdkEvent.SessionLength + //note: External Events DTO does not support the session mpids array as of this time. + //spanning_mpids: sdkEvent.SessionMpids + }; - // 8. Return error. - return decoderError(fatal); + sessionEndEventData = Object.assign(sessionEndEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.sessionEnd, + data: sessionEndEventData + }; + } + function convertSessionStartEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var sessionStartEventData = {}; + sessionStartEventData = Object.assign(sessionStartEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.sessionStart, + data: sessionStartEventData + }; + } + function convertPageViewEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var screenViewEventData = { + custom_flags: sdkEvent.CustomFlags, + screen_name: sdkEvent.EventName + }; + screenViewEventData = Object.assign(screenViewEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.screenView, + data: screenViewEventData + }; + } + function convertOptOutEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var optOutEventData = { + is_opted_out: sdkEvent.OptOut + }; + optOutEventData = Object.assign(optOutEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.optOut, + data: optOutEventData + }; + } + function convertCustomEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var customEventData = { + custom_event_type: convertSdkEventType(sdkEvent.EventCategory), + custom_flags: sdkEvent.CustomFlags, + event_name: sdkEvent.EventName + }; + customEventData = Object.assign(customEventData, commonEventData); + return { + event_type: dist.EventTypeEnum.customEvent, + data: customEventData + }; + } + function convertSdkEventType(sdkEventType) { + switch (sdkEventType) { + case Types.EventType.Other: + return dist.CustomEventDataCustomEventTypeEnum.other; + case Types.EventType.Location: + return dist.CustomEventDataCustomEventTypeEnum.location; + case Types.EventType.Navigation: + return dist.CustomEventDataCustomEventTypeEnum.navigation; + case Types.EventType.Search: + return dist.CustomEventDataCustomEventTypeEnum.search; + case Types.EventType.Social: + return dist.CustomEventDataCustomEventTypeEnum.social; + case Types.EventType.Transaction: + return dist.CustomEventDataCustomEventTypeEnum.transaction; + case Types.EventType.UserContent: + return dist.CustomEventDataCustomEventTypeEnum.userContent; + case Types.EventType.UserPreference: + return dist.CustomEventDataCustomEventTypeEnum.userPreference; + case Types.EventType.Media: + return dist.CustomEventDataCustomEventTypeEnum.media; + case Types.CommerceEventType.ProductAddToCart: + return dist.CommerceEventDataCustomEventTypeEnum.addToCart; + case Types.CommerceEventType.ProductAddToWishlist: + return dist.CommerceEventDataCustomEventTypeEnum.addToWishlist; + case Types.CommerceEventType.ProductCheckout: + return dist.CommerceEventDataCustomEventTypeEnum.checkout; + case Types.CommerceEventType.ProductCheckoutOption: + return dist.CommerceEventDataCustomEventTypeEnum.checkoutOption; + case Types.CommerceEventType.ProductClick: + return dist.CommerceEventDataCustomEventTypeEnum.click; + case Types.CommerceEventType.ProductImpression: + return dist.CommerceEventDataCustomEventTypeEnum.impression; + case Types.CommerceEventType.ProductPurchase: + return dist.CommerceEventDataCustomEventTypeEnum.purchase; + case Types.CommerceEventType.ProductRefund: + return dist.CommerceEventDataCustomEventTypeEnum.refund; + case Types.CommerceEventType.ProductRemoveFromCart: + return dist.CommerceEventDataCustomEventTypeEnum.removeFromCart; + case Types.CommerceEventType.ProductRemoveFromWishlist: + return dist.CommerceEventDataCustomEventTypeEnum.removeFromWishlist; + case Types.CommerceEventType.ProductViewDetail: + return dist.CommerceEventDataCustomEventTypeEnum.viewDetail; + case Types.CommerceEventType.PromotionClick: + return dist.CommerceEventDataCustomEventTypeEnum.promotionClick; + case Types.CommerceEventType.PromotionView: + return dist.CommerceEventDataCustomEventTypeEnum.promotionView; + default: + return dist.CustomEventDataCustomEventTypeEnum.unknown; + } + } + function convertBaseEventData(sdkEvent) { + var commonEventData = { + timestamp_unixtime_ms: sdkEvent.Timestamp, + session_uuid: sdkEvent.SessionId, + session_start_unixtime_ms: sdkEvent.SessionStartDate, + custom_attributes: sdkEvent.EventAttributes, + location: convertSDKLocation(sdkEvent.Location), + source_message_id: sdkEvent.SourceMessageId + }; + return commonEventData; + } + function convertSDKLocation(sdkEventLocation) { + if (sdkEventLocation && Object.keys(sdkEventLocation).length) { + return { + latitude: sdkEventLocation.lat, + longitude: sdkEventLocation.lng }; } + return null; + } + function convertUserAttributeChangeEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var userAttributeChangeEvent = { + user_attribute_name: sdkEvent.UserAttributeChanges.UserAttributeName, + "new": sdkEvent.UserAttributeChanges.New, + old: sdkEvent.UserAttributeChanges.Old, + deleted: sdkEvent.UserAttributeChanges.Deleted, + is_new_attribute: sdkEvent.UserAttributeChanges.IsNewAttribute + }; + userAttributeChangeEvent = __assign(__assign({}, userAttributeChangeEvent), commonEventData); + return { + event_type: dist.EventTypeEnum.userAttributeChange, + data: userAttributeChangeEvent + }; + } + function convertUserIdentityChangeEvent(sdkEvent) { + var commonEventData = convertBaseEventData(sdkEvent); + var userIdentityChangeEvent = { + "new": { + identity_type: convertUserIdentityTypeToServerIdentityType(sdkEvent.UserIdentityChanges.New.IdentityType), + identity: sdkEvent.UserIdentityChanges.New.Identity || null, + timestamp_unixtime_ms: sdkEvent.Timestamp, + created_this_batch: sdkEvent.UserIdentityChanges.New.CreatedThisBatch + }, + old: { + identity_type: convertUserIdentityTypeToServerIdentityType(sdkEvent.UserIdentityChanges.Old.IdentityType), + identity: sdkEvent.UserIdentityChanges.Old.Identity || null, + timestamp_unixtime_ms: sdkEvent.Timestamp, + created_this_batch: sdkEvent.UserIdentityChanges.Old.CreatedThisBatch + } + }; + userIdentityChangeEvent = Object.assign(userIdentityChangeEvent, commonEventData); + return { + event_type: dist.EventTypeEnum.userIdentityChange, + data: userIdentityChangeEvent + }; + } + function convertUserIdentityTypeToServerIdentityType(identityType) { + switch (identityType) { + case SDKIdentityTypeEnum.other: + return dist.IdentityTypeEnum.other; + case SDKIdentityTypeEnum.customerId: + return dist.IdentityTypeEnum.customerId; + case SDKIdentityTypeEnum.facebook: + return dist.IdentityTypeEnum.facebook; + case SDKIdentityTypeEnum.twitter: + return dist.IdentityTypeEnum.twitter; + case SDKIdentityTypeEnum.google: + return dist.IdentityTypeEnum.google; + case SDKIdentityTypeEnum.microsoft: + return dist.IdentityTypeEnum.microsoft; + case SDKIdentityTypeEnum.yahoo: + return dist.IdentityTypeEnum.yahoo; + case SDKIdentityTypeEnum.email: + return dist.IdentityTypeEnum.email; + case SDKIdentityTypeEnum.alias: + return dist.IdentityTypeEnum.alias; + case SDKIdentityTypeEnum.facebookCustomAudienceId: + return dist.IdentityTypeEnum.facebookCustomAudienceId; + case SDKIdentityTypeEnum.otherId2: + return dist.IdentityTypeEnum.otherId2; + case SDKIdentityTypeEnum.otherId3: + return dist.IdentityTypeEnum.otherId3; + case SDKIdentityTypeEnum.otherId4: + return dist.IdentityTypeEnum.otherId4; + case SDKIdentityTypeEnum.otherId5: + return dist.IdentityTypeEnum.otherId5; + case SDKIdentityTypeEnum.otherId6: + return dist.IdentityTypeEnum.otherId6; + case SDKIdentityTypeEnum.otherId7: + return dist.IdentityTypeEnum.otherId7; + case SDKIdentityTypeEnum.otherId8: + return dist.IdentityTypeEnum.otherId8; + case SDKIdentityTypeEnum.otherId9: + return dist.IdentityTypeEnum.otherId9; + case SDKIdentityTypeEnum.otherId10: + return dist.IdentityTypeEnum.otherId10; + case SDKIdentityTypeEnum.mobileNumber: + return dist.IdentityTypeEnum.mobileNumber; + case SDKIdentityTypeEnum.phoneNumber2: + return dist.IdentityTypeEnum.phoneNumber2; + case SDKIdentityTypeEnum.phoneNumber3: + return dist.IdentityTypeEnum.phoneNumber3; + } + } - // 13.1.2 euc-jp encoder + var BaseVault = /** @class */function () { /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options + * + * @param {string} storageKey the local storage key string + * @param {Storage} Web API Storage object that is being used + * @param {IVaultOptions} options A Dictionary of IVaultOptions */ - function EUCJPEncoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; - - // 3. If code point is U+00A5, return byte 0x5C. - if (code_point === 0x00A5) - return 0x5C; - - // 4. If code point is U+203E, return byte 0x7E. - if (code_point === 0x203E) - return 0x7E; - - // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, - // return two bytes whose values are 0x8E and code point − - // 0xFF61 + 0xA1. - if (inRange(code_point, 0xFF61, 0xFF9F)) - return [0x8E, code_point - 0xFF61 + 0xA1]; - - // 6. If code point is U+2212, set it to U+FF0D. - if (code_point === 0x2212) - code_point = 0xFF0D; - - // 7. Let pointer be the index pointer for code point in index - // jis0208. - var pointer = indexPointerFor(code_point, index('jis0208')); - - // 8. If pointer is null, return error with code point. - if (pointer === null) - return encoderError(code_point); - - // 9. Let lead be floor(pointer / 94) + 0xA1. - var lead = floor(pointer / 94) + 0xA1; - - // 10. Let trail be pointer % 94 + 0xA1. - var trail = pointer % 94 + 0xA1; - - // 11. Return two bytes whose values are lead and trail. - return [lead, trail]; + function BaseVault(storageKey, storageObject, options) { + this._storageKey = storageKey; + this.storageObject = storageObject; + // Add a fake logger in case one is not provided or needed + this.logger = (options === null || options === void 0 ? void 0 : options.logger) || { + verbose: function verbose() {}, + warning: function warning() {}, + error: function error() {} }; + this.contents = this.retrieve(); } - - /** @param {{fatal: boolean}} options */ - encoders['EUC-JP'] = function(options) { - return new EUCJPEncoder(options); + /** + * Stores a StorableItem to Storage + * @method store + * @param item {StorableItem} + */ + BaseVault.prototype.store = function (item) { + this.contents = item; + var stringifiedItem = !isEmpty(item) ? JSON.stringify(item) : ''; + try { + this.storageObject.setItem(this._storageKey, stringifiedItem); + this.logger.verbose("Saving item to Storage: ".concat(stringifiedItem)); + } catch (error) { + this.logger.error("Cannot Save items to Storage: ".concat(stringifiedItem)); + this.logger.error(error); + } }; - /** @param {{fatal: boolean}} options */ - decoders['EUC-JP'] = function(options) { - return new EUCJPDecoder(options); + /** + * Retrieve StorableItem from Storage + * @method retrieve + * @returns {StorableItem} + */ + BaseVault.prototype.retrieve = function () { + // TODO: Handle cases where Local Storage is unavailable + // https://go.mparticle.com/work/SQDSDKS-5022 + var item = this.storageObject.getItem(this._storageKey); + this.contents = item ? JSON.parse(item) : null; + this.logger.verbose("Retrieving item from Storage: ".concat(item)); + return this.contents; }; - - // 13.2 iso-2022-jp - - // 13.2.1 iso-2022-jp decoder /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options + * Removes all persisted data from Storage based on this vault's `key` + * Will remove storage key from Storage as well + * @method purge */ - function ISO2022JPDecoder(options) { - var fatal = options.fatal; - /** @enum */ - var states = { - ASCII: 0, - Roman: 1, - Katakana: 2, - LeadByte: 3, - TrailByte: 4, - EscapeStart: 5, - Escape: 6 - }; - // iso-2022-jp's decoder has an associated iso-2022-jp decoder - // state (initially ASCII), iso-2022-jp decoder output state - // (initially ASCII), iso-2022-jp lead (initially 0x00), and - // iso-2022-jp output flag (initially unset). - var /** @type {number} */ iso2022jp_decoder_state = states.ASCII, - /** @type {number} */ iso2022jp_decoder_output_state = states.ASCII, - /** @type {number} */ iso2022jp_lead = 0x00, - /** @type {boolean} */ iso2022jp_output_flag = false; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // switching on iso-2022-jp decoder state: - switch (iso2022jp_decoder_state) { - default: - case states.ASCII: - // ASCII - // Based on byte: - - // 0x1B - if (bite === 0x1B) { - // Set iso-2022-jp decoder state to escape start and return - // continue. - iso2022jp_decoder_state = states.EscapeStart; - return null; - } - - // 0x00 to 0x7F, excluding 0x0E, 0x0F, and 0x1B - if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E - && bite !== 0x0F && bite !== 0x1B) { - // Unset the iso-2022-jp output flag and return a code point - // whose value is byte. - iso2022jp_output_flag = false; - return bite; - } + BaseVault.prototype.purge = function () { + this.logger.verbose('Purging Storage'); + this.contents = null; + this.storageObject.removeItem(this._storageKey); + }; + return BaseVault; + }(); + var LocalStorageVault = /** @class */function (_super) { + __extends(LocalStorageVault, _super); + function LocalStorageVault(storageKey, options) { + return _super.call(this, storageKey, window.localStorage, options) || this; + } + return LocalStorageVault; + }(BaseVault); + var SessionStorageVault = /** @class */function (_super) { + __extends(SessionStorageVault, _super); + function SessionStorageVault(storageKey, options) { + return _super.call(this, storageKey, window.sessionStorage, options) || this; + } + return SessionStorageVault; + }(BaseVault); - // end-of-stream - if (bite === end_of_stream) { - // Return finished. - return finished; + /** + * BatchUploader contains all the logic to store/retrieve events and batches + * to/from persistence, and upload batches to mParticle. + * It queues events as they come in, storing them in persistence, then at set + * intervals turns them into batches and transfers between event and batch + * persistence. + * It then attempts to upload them to mParticle, purging batch persistence if + * the upload is successful + * + * These uploads happen on an interval basis using window.fetch or XHR + * requests, depending on what is available in the browser. + * + * Uploads can also be triggered on browser visibility/focus changes via an + * event listener, which then uploads to mPartice via the browser's Beacon API. + */ + var BatchUploader = /** @class */function () { + /** + * Creates an instance of a BatchUploader + * @param {MParticleWebSDK} mpInstance - the mParticle SDK instance + * @param {number} uploadInterval - the desired upload interval in milliseconds + */ + function BatchUploader(mpInstance, uploadInterval) { + var _a; + this.offlineStorageEnabled = false; + this.mpInstance = mpInstance; + this.uploadIntervalMillis = uploadInterval; + this.batchingEnabled = uploadInterval >= BatchUploader.MINIMUM_INTERVAL_MILLIS; + if (this.uploadIntervalMillis < BatchUploader.MINIMUM_INTERVAL_MILLIS) { + this.uploadIntervalMillis = BatchUploader.MINIMUM_INTERVAL_MILLIS; + } + // Events will be queued during `queueEvents` method + this.eventsQueuedForProcessing = []; + // Batch queue should start empty and will be populated during + // `prepareAndUpload` method, either via Local Storage or after + // new batches are created. + this.batchesQueuedForProcessing = []; + // Cache Offline Storage Availability boolean + // so that we don't have to check it every time + this.offlineStorageEnabled = this.isOfflineStorageAvailable(); + if (this.offlineStorageEnabled) { + this.eventVault = new SessionStorageVault("".concat(mpInstance._Store.storageName, "-events"), { + logger: mpInstance.Logger + }); + this.batchVault = new LocalStorageVault("".concat(mpInstance._Store.storageName, "-batches"), { + logger: mpInstance.Logger + }); + // Load Events from Session Storage in case we have any in storage + (_a = this.eventsQueuedForProcessing).push.apply(_a, this.eventVault.retrieve()); + } + var _b = this.mpInstance._Store, + SDKConfig = _b.SDKConfig, + devToken = _b.devToken; + var baseUrl = this.mpInstance._Helpers.createServiceUrl(SDKConfig.v3SecureServiceUrl, devToken); + this.uploadUrl = "".concat(baseUrl, "/events"); + this.uploader = window.fetch ? new FetchUploader(this.uploadUrl) : new XHRUploader(this.uploadUrl); + this.triggerUploadInterval(true, false); + this.addEventListeners(); + } + BatchUploader.prototype.isOfflineStorageAvailable = function () { + var _a = this.mpInstance, + getFeatureFlag = _a._Helpers.getFeatureFlag, + deviceId = _a._Store.deviceId; + var offlineStorageFeatureFlagValue = getFeatureFlag(Constants.FeatureFlags.OfflineStorage); + var offlineStoragePercentage = parseInt(offlineStorageFeatureFlagValue, 10); + var rampNumber = getRampNumber(deviceId); + // TODO: Handle cases where Local Storage is unavailable + // Potentially shared between Vault and Persistence as well + // https://go.mparticle.com/work/SQDSDKS-5022 + return offlineStoragePercentage >= rampNumber; + }; + // Adds listeners to be used trigger Navigator.sendBeacon if the browser + // loses focus for any reason, such as closing browser tab or minimizing window + BatchUploader.prototype.addEventListeners = function () { + var _this = this; + // visibility change is a document property, not window + document.addEventListener('visibilitychange', function () { + _this.prepareAndUpload(false, _this.isBeaconAvailable()); + }); + window.addEventListener('beforeunload', function () { + _this.prepareAndUpload(false, _this.isBeaconAvailable()); + }); + window.addEventListener('pagehide', function () { + _this.prepareAndUpload(false, _this.isBeaconAvailable()); + }); + }; + BatchUploader.prototype.isBeaconAvailable = function () { + if (navigator.sendBeacon) { + return true; + } + return false; + }; + // Triggers a setTimeout for prepareAndUpload + BatchUploader.prototype.triggerUploadInterval = function (triggerFuture, useBeacon) { + var _this_1 = this; + if (triggerFuture === void 0) { + triggerFuture = false; + } + if (useBeacon === void 0) { + useBeacon = false; + } + setTimeout(function () { + _this_1.prepareAndUpload(triggerFuture, useBeacon); + }, this.uploadIntervalMillis); + }; + /** + * This method will queue a single Event which will eventually be processed into a Batch + * @param event event that should be queued + */ + BatchUploader.prototype.queueEvent = function (event) { + if (!isEmpty(event)) { + this.eventsQueuedForProcessing.push(event); + if (this.offlineStorageEnabled && this.eventVault) { + this.eventVault.store(this.eventsQueuedForProcessing); + } + this.mpInstance.Logger.verbose("Queuing event: ".concat(JSON.stringify(event))); + this.mpInstance.Logger.verbose("Queued event count: ".concat(this.eventsQueuedForProcessing.length)); + // TODO: Remove this check once the v2 code path is removed + // https://go.mparticle.com/work/SQDSDKS-3720 + if (!this.batchingEnabled || Types.TriggerUploadType[event.EventDataType]) { + this.prepareAndUpload(false, false); + } + } + }; + /** + * This implements crucial logic to: + * - bucket pending events by MPID, and then by Session, and upload individual batches for each bucket. + * + * In the future this should enforce other requirements such as maximum batch size. + * + * @param sdkEvents current pending events + * @param defaultUser the user to reference for events that are missing data + */ + BatchUploader.createNewBatches = function (sdkEvents, defaultUser, mpInstance) { + if (!defaultUser || !sdkEvents || !sdkEvents.length) { + return null; + } + //bucket by MPID, and then by session, ordered by timestamp + var newUploads = []; + var eventsByUser = new Map(); + for (var _i = 0, sdkEvents_1 = sdkEvents; _i < sdkEvents_1.length; _i++) { + var sdkEvent = sdkEvents_1[_i]; + //on initial startup, there may be events logged without an mpid. + if (!sdkEvent.MPID) { + var mpid = defaultUser.getMPID(); + sdkEvent.MPID = mpid; + } + var events = eventsByUser.get(sdkEvent.MPID); + if (!events) { + events = []; + } + events.push(sdkEvent); + eventsByUser.set(sdkEvent.MPID, events); + } + for (var _a = 0, _b = Array.from(eventsByUser.entries()); _a < _b.length; _a++) { + var entry = _b[_a]; + var mpid = entry[0]; + var userEvents = entry[1]; + var eventsBySession = new Map(); + for (var _c = 0, userEvents_1 = userEvents; _c < userEvents_1.length; _c++) { + var sdkEvent = userEvents_1[_c]; + var events = eventsBySession.get(sdkEvent.SessionId); + if (!events) { + events = []; } - - // Otherwise - // Unset the iso-2022-jp output flag and return error. - iso2022jp_output_flag = false; - return decoderError(fatal); - - case states.Roman: - // Roman - // Based on byte: - - // 0x1B - if (bite === 0x1B) { - // Set iso-2022-jp decoder state to escape start and return - // continue. - iso2022jp_decoder_state = states.EscapeStart; - return null; + events.push(sdkEvent); + eventsBySession.set(sdkEvent.SessionId, events); + } + for (var _d = 0, _e = Array.from(eventsBySession.entries()); _d < _e.length; _d++) { + var entry_1 = _e[_d]; + var uploadBatchObject = convertEvents(mpid, entry_1[1], mpInstance); + var onCreateBatchCallback = mpInstance._Store.SDKConfig.onCreateBatch; + if (onCreateBatchCallback) { + uploadBatchObject = onCreateBatchCallback(uploadBatchObject); + if (uploadBatchObject) { + uploadBatchObject.modified = true; + } else { + mpInstance.Logger.warning('Skiping batch upload because no batch was returned from onCreateBatch callback'); + } } - - // 0x5C - if (bite === 0x5C) { - // Unset the iso-2022-jp output flag and return code point - // U+00A5. - iso2022jp_output_flag = false; - return 0x00A5; + if (uploadBatchObject) { + newUploads.push(uploadBatchObject); } - - // 0x7E - if (bite === 0x7E) { - // Unset the iso-2022-jp output flag and return code point - // U+203E. - iso2022jp_output_flag = false; - return 0x203E; + } + } + return newUploads; + }; + /** + * This is the main loop function: + * - take all pending events and turn them into batches + * - attempt to upload each batch + * + * @param triggerFuture whether to trigger the loop again - for manual/forced uploads this should be false + * @param useBeacon whether to use the beacon API - used when the page is being unloaded + */ + BatchUploader.prototype.prepareAndUpload = function (triggerFuture, useBeacon) { + return __awaiter(this, void 0, void 0, function () { + var currentUser, currentEvents, newBatches, batchesToUpload, batchesThatDidNotUpload; + var _a, _b, _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + currentUser = this.mpInstance.Identity.getCurrentUser(); + currentEvents = this.eventsQueuedForProcessing; + this.eventsQueuedForProcessing = []; + if (this.offlineStorageEnabled && this.eventVault) { + this.eventVault.store([]); + } + newBatches = []; + if (!isEmpty(currentEvents)) { + newBatches = BatchUploader.createNewBatches(currentEvents, currentUser, this.mpInstance); + } + // Top Load any older Batches from Offline Storage so they go out first + if (this.offlineStorageEnabled && this.batchVault) { + (_a = this.batchesQueuedForProcessing).unshift.apply(_a, this.batchVault.retrieve()); + // Remove batches from local storage before transmit to + // prevent duplication + this.batchVault.purge(); + } + if (!isEmpty(newBatches)) { + (_b = this.batchesQueuedForProcessing).push.apply(_b, newBatches); + } + batchesToUpload = this.batchesQueuedForProcessing; + this.batchesQueuedForProcessing = []; + // If `useBeacon` is true, the browser has been closed suddently + // so we should save `batchesToUpload` to Offline Storage before + // an upload is attempted. + if (useBeacon && this.offlineStorageEnabled && this.batchVault) { + this.batchVault.store(batchesToUpload); + } + return [4 /*yield*/, this.uploadBatches(this.mpInstance.Logger, batchesToUpload, useBeacon)]; + case 1: + batchesThatDidNotUpload = _d.sent(); + // Batches that do not successfully upload are added back to the process queue + // in the order they were created so that we can attempt re-transmission in + // the same sequence. This is to prevent any potential data corruption. + if (!isEmpty(batchesThatDidNotUpload)) { + // TODO: https://go.mparticle.com/work/SQDSDKS-5165 + (_c = this.batchesQueuedForProcessing).unshift.apply(_c, batchesThatDidNotUpload); + } + // Update Offline Storage with current state of batch queue + if (!useBeacon && this.offlineStorageEnabled && this.batchVault) { + // Note: since beacon is "Fire and forget" it will empty `batchesThatDidNotUplod` + // regardless of whether the batches were successfully uploaded or not. We should + // therefore NOT overwrite Offline Storage when beacon returns, so that we can retry + // uploading saved batches at a later time. Batches should only be removed from + // Local Storage once we can confirm they are successfully uploaded. + this.batchVault.store(this.batchesQueuedForProcessing); + // Clear batch queue since everything should be in Offline Storage + this.batchesQueuedForProcessing = []; + } + if (triggerFuture) { + this.triggerUploadInterval(triggerFuture, false); + } + return [2 /*return*/]; } - - // 0x00 to 0x7F, excluding 0x0E, 0x0F, 0x1B, 0x5C, and 0x7E - if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E && bite !== 0x0F - && bite !== 0x1B && bite !== 0x5C && bite !== 0x7E) { - // Unset the iso-2022-jp output flag and return a code point - // whose value is byte. - iso2022jp_output_flag = false; - return bite; + }); + }); + }; + // TODO: Refactor to use logger as a class method + // https://go.mparticle.com/work/SQDSDKS-5167 + BatchUploader.prototype.uploadBatches = function (logger, batches, useBeacon) { + return __awaiter(this, void 0, void 0, function () { + var uploads, i, fetchPayload, blob, response, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + uploads = batches.filter(function (batch) { + return !isEmpty(batch.events); + }); + if (isEmpty(uploads)) { + return [2 /*return*/, null]; + } + logger.verbose("Uploading batches: ".concat(JSON.stringify(uploads))); + logger.verbose("Batch count: ".concat(uploads.length)); + i = 0; + _a.label = 1; + case 1: + if (!(i < uploads.length)) return [3 /*break*/, 6]; + fetchPayload = { + method: 'POST', + headers: { + Accept: BatchUploader.CONTENT_TYPE, + 'Content-Type': 'text/plain;charset=UTF-8' + }, + body: JSON.stringify(uploads[i]) + }; + if (!(useBeacon && this.isBeaconAvailable())) return [3 /*break*/, 2]; + blob = new Blob([fetchPayload.body], { + type: 'text/plain;charset=UTF-8' + }); + navigator.sendBeacon(this.uploadUrl, blob); + return [3 /*break*/, 5]; + case 2: + _a.trys.push([2, 4,, 5]); + return [4 /*yield*/, this.uploader.upload(fetchPayload)]; + case 3: + response = _a.sent(); + if (response.status >= 200 && response.status < 300) { + logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id)); + } else if (response.status >= 500 || response.status === 429) { + logger.error("HTTP error status ".concat(response.status, " received")); + // Server error, add back current batches and try again later + return [2 /*return*/, uploads.slice(i, uploads.length)]; + } else if (response.status >= 401) { + logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key.")); + //if we're getting a 401, assume we'll keep getting a 401 and clear the uploads. + return [2 /*return*/, null]; + } else { + // In case there is an HTTP error we did not anticipate. + console.error("HTTP error status ".concat(response.status, " while uploading events."), response); + throw new Error("Uncaught HTTP Error ".concat(response.status, ". Batch upload will be re-attempted.")); + } + return [3 /*break*/, 5]; + case 4: + e_1 = _a.sent(); + logger.error("Error sending event to mParticle servers. ".concat(e_1)); + return [2 /*return*/, uploads.slice(i, uploads.length)]; + case 5: + i++; + return [3 /*break*/, 1]; + case 6: + return [2 /*return*/, null]; } - - // end-of-stream - if (bite === end_of_stream) { - // Return finished. - return finished; + }); + }); + }; + // We upload JSON, but this content type is required to avoid a CORS preflight request + BatchUploader.CONTENT_TYPE = 'text/plain;charset=UTF-8'; + BatchUploader.MINIMUM_INTERVAL_MILLIS = 500; + return BatchUploader; + }(); + var AsyncUploader = /** @class */function () { + function AsyncUploader(url) { + this.url = url; + } + return AsyncUploader; + }(); + var FetchUploader = /** @class */function (_super) { + __extends(FetchUploader, _super); + function FetchUploader() { + return _super !== null && _super.apply(this, arguments) || this; + } + FetchUploader.prototype.upload = function (fetchPayload) { + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, fetch(this.url, fetchPayload)]; + case 1: + response = _a.sent(); + return [2 /*return*/, response]; } + }); + }); + }; + return FetchUploader; + }(AsyncUploader); + var XHRUploader = /** @class */function (_super) { + __extends(XHRUploader, _super); + function XHRUploader() { + return _super !== null && _super.apply(this, arguments) || this; + } + XHRUploader.prototype.upload = function (fetchPayload) { + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + return [4 /*yield*/, this.makeRequest(this.url, fetchPayload.body)]; + case 1: + response = _a.sent(); + return [2 /*return*/, response]; + } + }); + }); + }; + XHRUploader.prototype.makeRequest = function (url, data) { + return __awaiter(this, void 0, void 0, function () { + var xhr; + return __generator(this, function (_a) { + xhr = new XMLHttpRequest(); + return [2 /*return*/, new Promise(function (resolve, reject) { + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4) return; + // Process the response + if (xhr.status >= 200 && xhr.status < 300) { + resolve(xhr); + } else { + reject(xhr); + } + }; + xhr.open('post', url); + xhr.send(data); + })]; + }); + }); + }; + return XHRUploader; + }(AsyncUploader); - // Otherwise - // Unset the iso-2022-jp output flag and return error. - iso2022jp_output_flag = false; - return decoderError(fatal); - - case states.Katakana: - // Katakana - // Based on byte: + var chai$2 = {}; - // 0x1B - if (bite === 0x1B) { - // Set iso-2022-jp decoder state to escape start and return - // continue. - iso2022jp_decoder_state = states.EscapeStart; - return null; - } + /*! + * assertion-error + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ - // 0x21 to 0x5F - if (inRange(bite, 0x21, 0x5F)) { - // Unset the iso-2022-jp output flag and return a code point - // whose value is 0xFF61 − 0x21 + byte. - iso2022jp_output_flag = false; - return 0xFF61 - 0x21 + bite; - } + /*! + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. + * + * @param {String} excluded properties ... + * @return {Function} + */ - // end-of-stream - if (bite === end_of_stream) { - // Return finished. - return finished; - } + function exclude () { + var excludes = [].slice.call(arguments); - // Otherwise - // Unset the iso-2022-jp output flag and return error. - iso2022jp_output_flag = false; - return decoderError(fatal); + function excludeProps (res, obj) { + Object.keys(obj).forEach(function (key) { + if (!~excludes.indexOf(key)) res[key] = obj[key]; + }); + } - case states.LeadByte: - // Lead byte - // Based on byte: + return function extendExclude () { + var args = [].slice.call(arguments) + , i = 0 + , res = {}; - // 0x1B - if (bite === 0x1B) { - // Set iso-2022-jp decoder state to escape start and return - // continue. - iso2022jp_decoder_state = states.EscapeStart; - return null; - } + for (; i < args.length; i++) { + excludeProps(res, args[i]); + } - // 0x21 to 0x7E - if (inRange(bite, 0x21, 0x7E)) { - // Unset the iso-2022-jp output flag, set iso-2022-jp lead - // to byte, iso-2022-jp decoder state to trail byte, and - // return continue. - iso2022jp_output_flag = false; - iso2022jp_lead = bite; - iso2022jp_decoder_state = states.TrailByte; - return null; - } + return res; + }; + } + /*! + * Primary Exports + */ - // end-of-stream - if (bite === end_of_stream) { - // Return finished. - return finished; - } + var assertionError = AssertionError$1; - // Otherwise - // Unset the iso-2022-jp output flag and return error. - iso2022jp_output_flag = false; - return decoderError(fatal); + /** + * ### AssertionError + * + * An extension of the JavaScript `Error` constructor for + * assertion and validation scenarios. + * + * @param {String} message + * @param {Object} properties to include (optional) + * @param {callee} start stack function (optional) + */ - case states.TrailByte: - // Trail byte - // Based on byte: + function AssertionError$1 (message, _props, ssf) { + var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') + , props = extend(_props || {}); - // 0x1B - if (bite === 0x1B) { - // Set iso-2022-jp decoder state to escape start and return - // continue. - iso2022jp_decoder_state = states.EscapeStart; - return decoderError(fatal); - } + // default values + this.message = message || 'Unspecified AssertionError'; + this.showDiff = false; - // 0x21 to 0x7E - if (inRange(bite, 0x21, 0x7E)) { - // 1. Set the iso-2022-jp decoder state to lead byte. - iso2022jp_decoder_state = states.LeadByte; + // copy from properties + for (var key in props) { + this[key] = props[key]; + } - // 2. Let pointer be (iso-2022-jp lead − 0x21) × 94 + byte − 0x21. - var pointer = (iso2022jp_lead - 0x21) * 94 + bite - 0x21; + // capture stack trace + ssf = ssf || AssertionError$1; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, ssf); + } else { + try { + throw new Error(); + } catch(e) { + this.stack = e.stack; + } + } + } - // 3. Let code point be the index code point for pointer in - // index jis0208. - var code_point = indexCodePointFor(pointer, index('jis0208')); + /*! + * Inherit from Error.prototype + */ - // 4. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + AssertionError$1.prototype = Object.create(Error.prototype); - // 5. Return a code point whose value is code point. - return code_point; - } + /*! + * Statically set name + */ - // end-of-stream - if (bite === end_of_stream) { - // Set the iso-2022-jp decoder state to lead byte, prepend - // byte to stream, and return error. - iso2022jp_decoder_state = states.LeadByte; - stream.prepend(bite); - return decoderError(fatal); - } + AssertionError$1.prototype.name = 'AssertionError'; - // Otherwise - // Set iso-2022-jp decoder state to lead byte and return - // error. - iso2022jp_decoder_state = states.LeadByte; - return decoderError(fatal); + /*! + * Ensure correct constructor + */ - case states.EscapeStart: - // Escape start + AssertionError$1.prototype.constructor = AssertionError$1; - // 1. If byte is either 0x24 or 0x28, set iso-2022-jp lead to - // byte, iso-2022-jp decoder state to escape, and return - // continue. - if (bite === 0x24 || bite === 0x28) { - iso2022jp_lead = bite; - iso2022jp_decoder_state = states.Escape; - return null; - } + /** + * Allow errors to be converted to JSON for static transfer. + * + * @param {Boolean} include stack (default: `true`) + * @return {Object} object that can be `JSON.stringify` + */ - // 2. Prepend byte to stream. - stream.prepend(bite); + AssertionError$1.prototype.toJSON = function (stack) { + var extend = exclude('constructor', 'toJSON', 'stack') + , props = extend({ name: this.name }, this); - // 3. Unset the iso-2022-jp output flag, set iso-2022-jp - // decoder state to iso-2022-jp decoder output state, and - // return error. - iso2022jp_output_flag = false; - iso2022jp_decoder_state = iso2022jp_decoder_output_state; - return decoderError(fatal); + // include stack if exists and not turned off + if (false !== stack && this.stack) { + props.stack = this.stack; + } - case states.Escape: - // Escape + return props; + }; - // 1. Let lead be iso-2022-jp lead and set iso-2022-jp lead to - // 0x00. - var lead = iso2022jp_lead; - iso2022jp_lead = 0x00; + var utils = {}; - // 2. Let state be null. - var state = null; + /* ! + * Chai - pathval utility + * Copyright(c) 2012-2014 Jake Luer + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ - // 3. If lead is 0x28 and byte is 0x42, set state to ASCII. - if (lead === 0x28 && bite === 0x42) - state = states.ASCII; + /** + * ### .hasProperty(object, name) + * + * This allows checking whether an object has own + * or inherited from prototype chain named property. + * + * Basically does the same thing as the `in` + * operator but works properly with null/undefined values + * and other primitives. + * + * var obj = { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * + * The following would be the results. + * + * hasProperty(obj, 'str'); // true + * hasProperty(obj, 'constructor'); // true + * hasProperty(obj, 'bar'); // false + * + * hasProperty(obj.str, 'length'); // true + * hasProperty(obj.str, 1); // true + * hasProperty(obj.str, 5); // false + * + * hasProperty(obj.arr, 'length'); // true + * hasProperty(obj.arr, 2); // true + * hasProperty(obj.arr, 3); // false + * + * @param {Object} object + * @param {String|Symbol} name + * @returns {Boolean} whether it exists + * @namespace Utils + * @name hasProperty + * @api public + */ - // 4. If lead is 0x28 and byte is 0x4A, set state to Roman. - if (lead === 0x28 && bite === 0x4A) - state = states.Roman; + function hasProperty(obj, name) { + if (typeof obj === 'undefined' || obj === null) { + return false; + } - // 5. If lead is 0x28 and byte is 0x49, set state to Katakana. - if (lead === 0x28 && bite === 0x49) - state = states.Katakana; + // The `in` operator does not work with primitives. + return name in Object(obj); + } - // 6. If lead is 0x24 and byte is either 0x40 or 0x42, set - // state to lead byte. - if (lead === 0x24 && (bite === 0x40 || bite === 0x42)) - state = states.LeadByte; + /* ! + * ## parsePath(path) + * + * Helper function used to parse string object + * paths. Use in conjunction with `internalGetPathValue`. + * + * var parsed = parsePath('myobject.property.subprop'); + * + * ### Paths: + * + * * Can be infinitely deep and nested. + * * Arrays are also valid using the formal `myobject.document[3].property`. + * * Literal dots and brackets (not delimiter) must be backslash-escaped. + * + * @param {String} path + * @returns {Object} parsed + * @api private + */ - // 7. If state is non-null, run these substeps: - if (state !== null) { - // 1. Set iso-2022-jp decoder state and iso-2022-jp decoder - // output state to states. - iso2022jp_decoder_state = iso2022jp_decoder_state = state; + function parsePath(path) { + var str = path.replace(/([^\\])\[/g, '$1.['); + var parts = str.match(/(\\\.|[^.]+?)+/g); + return parts.map(function mapMatches(value) { + if ( + value === 'constructor' || + value === '__proto__' || + value === 'prototype' + ) { + return {}; + } + var regexp = /^\[(\d+)\]$/; + var mArr = regexp.exec(value); + var parsed = null; + if (mArr) { + parsed = { i: parseFloat(mArr[1]) }; + } else { + parsed = { p: value.replace(/\\([.[\]])/g, '$1') }; + } - // 2. Let output flag be the iso-2022-jp output flag. - var output_flag = iso2022jp_output_flag; + return parsed; + }); + } - // 3. Set the iso-2022-jp output flag. - iso2022jp_output_flag = true; + /* ! + * ## internalGetPathValue(obj, parsed[, pathDepth]) + * + * Helper companion function for `.parsePath` that returns + * the value located at the parsed address. + * + * var value = getPathValue(obj, parsed); + * + * @param {Object} object to search against + * @param {Object} parsed definition from `parsePath`. + * @param {Number} depth (nesting level) of the property we want to retrieve + * @returns {Object|Undefined} value + * @api private + */ - // 4. Return continue, if output flag is unset, and error - // otherwise. - return !output_flag ? null : decoderError(fatal); - } + function internalGetPathValue(obj, parsed, pathDepth) { + var temporaryValue = obj; + var res = null; + pathDepth = typeof pathDepth === 'undefined' ? parsed.length : pathDepth; - // 8. Prepend lead and byte to stream. - stream.prepend([lead, bite]); + for (var i = 0; i < pathDepth; i++) { + var part = parsed[i]; + if (temporaryValue) { + if (typeof part.p === 'undefined') { + temporaryValue = temporaryValue[part.i]; + } else { + temporaryValue = temporaryValue[part.p]; + } - // 9. Unset the iso-2022-jp output flag, set iso-2022-jp - // decoder state to iso-2022-jp decoder output state and - // return error. - iso2022jp_output_flag = false; - iso2022jp_decoder_state = iso2022jp_decoder_output_state; - return decoderError(fatal); + if (i === pathDepth - 1) { + res = temporaryValue; } - }; + } } - // 13.2.2 iso-2022-jp encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ - function ISO2022JPEncoder(options) { - options.fatal; - // iso-2022-jp's encoder has an associated iso-2022-jp encoder - // state which is one of ASCII, Roman, and jis0208 (initially - // ASCII). - /** @enum */ - var states = { - ASCII: 0, - Roman: 1, - jis0208: 2 - }; - var /** @type {number} */ iso2022jp_state = states.ASCII; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream and iso-2022-jp encoder - // state is not ASCII, prepend code point to stream, set - // iso-2022-jp encoder state to ASCII, and return three bytes - // 0x1B 0x28 0x42. - if (code_point === end_of_stream && - iso2022jp_state !== states.ASCII) { - stream.prepend(code_point); - iso2022jp_state = states.ASCII; - return [0x1B, 0x28, 0x42]; - } + return res; + } - // 2. If code point is end-of-stream and iso-2022-jp encoder - // state is ASCII, return finished. - if (code_point === end_of_stream && iso2022jp_state === states.ASCII) - return finished; + /* ! + * ## internalSetPathValue(obj, value, parsed) + * + * Companion function for `parsePath` that sets + * the value located at a parsed address. + * + * internalSetPathValue(obj, 'value', parsed); + * + * @param {Object} object to search and define on + * @param {*} value to use upon set + * @param {Object} parsed definition from `parsePath` + * @api private + */ - // 3. If ISO-2022-JP encoder state is ASCII or Roman, and code - // point is U+000E, U+000F, or U+001B, return error with U+FFFD. - if ((iso2022jp_state === states.ASCII || - iso2022jp_state === states.Roman) && - (code_point === 0x000E || code_point === 0x000F || - code_point === 0x001B)) { - return encoderError(0xFFFD); - } + function internalSetPathValue(obj, val, parsed) { + var tempObj = obj; + var pathDepth = parsed.length; + var part = null; + // Here we iterate through every part of the path + for (var i = 0; i < pathDepth; i++) { + var propName = null; + var propVal = null; + part = parsed[i]; + + // If it's the last part of the path, we set the 'propName' value with the property name + if (i === pathDepth - 1) { + propName = typeof part.p === 'undefined' ? part.i : part.p; + // Now we set the property with the name held by 'propName' on object with the desired val + tempObj[propName] = val; + } else if (typeof part.p !== 'undefined' && tempObj[part.p]) { + tempObj = tempObj[part.p]; + } else if (typeof part.i !== 'undefined' && tempObj[part.i]) { + tempObj = tempObj[part.i]; + } else { + // If the obj doesn't have the property we create one with that name to define it + var next = parsed[i + 1]; + // Here we set the name of the property which will be defined + propName = typeof part.p === 'undefined' ? part.i : part.p; + // Here we decide if this property will be an array or a new object + propVal = typeof next.p === 'undefined' ? [] : {}; + tempObj[propName] = propVal; + tempObj = tempObj[propName]; + } + } + } - // 4. If iso-2022-jp encoder state is ASCII and code point is an - // ASCII code point, return a byte whose value is code point. - if (iso2022jp_state === states.ASCII && - isASCIICodePoint(code_point)) - return code_point; + /** + * ### .getPathInfo(object, path) + * + * This allows the retrieval of property info in an + * object given a string path. + * + * The path info consists of an object with the + * following properties: + * + * * parent - The parent object of the property referenced by `path` + * * name - The name of the final property, a number if it was an array indexer + * * value - The value of the property, if it exists, otherwise `undefined` + * * exists - Whether the property exists or not + * + * @param {Object} object + * @param {String} path + * @returns {Object} info + * @namespace Utils + * @name getPathInfo + * @api public + */ - // 5. If iso-2022-jp encoder state is Roman and code point is an - // ASCII code point, excluding U+005C and U+007E, or is U+00A5 - // or U+203E, run these substeps: - if (iso2022jp_state === states.Roman && - ((isASCIICodePoint(code_point) && - code_point !== 0x005C && code_point !== 0x007E) || - (code_point == 0x00A5 || code_point == 0x203E))) { + function getPathInfo(obj, path) { + var parsed = parsePath(path); + var last = parsed[parsed.length - 1]; + var info = { + parent: + parsed.length > 1 ? + internalGetPathValue(obj, parsed, parsed.length - 1) : + obj, + name: last.p || last.i, + value: internalGetPathValue(obj, parsed), + }; + info.exists = hasProperty(info.parent, info.name); - // 1. If code point is an ASCII code point, return a byte - // whose value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + return info; + } - // 2. If code point is U+00A5, return byte 0x5C. - if (code_point === 0x00A5) - return 0x5C; + /** + * ### .getPathValue(object, path) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue(obj, 'prop1.str'); // Hello + * getPathValue(obj, 'prop1.att[2]'); // b + * getPathValue(obj, 'prop2.arr[0].nested'); // Universe + * + * @param {Object} object + * @param {String} path + * @returns {Object} value or `undefined` + * @namespace Utils + * @name getPathValue + * @api public + */ - // 3. If code point is U+203E, return byte 0x7E. - if (code_point === 0x203E) - return 0x7E; - } + function getPathValue(obj, path) { + var info = getPathInfo(obj, path); + return info.value; + } - // 6. If code point is an ASCII code point, and iso-2022-jp - // encoder state is not ASCII, prepend code point to stream, set - // iso-2022-jp encoder state to ASCII, and return three bytes - // 0x1B 0x28 0x42. - if (isASCIICodePoint(code_point) && - iso2022jp_state !== states.ASCII) { - stream.prepend(code_point); - iso2022jp_state = states.ASCII; - return [0x1B, 0x28, 0x42]; - } + /** + * ### .setPathValue(object, path, value) + * + * Define the value in an object at a given string path. + * + * ```js + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * }; + * ``` + * + * The following would be acceptable. + * + * ```js + * var properties = require('tea-properties'); + * properties.set(obj, 'prop1.str', 'Hello Universe!'); + * properties.set(obj, 'prop1.arr[2]', 'B'); + * properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' }); + * ``` + * + * @param {Object} object + * @param {String} path + * @param {Mixed} value + * @api private + */ - // 7. If code point is either U+00A5 or U+203E, and iso-2022-jp - // encoder state is not Roman, prepend code point to stream, set - // iso-2022-jp encoder state to Roman, and return three bytes - // 0x1B 0x28 0x4A. - if ((code_point === 0x00A5 || code_point === 0x203E) && - iso2022jp_state !== states.Roman) { - stream.prepend(code_point); - iso2022jp_state = states.Roman; - return [0x1B, 0x28, 0x4A]; - } + function setPathValue(obj, path, val) { + var parsed = parsePath(path); + internalSetPathValue(obj, val, parsed); + return obj; + } - // 8. If code point is U+2212, set it to U+FF0D. - if (code_point === 0x2212) - code_point = 0xFF0D; + var pathval = { + hasProperty: hasProperty, + getPathInfo: getPathInfo, + getPathValue: getPathValue, + setPathValue: setPathValue, + }; - // 9. Let pointer be the index pointer for code point in index - // jis0208. - var pointer = indexPointerFor(code_point, index('jis0208')); + /*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - // 10. If pointer is null, return error with code point. - if (pointer === null) - return encoderError(code_point); + /** + * ### .flag(object, key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @namespace Utils + * @name flag + * @api private + */ - // 11. If iso-2022-jp encoder state is not jis0208, prepend code - // point to stream, set iso-2022-jp encoder state to jis0208, - // and return three bytes 0x1B 0x24 0x42. - if (iso2022jp_state !== states.jis0208) { - stream.prepend(code_point); - iso2022jp_state = states.jis0208; - return [0x1B, 0x24, 0x42]; - } + var flag$5 = function flag(obj, key, value) { + var flags = obj.__flags || (obj.__flags = Object.create(null)); + if (arguments.length === 3) { + flags[key] = value; + } else { + return flags[key]; + } + }; - // 12. Let lead be floor(pointer / 94) + 0x21. - var lead = floor(pointer / 94) + 0x21; + /*! + * Chai - test utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - // 13. Let trail be pointer % 94 + 0x21. - var trail = pointer % 94 + 0x21; + /*! + * Module dependencies + */ - // 14. Return two bytes whose values are lead and trail. - return [lead, trail]; - }; - } + var flag$4 = flag$5; - /** @param {{fatal: boolean}} options */ - encoders['ISO-2022-JP'] = function(options) { - return new ISO2022JPEncoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['ISO-2022-JP'] = function(options) { - return new ISO2022JPDecoder(options); - }; + /** + * ### .test(object, expression) + * + * Test an object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name test + */ - // 13.3 Shift_JIS + var test = function test(obj, args) { + var negate = flag$4(obj, 'negate') + , expr = args[0]; + return negate ? !expr : expr; + }; - // 13.3.1 Shift_JIS decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ - function ShiftJISDecoder(options) { - var fatal = options.fatal; - // Shift_JIS's decoder has an associated Shift_JIS lead (initially - // 0x00). - var /** @type {number} */ Shift_JIS_lead = 0x00; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and Shift_JIS lead is not 0x00, - // set Shift_JIS lead to 0x00 and return error. - if (bite === end_of_stream && Shift_JIS_lead !== 0x00) { - Shift_JIS_lead = 0x00; - return decoderError(fatal); - } + var typeDetect = {exports: {}}; + + typeDetect.exports; + + (function (module, exports) { + (function (global, factory) { + module.exports = factory() ; + }(commonjsGlobal$1, (function () { + /* ! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + var promiseExists = typeof Promise === 'function'; + + /* eslint-disable no-undef */ + var globalObject = typeof self === 'object' ? self : commonjsGlobal$1; // eslint-disable-line id-blacklist + + var symbolExists = typeof Symbol !== 'undefined'; + var mapExists = typeof Map !== 'undefined'; + var setExists = typeof Set !== 'undefined'; + var weakMapExists = typeof WeakMap !== 'undefined'; + var weakSetExists = typeof WeakSet !== 'undefined'; + var dataViewExists = typeof DataView !== 'undefined'; + var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; + var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; + var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; + var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; + var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); + var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); + var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; + var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); + var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; + var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); + var toStringLeftSliceLength = 8; + var toStringRightSliceLength = -1; + /** + * ### typeOf (obj) + * + * Uses `Object.prototype.toString` to determine the type of an object, + * normalising behaviour across engine versions & well optimised. + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ + function typeDetect(obj) { + /* ! Speed optimisation + * Pre: + * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) + * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) + * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) + * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) + * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) + * Post: + * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) + * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) + * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) + * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) + * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) + */ + var typeofObj = typeof obj; + if (typeofObj !== 'object') { + return typeofObj; + } + + /* ! Speed optimisation + * Pre: + * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) + * Post: + * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) + */ + if (obj === null) { + return 'null'; + } + + /* ! Spec Conformance + * Test: `Object.prototype.toString.call(window)`` + * - Node === "[object global]" + * - Chrome === "[object global]" + * - Firefox === "[object Window]" + * - PhantomJS === "[object Window]" + * - Safari === "[object Window]" + * - IE 11 === "[object Window]" + * - IE Edge === "[object Window]" + * Test: `Object.prototype.toString.call(this)`` + * - Chrome Worker === "[object global]" + * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" + * - Safari Worker === "[object DedicatedWorkerGlobalScope]" + * - IE 11 Worker === "[object WorkerGlobalScope]" + * - IE Edge Worker === "[object WorkerGlobalScope]" + */ + if (obj === globalObject) { + return 'global'; + } + + /* ! Speed optimisation + * Pre: + * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) + * Post: + * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) + */ + if ( + Array.isArray(obj) && + (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) + ) { + return 'Array'; + } + + // Not caching existence of `window` and related properties due to potential + // for `window` to be unset before tests in quasi-browser environments. + if (typeof window === 'object' && window !== null) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/browsers.html#location) + * WhatWG HTML$7.7.3 - The `Location` interface + * Test: `Object.prototype.toString.call(window.location)`` + * - IE <=11 === "[object Object]" + * - IE Edge <=13 === "[object Object]" + */ + if (typeof window.location === 'object' && obj === window.location) { + return 'Location'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#document) + * WhatWG HTML$3.1.1 - The `Document` object + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * WhatWG HTML states: + * > For historical reasons, Window objects must also have a + * > writable, configurable, non-enumerable property named + * > HTMLDocument whose value is the Document interface object. + * Test: `Object.prototype.toString.call(document)`` + * - Chrome === "[object HTMLDocument]" + * - Firefox === "[object HTMLDocument]" + * - Safari === "[object HTMLDocument]" + * - IE <=10 === "[object Document]" + * - IE 11 === "[object HTMLDocument]" + * - IE Edge <=13 === "[object HTMLDocument]" + */ + if (typeof window.document === 'object' && obj === window.document) { + return 'Document'; + } + + if (typeof window.navigator === 'object') { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` + * - IE <=10 === "[object MSMimeTypesCollection]" + */ + if (typeof window.navigator.mimeTypes === 'object' && + obj === window.navigator.mimeTypes) { + return 'MimeTypeArray'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray + * Test: `Object.prototype.toString.call(navigator.plugins)`` + * - IE <=10 === "[object MSPluginsCollection]" + */ + if (typeof window.navigator.plugins === 'object' && + obj === window.navigator.plugins) { + return 'PluginArray'; + } + } + + if ((typeof window.HTMLElement === 'function' || + typeof window.HTMLElement === 'object') && + obj instanceof window.HTMLElement) { + /* ! Spec Conformance + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` + * - IE <=10 === "[object HTMLBlockElement]" + */ + if (obj.tagName === 'BLOCKQUOTE') { + return 'HTMLQuoteElement'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltabledatacellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('td')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TD') { + return 'HTMLTableDataCellElement'; + } + + /* ! Spec Conformance + * (https://html.spec.whatwg.org/#htmltableheadercellelement) + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` + * Note: Most browsers currently adher to the W3C DOM Level 2 spec + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) + * which suggests that browsers should use HTMLTableCellElement for + * both TD and TH elements. WhatWG separates these. + * Test: Object.prototype.toString.call(document.createElement('th')) + * - Chrome === "[object HTMLTableCellElement]" + * - Firefox === "[object HTMLTableCellElement]" + * - Safari === "[object HTMLTableCellElement]" + */ + if (obj.tagName === 'TH') { + return 'HTMLTableHeaderCellElement'; + } + } + } + + /* ! Speed optimisation + * Pre: + * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) + * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) + * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) + * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) + * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) + * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) + * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) + * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) + * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) + * Post: + * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) + * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) + * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) + * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) + * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) + * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) + * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) + * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) + * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) + */ + var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); + if (typeof stringTag === 'string') { + return stringTag; + } + + var objPrototype = Object.getPrototypeOf(obj); + /* ! Speed optimisation + * Pre: + * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) + * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) + * Post: + * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) + * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) + */ + if (objPrototype === RegExp.prototype) { + return 'RegExp'; + } + + /* ! Speed optimisation + * Pre: + * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) + * Post: + * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) + */ + if (objPrototype === Date.prototype) { + return 'Date'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) + * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": + * Test: `Object.prototype.toString.call(Promise.resolve())`` + * - Chrome <=47 === "[object Object]" + * - Edge <=20 === "[object Object]" + * - Firefox 29-Latest === "[object Promise]" + * - Safari 7.1-Latest === "[object Promise]" + */ + if (promiseExists && objPrototype === Promise.prototype) { + return 'Promise'; + } + + /* ! Speed optimisation + * Pre: + * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) + * Post: + * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) + */ + if (setExists && objPrototype === Set.prototype) { + return 'Set'; + } + + /* ! Speed optimisation + * Pre: + * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) + * Post: + * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) + */ + if (mapExists && objPrototype === Map.prototype) { + return 'Map'; + } + + /* ! Speed optimisation + * Pre: + * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) + * Post: + * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) + */ + if (weakSetExists && objPrototype === WeakSet.prototype) { + return 'WeakSet'; + } + + /* ! Speed optimisation + * Pre: + * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) + * Post: + * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) + */ + if (weakMapExists && objPrototype === WeakMap.prototype) { + return 'WeakMap'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` + * - Edge <=13 === "[object Object]" + */ + if (dataViewExists && objPrototype === DataView.prototype) { + return 'DataView'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": + * Test: `Object.prototype.toString.call(new Map().entries())`` + * - Edge <=13 === "[object Object]" + */ + if (mapExists && objPrototype === mapIteratorPrototype) { + return 'Map Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": + * Test: `Object.prototype.toString.call(new Set().entries())`` + * - Edge <=13 === "[object Object]" + */ + if (setExists && objPrototype === setIteratorPrototype) { + return 'Set Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { + return 'Array Iterator'; + } + + /* ! Spec Conformance + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` + * - Edge <=13 === "[object Object]" + */ + if (stringIteratorExists && objPrototype === stringIteratorPrototype) { + return 'String Iterator'; + } + + /* ! Speed optimisation + * Pre: + * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) + * Post: + * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) + */ + if (objPrototype === null) { + return 'Object'; + } + + return Object + .prototype + .toString + .call(obj) + .slice(toStringLeftSliceLength, toStringRightSliceLength); + } + + return typeDetect; + + }))); + } (typeDetect, typeDetect.exports)); + + var typeDetectExports = typeDetect.exports; + + /*! + * Chai - expectTypes utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .expectTypes(obj, types) + * + * Ensures that the object being tested against is of a valid type. + * + * utils.expectTypes(this, ['array', 'object', 'string']); + * + * @param {Mixed} obj constructed Assertion + * @param {Array} type A list of allowed types for this assertion + * @namespace Utils + * @name expectTypes + * @api public + */ - // 2. If byte is end-of-stream and Shift_JIS lead is 0x00, - // return finished. - if (bite === end_of_stream && Shift_JIS_lead === 0x00) - return finished; + var AssertionError = assertionError; + var flag$3 = flag$5; + var type$2 = typeDetectExports; - // 3. If Shift_JIS lead is not 0x00, let lead be Shift_JIS lead, - // let pointer be null, set Shift_JIS lead to 0x00, and then run - // these substeps: - if (Shift_JIS_lead !== 0x00) { - var lead = Shift_JIS_lead; - var pointer = null; - Shift_JIS_lead = 0x00; + var expectTypes = function expectTypes(obj, types) { + var flagMsg = flag$3(obj, 'message'); + var ssfi = flag$3(obj, 'ssfi'); - // 1. Let offset be 0x40, if byte is less than 0x7F, and 0x41 - // otherwise. - var offset = (bite < 0x7F) ? 0x40 : 0x41; + flagMsg = flagMsg ? flagMsg + ': ' : ''; - // 2. Let lead offset be 0x81, if lead is less than 0xA0, and - // 0xC1 otherwise. - var lead_offset = (lead < 0xA0) ? 0x81 : 0xC1; + obj = flag$3(obj, 'object'); + types = types.map(function (t) { return t.toLowerCase(); }); + types.sort(); - // 3. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80 - // to 0xFC, inclusive, set pointer to (lead − lead offset) × - // 188 + byte − offset. - if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFC)) - pointer = (lead - lead_offset) * 188 + bite - offset; + // Transforms ['lorem', 'ipsum'] into 'a lorem, or an ipsum' + var str = types.map(function (t, index) { + var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a'; + var or = types.length > 1 && index === types.length - 1 ? 'or ' : ''; + return or + art + ' ' + t; + }).join(', '); - // 4. If pointer is in the range 8836 to 10715, inclusive, - // return a code point whose value is 0xE000 − 8836 + pointer. - if (inRange(pointer, 8836, 10715)) - return 0xE000 - 8836 + pointer; + var objType = type$2(obj).toLowerCase(); - // 5. Let code point be null, if pointer is null, and the - // index code point for pointer in index jis0208 otherwise. - var code_point = (pointer === null) ? null : - indexCodePointFor(pointer, index('jis0208')); + if (!types.some(function (expected) { return objType === expected; })) { + throw new AssertionError( + flagMsg + 'object tested must be ' + str + ', but ' + objType + ' given', + undefined, + ssfi + ); + } + }; - // 6. If code point is null and byte is an ASCII byte, prepend - // byte to stream. - if (code_point === null && isASCIIByte(bite)) - stream.prepend(bite); + /*! + * Chai - getActual utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - // 7. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + /** + * ### .getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getActual + */ - // 8. Return a code point whose value is code point. - return code_point; - } + var getActual$1 = function getActual(obj, args) { + return args.length > 4 ? args[4] : obj._obj; + }; - // 4. If byte is an ASCII byte or 0x80, return a code point - // whose value is byte. - if (isASCIIByte(bite) || bite === 0x80) - return bite; + /* ! + * Chai - getFuncName utility + * Copyright(c) 2012-2016 Jake Luer + * MIT Licensed + */ - // 5. If byte is in the range 0xA1 to 0xDF, inclusive, return a - // code point whose value is 0xFF61 − 0xA1 + byte. - if (inRange(bite, 0xA1, 0xDF)) - return 0xFF61 - 0xA1 + bite; + /** + * ### .getFuncName(constructorFn) + * + * Returns the name of a function. + * When a non-function instance is passed, returns `null`. + * This also includes a polyfill function if `aFunc.name` is not defined. + * + * @name getFuncName + * @param {Function} funct + * @namespace Utils + * @api public + */ - // 6. If byte is in the range 0x81 to 0x9F, inclusive, or 0xE0 - // to 0xFC, inclusive, set Shift_JIS lead to byte and return - // continue. - if (inRange(bite, 0x81, 0x9F) || inRange(bite, 0xE0, 0xFC)) { - Shift_JIS_lead = bite; - return null; - } + var toString$1 = Function.prototype.toString; + var functionNameMatch = /\s*function(?:\s|\s*\/\*[^(?:*\/)]+\*\/\s*)*([^\s\(\/]+)/; + var maxFunctionSourceLength = 512; + function getFuncName(aFunc) { + if (typeof aFunc !== 'function') { + return null; + } - // 7. Return error. - return decoderError(fatal); - }; + var name = ''; + if (typeof Function.prototype.name === 'undefined' && typeof aFunc.name === 'undefined') { + // eslint-disable-next-line prefer-reflect + var functionSource = toString$1.call(aFunc); + // To avoid unconstrained resource consumption due to pathalogically large function names, + // we limit the available return value to be less than 512 characters. + if (functionSource.indexOf('(') > maxFunctionSourceLength) { + return name; + } + // Here we run a polyfill if Function does not support the `name` property and if aFunc.name is not defined + var match = functionSource.match(functionNameMatch); + if (match) { + name = match[1]; + } + } else { + // If we've got a `name` property we just use it + name = aFunc.name; } - // 13.3.2 Shift_JIS encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ - function ShiftJISEncoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; + return name; + } - // 2. If code point is an ASCII code point or U+0080, return a - // byte whose value is code point. - if (isASCIICodePoint(code_point) || code_point === 0x0080) - return code_point; + var getFuncName_1 = getFuncName; + + var getFuncName$1 = /*@__PURE__*/getDefaultExportFromCjs(getFuncName_1); + + const ansiColors = { + bold: ['1', '22'], + dim: ['2', '22'], + italic: ['3', '23'], + underline: ['4', '24'], + // 5 & 6 are blinking + inverse: ['7', '27'], + hidden: ['8', '28'], + strike: ['9', '29'], + // 10-20 are fonts + // 21-29 are resets for 1-9 + black: ['30', '39'], + red: ['31', '39'], + green: ['32', '39'], + yellow: ['33', '39'], + blue: ['34', '39'], + magenta: ['35', '39'], + cyan: ['36', '39'], + white: ['37', '39'], + + brightblack: ['30;1', '39'], + brightred: ['31;1', '39'], + brightgreen: ['32;1', '39'], + brightyellow: ['33;1', '39'], + brightblue: ['34;1', '39'], + brightmagenta: ['35;1', '39'], + brightcyan: ['36;1', '39'], + brightwhite: ['37;1', '39'], + + grey: ['90', '39'], + }; - // 3. If code point is U+00A5, return byte 0x5C. - if (code_point === 0x00A5) - return 0x5C; + const styles = { + special: 'cyan', + number: 'yellow', + bigint: 'yellow', + boolean: 'yellow', + undefined: 'grey', + null: 'bold', + string: 'green', + symbol: 'green', + date: 'magenta', + regexp: 'red', + }; - // 4. If code point is U+203E, return byte 0x7E. - if (code_point === 0x203E) - return 0x7E; + const truncator = '…'; - // 5. If code point is in the range U+FF61 to U+FF9F, inclusive, - // return a byte whose value is code point − 0xFF61 + 0xA1. - if (inRange(code_point, 0xFF61, 0xFF9F)) - return code_point - 0xFF61 + 0xA1; + function colorise(value, styleType) { + const color = ansiColors[styles[styleType]] || ansiColors[styleType]; + if (!color) { + return String(value) + } + return `\u001b[${color[0]}m${String(value)}\u001b[${color[1]}m` + } - // 6. If code point is U+2212, set it to U+FF0D. - if (code_point === 0x2212) - code_point = 0xFF0D; + function normaliseOptions({ + showHidden = false, + depth = 2, + colors = false, + customInspect = true, + showProxy = false, + maxArrayLength = Infinity, + breakLength = Infinity, + seen = [], + // eslint-disable-next-line no-shadow + truncate = Infinity, + stylize = String, + } = {}) { + const options = { + showHidden: Boolean(showHidden), + depth: Number(depth), + colors: Boolean(colors), + customInspect: Boolean(customInspect), + showProxy: Boolean(showProxy), + maxArrayLength: Number(maxArrayLength), + breakLength: Number(breakLength), + truncate: Number(truncate), + seen, + stylize, + }; + if (options.colors) { + options.stylize = colorise; + } + return options + } - // 7. Let pointer be the index Shift_JIS pointer for code point. - var pointer = indexShiftJISPointerFor(code_point); + function truncate(string, length, tail = truncator) { + string = String(string); + const tailLength = tail.length; + const stringLength = string.length; + if (tailLength > length && stringLength > tailLength) { + return tail + } + if (stringLength > length && stringLength > tailLength) { + return `${string.slice(0, length - tailLength)}${tail}` + } + return string + } - // 8. If pointer is null, return error with code point. - if (pointer === null) - return encoderError(code_point); + // eslint-disable-next-line complexity + function inspectList(list, options, inspectItem, separator = ', ') { + inspectItem = inspectItem || options.inspect; + const size = list.length; + if (size === 0) return '' + const originalLength = options.truncate; + let output = ''; + let peek = ''; + let truncated = ''; + for (let i = 0; i < size; i += 1) { + const last = i + 1 === list.length; + const secondToLast = i + 2 === list.length; + truncated = `${truncator}(${list.length - i})`; + const value = list[i]; + + // If there is more than one remaining we need to account for a separator of `, ` + options.truncate = originalLength - output.length - (last ? 0 : separator.length); + const string = peek || inspectItem(value, options) + (last ? '' : separator); + const nextLength = output.length + string.length; + const truncatedLength = nextLength + truncated.length; + + // If this is the last element, and adding it would + // take us over length, but adding the truncator wouldn't - then break now + if (last && nextLength > originalLength && output.length + truncated.length <= originalLength) { + break + } - // 9. Let lead be floor(pointer / 188). - var lead = floor(pointer / 188); + // If this isn't the last or second to last element to scan, + // but the string is already over length then break here + if (!last && !secondToLast && truncatedLength > originalLength) { + break + } - // 10. Let lead offset be 0x81, if lead is less than 0x1F, and - // 0xC1 otherwise. - var lead_offset = (lead < 0x1F) ? 0x81 : 0xC1; + // Peek at the next string to determine if we should + // break early before adding this item to the output + peek = last ? '' : inspectItem(list[i + 1], options) + (secondToLast ? '' : separator); - // 11. Let trail be pointer % 188. - var trail = pointer % 188; + // If we have one element left, but this element and + // the next takes over length, the break early + if (!last && secondToLast && truncatedLength > originalLength && nextLength + peek.length > originalLength) { + break + } - // 12. Let offset be 0x40, if trail is less than 0x3F, and 0x41 - // otherwise. - var offset = (trail < 0x3F) ? 0x40 : 0x41; + output += string; - // 13. Return two bytes whose values are lead + lead offset and - // trail + offset. - return [lead + lead_offset, trail + offset]; - }; + // If the next element takes us to length - + // but there are more after that, then we should truncate now + if (!last && !secondToLast && nextLength + peek.length >= originalLength) { + truncated = `${truncator}(${list.length - i - 1})`; + break + } + + truncated = ''; } + return `${output}${truncated}` + } - /** @param {{fatal: boolean}} options */ - encoders['Shift_JIS'] = function(options) { - return new ShiftJISEncoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['Shift_JIS'] = function(options) { - return new ShiftJISDecoder(options); - }; + function quoteComplexKey(key) { + if (key.match(/^[a-zA-Z_][a-zA-Z_0-9]*$/)) { + return key + } + return JSON.stringify(key) + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'") + } - // - // 14. Legacy multi-byte Korean encodings - // + function inspectProperty([key, value], options) { + options.truncate -= 2; + if (typeof key === 'string') { + key = quoteComplexKey(key); + } else if (typeof key !== 'number') { + key = `[${options.inspect(key, options)}]`; + } + options.truncate -= key.length; + value = options.inspect(value, options); + return `${key}: ${value}` + } - // 14.1 euc-kr + function inspectArray(array, options) { + // Object.keys will always output the Array indices first, so we can slice by + // `array.length` to get non-index properties + const nonIndexProperties = Object.keys(array).slice(array.length); + if (!array.length && !nonIndexProperties.length) return '[]' + options.truncate -= 4; + const listContents = inspectList(array, options); + options.truncate -= listContents.length; + let propertyContents = ''; + if (nonIndexProperties.length) { + propertyContents = inspectList( + nonIndexProperties.map(key => [key, array[key]]), + options, + inspectProperty + ); + } + return `[ ${listContents}${propertyContents ? `, ${propertyContents}` : ''} ]` + } - // 14.1.1 euc-kr decoder - /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ - function EUCKRDecoder(options) { - var fatal = options.fatal; + const getArrayName = array => { + // We need to special case Node.js' Buffers, which report to be Uint8Array + if (typeof Buffer === 'function' && array instanceof Buffer) { + return 'Buffer' + } + if (array[Symbol.toStringTag]) { + return array[Symbol.toStringTag] + } + return getFuncName$1(array.constructor) + }; - // euc-kr's decoder has an associated euc-kr lead (initially 0x00). - var /** @type {number} */ euckr_lead = 0x00; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and euc-kr lead is not 0x00, set - // euc-kr lead to 0x00 and return error. - if (bite === end_of_stream && euckr_lead !== 0) { - euckr_lead = 0x00; - return decoderError(fatal); - } + function inspectTypedArray(array, options) { + const name = getArrayName(array); + options.truncate -= name.length + 4; + // Object.keys will always output the Array indices first, so we can slice by + // `array.length` to get non-index properties + const nonIndexProperties = Object.keys(array).slice(array.length); + if (!array.length && !nonIndexProperties.length) return `${name}[]` + // As we know TypedArrays only contain Unsigned Integers, we can skip inspecting each one and simply + // stylise the toString() value of them + let output = ''; + for (let i = 0; i < array.length; i++) { + const string = `${options.stylize(truncate(array[i], options.truncate), 'number')}${ + i === array.length - 1 ? '' : ', ' + }`; + options.truncate -= string.length; + if (array[i] !== array.length && options.truncate <= 3) { + output += `${truncator}(${array.length - array[i] + 1})`; + break + } + output += string; + } + let propertyContents = ''; + if (nonIndexProperties.length) { + propertyContents = inspectList( + nonIndexProperties.map(key => [key, array[key]]), + options, + inspectProperty + ); + } + return `${name}[ ${output}${propertyContents ? `, ${propertyContents}` : ''} ]` + } - // 2. If byte is end-of-stream and euc-kr lead is 0x00, return - // finished. - if (bite === end_of_stream && euckr_lead === 0) - return finished; + function inspectDate(dateObject, options) { + const stringRepresentation = dateObject.toJSON(); - // 3. If euc-kr lead is not 0x00, let lead be euc-kr lead, let - // pointer be null, set euc-kr lead to 0x00, and then run these - // substeps: - if (euckr_lead !== 0x00) { - var lead = euckr_lead; - var pointer = null; - euckr_lead = 0x00; + if (stringRepresentation === null) { + return 'Invalid Date' + } - // 1. If byte is in the range 0x41 to 0xFE, inclusive, set - // pointer to (lead − 0x81) × 190 + (byte − 0x41). - if (inRange(bite, 0x41, 0xFE)) - pointer = (lead - 0x81) * 190 + (bite - 0x41); + const split = stringRepresentation.split('T'); + const date = split[0]; + // If we need to - truncate the time portion, but never the date + return options.stylize(`${date}T${truncate(split[1], options.truncate - date.length - 1)}`, 'date') + } - // 2. Let code point be null, if pointer is null, and the - // index code point for pointer in index euc-kr otherwise. - var code_point = (pointer === null) - ? null : indexCodePointFor(pointer, index('euc-kr')); + function inspectFunction(func, options) { + const name = getFuncName$1(func); + if (!name) { + return options.stylize('[Function]', 'special') + } + return options.stylize(`[Function ${truncate(name, options.truncate - 11)}]`, 'special') + } - // 3. If code point is null and byte is an ASCII byte, prepend - // byte to stream. - if (pointer === null && isASCIIByte(bite)) - stream.prepend(bite); + function inspectMapEntry([key, value], options) { + options.truncate -= 4; + key = options.inspect(key, options); + options.truncate -= key.length; + value = options.inspect(value, options); + return `${key} => ${value}` + } + + // IE11 doesn't support `map.entries()` + function mapToEntries(map) { + const entries = []; + map.forEach((value, key) => { + entries.push([key, value]); + }); + return entries + } + + function inspectMap(map, options) { + const size = map.size - 1; + if (size <= 0) { + return 'Map{}' + } + options.truncate -= 7; + return `Map{ ${inspectList(mapToEntries(map), options, inspectMapEntry)} }` + } + + const isNaN$2 = Number.isNaN || (i => i !== i); // eslint-disable-line no-self-compare + function inspectNumber(number, options) { + if (isNaN$2(number)) { + return options.stylize('NaN', 'number') + } + if (number === Infinity) { + return options.stylize('Infinity', 'number') + } + if (number === -Infinity) { + return options.stylize('-Infinity', 'number') + } + if (number === 0) { + return options.stylize(1 / number === Infinity ? '+0' : '-0', 'number') + } + return options.stylize(truncate(number, options.truncate), 'number') + } + + function inspectBigInt(number, options) { + let nums = truncate(number.toString(), options.truncate - 1); + if (nums !== truncator) nums += 'n'; + return options.stylize(nums, 'bigint') + } + + function inspectRegExp(value, options) { + const flags = value.toString().split('/')[2]; + const sourceLength = options.truncate - (2 + flags.length); + const source = value.source; + return options.stylize(`/${truncate(source, sourceLength)}/${flags}`, 'regexp') + } + + // IE11 doesn't support `Array.from(set)` + function arrayFromSet(set) { + const values = []; + set.forEach(value => { + values.push(value); + }); + return values + } + + function inspectSet(set, options) { + if (set.size === 0) return 'Set{}' + options.truncate -= 7; + return `Set{ ${inspectList(arrayFromSet(set), options)} }` + } - // 4. If code point is null, return error. - if (code_point === null) - return decoderError(fatal); + const stringEscapeChars = new RegExp( + "['\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5" + + '\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]', + 'g' + ); - // 5. Return a code point whose value is code point. - return code_point; - } + const escapeCharacters = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + "'": "\\'", + '\\': '\\\\', + }; + const hex = 16; + const unicodeLength = 4; + function escape(char) { + return escapeCharacters[char] || `\\u${`0000${char.charCodeAt(0).toString(hex)}`.slice(-unicodeLength)}` + } - // 4. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + function inspectString(string, options) { + if (stringEscapeChars.test(string)) { + string = string.replace(stringEscapeChars, escape); + } + return options.stylize(`'${truncate(string, options.truncate - 2)}'`, 'string') + } - // 5. If byte is in the range 0x81 to 0xFE, inclusive, set - // euc-kr lead to byte and return continue. - if (inRange(bite, 0x81, 0xFE)) { - euckr_lead = bite; - return null; - } + function inspectSymbol(value) { + if ('description' in Symbol.prototype) { + return value.description ? `Symbol(${value.description})` : 'Symbol()' + } + return value.toString() + } - // 6. Return error. - return decoderError(fatal); + let getPromiseValue = () => 'Promise{…}'; + try { + const { getPromiseDetails, kPending, kRejected } = process.binding('util'); + if (Array.isArray(getPromiseDetails(Promise.resolve()))) { + getPromiseValue = (value, options) => { + const [state, innerValue] = getPromiseDetails(value); + if (state === kPending) { + return 'Promise{}' + } + return `Promise${state === kRejected ? '!' : ''}{${options.inspect(innerValue, options)}}` }; } + } catch (notNode) { + /* ignore */ + } + var inspectPromise = getPromiseValue; - // 14.1.2 euc-kr encoder - /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ - function EUCKREncoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + function inspectObject$1(object, options) { + const properties = Object.getOwnPropertyNames(object); + const symbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []; + if (properties.length === 0 && symbols.length === 0) { + return '{}' + } + options.truncate -= 4; + options.seen = options.seen || []; + if (options.seen.indexOf(object) >= 0) { + return '[Circular]' + } + options.seen.push(object); + const propertyContents = inspectList( + properties.map(key => [key, object[key]]), + options, + inspectProperty + ); + const symbolContents = inspectList( + symbols.map(key => [key, object[key]]), + options, + inspectProperty + ); + options.seen.pop(); + let sep = ''; + if (propertyContents && symbolContents) { + sep = ', '; + } + return `{ ${propertyContents}${sep}${symbolContents} }` + } - // 3. Let pointer be the index pointer for code point in index - // euc-kr. - var pointer = indexPointerFor(code_point, index('euc-kr')); + const toStringTag = typeof Symbol !== 'undefined' && Symbol.toStringTag ? Symbol.toStringTag : false; - // 4. If pointer is null, return error with code point. - if (pointer === null) - return encoderError(code_point); + function inspectClass(value, options) { + let name = ''; + if (toStringTag && toStringTag in value) { + name = value[toStringTag]; + } + name = name || getFuncName$1(value.constructor); + // Babel transforms anonymous classes to the name `_class` + if (!name || name === '_class') { + name = ''; + } + options.truncate -= name.length; + return `${name}${inspectObject$1(value, options)}` + } - // 5. Let lead be floor(pointer / 190) + 0x81. - var lead = floor(pointer / 190) + 0x81; + function inspectArguments(args, options) { + if (args.length === 0) return 'Arguments[]' + options.truncate -= 13; + return `Arguments[ ${inspectList(args, options)} ]` + } - // 6. Let trail be pointer % 190 + 0x41. - var trail = (pointer % 190) + 0x41; + const errorKeys = [ + 'stack', + 'line', + 'column', + 'name', + 'message', + 'fileName', + 'lineNumber', + 'columnNumber', + 'number', + 'description', + ]; - // 7. Return two bytes whose values are lead and trail. - return [lead, trail]; - }; + function inspectObject(error, options) { + const properties = Object.getOwnPropertyNames(error).filter(key => errorKeys.indexOf(key) === -1); + const name = error.name; + options.truncate -= name.length; + let message = ''; + if (typeof error.message === 'string') { + message = truncate(error.message, options.truncate); + } else { + properties.unshift('message'); } + message = message ? `: ${message}` : ''; + options.truncate -= message.length + 5; + const propertyContents = inspectList( + properties.map(key => [key, error[key]]), + options, + inspectProperty + ); + return `${name}${message}${propertyContents ? ` { ${propertyContents} }` : ''}` + } - /** @param {{fatal: boolean}} options */ - encoders['EUC-KR'] = function(options) { - return new EUCKREncoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['EUC-KR'] = function(options) { - return new EUCKRDecoder(options); - }; - + function inspectAttribute([key, value], options) { + options.truncate -= 3; + if (!value) { + return `${options.stylize(key, 'yellow')}` + } + return `${options.stylize(key, 'yellow')}=${options.stylize(`"${value}"`, 'string')}` + } - // - // 15. Legacy miscellaneous encodings - // + function inspectHTMLCollection(collection, options) { + // eslint-disable-next-line no-use-before-define + return inspectList(collection, options, inspectHTML, '\n') + } - // 15.1 replacement + function inspectHTML(element, options) { + const properties = element.getAttributeNames(); + const name = element.tagName.toLowerCase(); + const head = options.stylize(`<${name}`, 'special'); + const headClose = options.stylize(`>`, 'special'); + const tail = options.stylize(``, 'special'); + options.truncate -= name.length * 2 + 5; + let propertyContents = ''; + if (properties.length > 0) { + propertyContents += ' '; + propertyContents += inspectList( + properties.map(key => [key, element.getAttribute(key)]), + options, + inspectAttribute, + ' ' + ); + } + options.truncate -= propertyContents.length; + const truncate = options.truncate; + let children = inspectHTMLCollection(element.children, options); + if (children && children.length > truncate) { + children = `${truncator}(${element.children.length})`; + } + return `${head}${propertyContents}${headClose}${children}${tail}` + } - // Not needed - API throws RangeError + /* ! + * loupe + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ - // 15.2 Common infrastructure for utf-16be and utf-16le + const symbolsSupported = typeof Symbol === 'function' && typeof Symbol.for === 'function'; + const chaiInspect = symbolsSupported ? Symbol.for('chai/inspect') : '@@chai/inspect'; + let nodeInspect = false; + try { + // eslint-disable-next-line global-require + const nodeUtil = require('util'); + nodeInspect = nodeUtil.inspect ? nodeUtil.inspect.custom : false; + } catch (noNodeInspect) { + nodeInspect = false; + } - /** - * @param {number} code_unit - * @param {boolean} utf16be - * @return {!Array.} bytes - */ - function convertCodeUnitToBytes(code_unit, utf16be) { - // 1. Let byte1 be code unit >> 8. - var byte1 = code_unit >> 8; + function FakeMap$1() { + // eslint-disable-next-line prefer-template + this.key = 'chai/loupe__' + Math.random() + Date.now(); + } + FakeMap$1.prototype = { + // eslint-disable-next-line object-shorthand + get: function get(key) { + return key[this.key] + }, + // eslint-disable-next-line object-shorthand + has: function has(key) { + return this.key in key + }, + // eslint-disable-next-line object-shorthand + set: function set(key, value) { + if (Object.isExtensible(key)) { + Object.defineProperty(key, this.key, { + // eslint-disable-next-line object-shorthand + value: value, + configurable: true, + }); + } + }, + }; + const constructorMap = new (typeof WeakMap === 'function' ? WeakMap : FakeMap$1)(); + const stringTagMap = {}; + const baseTypesMap = { + undefined: (value, options) => options.stylize('undefined', 'undefined'), + null: (value, options) => options.stylize(null, 'null'), + + boolean: (value, options) => options.stylize(value, 'boolean'), + Boolean: (value, options) => options.stylize(value, 'boolean'), + + number: inspectNumber, + Number: inspectNumber, + + bigint: inspectBigInt, + BigInt: inspectBigInt, + + string: inspectString, + String: inspectString, + + function: inspectFunction, + Function: inspectFunction, + + symbol: inspectSymbol, + // A Symbol polyfill will return `Symbol` not `symbol` from typedetect + Symbol: inspectSymbol, + + Array: inspectArray, + Date: inspectDate, + Map: inspectMap, + Set: inspectSet, + RegExp: inspectRegExp, + Promise: inspectPromise, + + // WeakSet, WeakMap are totally opaque to us + WeakSet: (value, options) => options.stylize('WeakSet{…}', 'special'), + WeakMap: (value, options) => options.stylize('WeakMap{…}', 'special'), + + Arguments: inspectArguments, + Int8Array: inspectTypedArray, + Uint8Array: inspectTypedArray, + Uint8ClampedArray: inspectTypedArray, + Int16Array: inspectTypedArray, + Uint16Array: inspectTypedArray, + Int32Array: inspectTypedArray, + Uint32Array: inspectTypedArray, + Float32Array: inspectTypedArray, + Float64Array: inspectTypedArray, + + Generator: () => '', + DataView: () => '', + ArrayBuffer: () => '', + + Error: inspectObject, + + HTMLCollection: inspectHTMLCollection, + NodeList: inspectHTMLCollection, + }; - // 2. Let byte2 be code unit & 0x00FF. - var byte2 = code_unit & 0x00FF; + // eslint-disable-next-line complexity + const inspectCustom = (value, options, type) => { + if (chaiInspect in value && typeof value[chaiInspect] === 'function') { + return value[chaiInspect](options) + } - // 3. Then return the bytes in order: - // utf-16be flag is set: byte1, then byte2. - if (utf16be) - return [byte1, byte2]; - // utf-16be flag is unset: byte2, then byte1. - return [byte2, byte1]; + if (nodeInspect && nodeInspect in value && typeof value[nodeInspect] === 'function') { + return value[nodeInspect](options.depth, options) } - // 15.2.1 shared utf-16 decoder - /** - * @constructor - * @implements {Decoder} - * @param {boolean} utf16_be True if big-endian, false if little-endian. - * @param {{fatal: boolean}} options - */ - function UTF16Decoder(utf16_be, options) { - var fatal = options.fatal; - var /** @type {?number} */ utf16_lead_byte = null, - /** @type {?number} */ utf16_lead_surrogate = null; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and either utf-16 lead byte or - // utf-16 lead surrogate is not null, set utf-16 lead byte and - // utf-16 lead surrogate to null, and return error. - if (bite === end_of_stream && (utf16_lead_byte !== null || - utf16_lead_surrogate !== null)) { - return decoderError(fatal); - } + if ('inspect' in value && typeof value.inspect === 'function') { + return value.inspect(options.depth, options) + } - // 2. If byte is end-of-stream and utf-16 lead byte and utf-16 - // lead surrogate are null, return finished. - if (bite === end_of_stream && utf16_lead_byte === null && - utf16_lead_surrogate === null) { - return finished; - } + if ('constructor' in value && constructorMap.has(value.constructor)) { + return constructorMap.get(value.constructor)(value, options) + } - // 3. If utf-16 lead byte is null, set utf-16 lead byte to byte - // and return continue. - if (utf16_lead_byte === null) { - utf16_lead_byte = bite; - return null; - } + if (stringTagMap[type]) { + return stringTagMap[type](value, options) + } - // 4. Let code unit be the result of: - var code_unit; - if (utf16_be) { - // utf-16be decoder flag is set - // (utf-16 lead byte << 8) + byte. - code_unit = (utf16_lead_byte << 8) + bite; - } else { - // utf-16be decoder flag is unset - // (byte << 8) + utf-16 lead byte. - code_unit = (bite << 8) + utf16_lead_byte; - } - // Then set utf-16 lead byte to null. - utf16_lead_byte = null; + return '' + }; - // 5. If utf-16 lead surrogate is not null, let lead surrogate - // be utf-16 lead surrogate, set utf-16 lead surrogate to null, - // and then run these substeps: - if (utf16_lead_surrogate !== null) { - var lead_surrogate = utf16_lead_surrogate; - utf16_lead_surrogate = null; + const toString = Object.prototype.toString; - // 1. If code unit is in the range U+DC00 to U+DFFF, - // inclusive, return a code point whose value is 0x10000 + - // ((lead surrogate − 0xD800) << 10) + (code unit − 0xDC00). - if (inRange(code_unit, 0xDC00, 0xDFFF)) { - return 0x10000 + (lead_surrogate - 0xD800) * 0x400 + - (code_unit - 0xDC00); - } + // eslint-disable-next-line complexity + function inspect$3(value, options) { + options = normaliseOptions(options); + options.inspect = inspect$3; + const { customInspect } = options; + let type = value === null ? 'null' : typeof value; + if (type === 'object') { + type = toString.call(value).slice(8, -1); + } - // 2. Prepend the sequence resulting of converting code unit - // to bytes using utf-16be decoder flag to stream and return - // error. - stream.prepend(convertCodeUnitToBytes(code_unit, utf16_be)); - return decoderError(fatal); - } + // If it is a base value that we already support, then use Loupe's inspector + if (baseTypesMap[type]) { + return baseTypesMap[type](value, options) + } - // 6. If code unit is in the range U+D800 to U+DBFF, inclusive, - // set utf-16 lead surrogate to code unit and return continue. - if (inRange(code_unit, 0xD800, 0xDBFF)) { - utf16_lead_surrogate = code_unit; - return null; - } + // If `options.customInspect` is set to true then try to use the custom inspector + if (customInspect && value) { + const output = inspectCustom(value, options, type); + if (output) { + if (typeof output === 'string') return output + return inspect$3(output, options) + } + } - // 7. If code unit is in the range U+DC00 to U+DFFF, inclusive, - // return error. - if (inRange(code_unit, 0xDC00, 0xDFFF)) - return decoderError(fatal); + const proto = value ? Object.getPrototypeOf(value) : false; + // If it's a plain Object then use Loupe's inspector + if (proto === Object.prototype || proto === null) { + return inspectObject$1(value, options) + } - // 8. Return code point code unit. - return code_unit; - }; + // Specifically account for HTMLElements + // eslint-disable-next-line no-undef + if (value && typeof HTMLElement === 'function' && value instanceof HTMLElement) { + return inspectHTML(value, options) } - // 15.2.2 shared utf-16 encoder - /** - * @constructor - * @implements {Encoder} - * @param {boolean} utf16_be True if big-endian, false if little-endian. - * @param {{fatal: boolean}} options - */ - function UTF16Encoder(utf16_be, options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; + if ('constructor' in value) { + // If it is a class, inspect it like an object but add the constructor name + if (value.constructor !== Object) { + return inspectClass(value, options) + } - // 2. If code point is in the range U+0000 to U+FFFF, inclusive, - // return the sequence resulting of converting code point to - // bytes using utf-16be encoder flag. - if (inRange(code_point, 0x0000, 0xFFFF)) - return convertCodeUnitToBytes(code_point, utf16_be); + // If it is an object with an anonymous prototype, display it as an object. + return inspectObject$1(value, options) + } - // 3. Let lead be ((code point − 0x10000) >> 10) + 0xD800, - // converted to bytes using utf-16be encoder flag. - var lead = convertCodeUnitToBytes( - ((code_point - 0x10000) >> 10) + 0xD800, utf16_be); + // last chance to check if it's an object + if (value === Object(value)) { + return inspectObject$1(value, options) + } - // 4. Let trail be ((code point − 0x10000) & 0x3FF) + 0xDC00, - // converted to bytes using utf-16be encoder flag. - var trail = convertCodeUnitToBytes( - ((code_point - 0x10000) & 0x3FF) + 0xDC00, utf16_be); + // We have run out of options! Just stringify the value + return options.stylize(String(value), type) + } - // 5. Return a byte sequence of lead followed by trail. - return lead.concat(trail); - }; + function registerConstructor(constructor, inspector) { + if (constructorMap.has(constructor)) { + return false + } + constructorMap.set(constructor, inspector); + return true + } + + function registerStringTag(stringTag, inspector) { + if (stringTag in stringTagMap) { + return false } + stringTagMap[stringTag] = inspector; + return true + } - // 15.3 utf-16be - // 15.3.1 utf-16be decoder - /** @param {{fatal: boolean}} options */ - encoders['UTF-16BE'] = function(options) { - return new UTF16Encoder(true, options); - }; - // 15.3.2 utf-16be encoder - /** @param {{fatal: boolean}} options */ - decoders['UTF-16BE'] = function(options) { - return new UTF16Decoder(true, options); - }; + const custom = chaiInspect; - // 15.4 utf-16le - // 15.4.1 utf-16le decoder - /** @param {{fatal: boolean}} options */ - encoders['UTF-16LE'] = function(options) { - return new UTF16Encoder(false, options); - }; - // 15.4.2 utf-16le encoder - /** @param {{fatal: boolean}} options */ - decoders['UTF-16LE'] = function(options) { - return new UTF16Decoder(false, options); - }; + var loupe$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + inspect: inspect$3, + registerConstructor: registerConstructor, + registerStringTag: registerStringTag, + custom: custom, + 'default': inspect$3 + }); - // 15.5 x-user-defined + var require$$1 = /*@__PURE__*/getAugmentedNamespace(loupe$1); + + var config$5 = { - // 15.5.1 x-user-defined decoder /** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options + * ### config.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message. + * + * chai.config.includeStack = true; // enable stack on error + * + * @param {Boolean} + * @api public */ - function XUserDefinedDecoder(options) { - options.fatal; - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream, return finished. - if (bite === end_of_stream) - return finished; - // 2. If byte is an ASCII byte, return a code point whose value - // is byte. - if (isASCIIByte(bite)) - return bite; + includeStack: false, - // 3. Return a code point whose value is 0xF780 + byte − 0x80. - return 0xF780 + bite - 0x80; - }; - } + /** + * ### config.showDiff + * + * User configurable property, influences whether or not + * the `showDiff` flag should be included in the thrown + * AssertionErrors. `false` will always be `false`; `true` + * will be true when the assertion has requested a diff + * be shown. + * + * @param {Boolean} + * @api public + */ + + showDiff: true, - // 15.5.2 x-user-defined encoder /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options + * ### config.truncateThreshold + * + * User configurable property, sets length threshold for actual and + * expected values in assertion errors. If this threshold is exceeded, for + * example for large data structures, the value is replaced with something + * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. + * + * Set it to zero if you want to disable truncating altogether. + * + * This is especially userful when doing assertions on arrays: having this + * set to a reasonable large value makes the failure messages readily + * inspectable. + * + * chai.config.truncateThreshold = 0; // disable truncating + * + * @param {Number} + * @api public */ - function XUserDefinedEncoder(options) { - options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1.If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - // 2. If code point is an ASCII code point, return a byte whose - // value is code point. - if (isASCIICodePoint(code_point)) - return code_point; + truncateThreshold: 40, - // 3. If code point is in the range U+F780 to U+F7FF, inclusive, - // return a byte whose value is code point − 0xF780 + 0x80. - if (inRange(code_point, 0xF780, 0xF7FF)) - return code_point - 0xF780 + 0x80; + /** + * ### config.useProxy + * + * User configurable property, defines if chai will use a Proxy to throw + * an error when a non-existent property is read, which protects users + * from typos when using property-based assertions. + * + * Set it to false if you want to disable this feature. + * + * chai.config.useProxy = false; // disable use of Proxy + * + * This feature is automatically disabled regardless of this config value + * in environments that don't support proxies. + * + * @param {Boolean} + * @api public + */ - // 4. Return error with code point. - return encoderError(code_point); - }; - } + useProxy: true, - /** @param {{fatal: boolean}} options */ - encoders['x-user-defined'] = function(options) { - return new XUserDefinedEncoder(options); - }; - /** @param {{fatal: boolean}} options */ - decoders['x-user-defined'] = function(options) { - return new XUserDefinedDecoder(options); - }; + /** + * ### config.proxyExcludedKeys + * + * User configurable property, defines which properties should be ignored + * instead of throwing an error if they do not exist on the assertion. + * This is only applied if the environment Chai is running in supports proxies and + * if the `useProxy` configuration setting is enabled. + * By default, `then` and `inspect` will not throw an error if they do not exist on the + * assertion object because the `.inspect` property is read by `util.inspect` (for example, when + * using `console.log` on the assertion object) and `.then` is necessary for promise type-checking. + * + * // By default these keys will not throw an error if they do not exist on the assertion object + * chai.config.proxyExcludedKeys = ['then', 'inspect']; + * + * @param {Array} + * @api public + */ - if (!global['TextEncoder']) - global['TextEncoder'] = TextEncoder; - if (!global['TextDecoder']) - global['TextDecoder'] = TextDecoder; + proxyExcludedKeys: ['then', 'catch', 'inspect', 'toJSON'] + }; - if (typeof module !== "undefined" && module.exports) { - module.exports = { - TextEncoder: global['TextEncoder'], - TextDecoder: global['TextDecoder'], - EncodingIndexes: global["encoding-indexes"] - }; - } + var loupe = require$$1; + var config$4 = config$5; - // For strict environments where `this` inside the global scope - // is `undefined`, take a pure object instead - }(this || {})); - },{"./encoding-indexes.js":109}],111:[function(require,module,exports){ - if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; - } else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; + var inspect_1 = inspect$2; + + /** + * ### .inspect(obj, [showHidden], [depth], [colors]) + * + * Echoes the value of a value. Tries to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. Default is false. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + * @namespace Utils + * @name inspect + */ + function inspect$2(obj, showHidden, depth, colors) { + var options = { + colors: colors, + depth: (typeof depth === 'undefined' ? 2 : depth), + showHidden: showHidden, + truncate: config$4.truncateThreshold ? config$4.truncateThreshold : Infinity, }; + return loupe.inspect(obj, options); } - },{}],112:[function(require,module,exports){ - module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; - }; - },{}],113:[function(require,module,exports){ - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. + /*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - var formatRegExp = /%[sdj%]/g; - exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } + /*! + * Module dependencies + */ - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; + var inspect$1 = inspect_1; + var config$3 = config$5; + + /** + * ### .objDisplay(object) + * + * Determines if an object or an array matches + * criteria to be inspected in-line for error + * messages or should be truncated. + * + * @param {Mixed} javascript object to inspect + * @returns {string} stringified object + * @name objDisplay + * @namespace Utils + * @api public + */ + + var objDisplay$1 = function objDisplay(obj) { + var str = inspect$1(obj) + , type = Object.prototype.toString.call(obj); + + if (config$3.truncateThreshold && str.length >= config$3.truncateThreshold) { + if (type === '[object Function]') { + return !obj.name || obj.name === '' + ? '[Function]' + : '[Function: ' + obj.name + ']'; + } else if (type === '[object Array]') { + return '[ Array(' + obj.length + ') ]'; + } else if (type === '[object Object]') { + var keys = Object.keys(obj) + , kstr = keys.length > 2 + ? keys.splice(0, 2).join(', ') + ', ...' + : keys.join(', '); + return '{ Object (' + kstr + ') }'; } else { - str += ' ' + inspect(x); + return str; } + } else { + return str; } - return str; }; + /*! + * Chai - message composition utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies + */ + + var flag$2 = flag$5 + , getActual = getActual$1 + , objDisplay = objDisplay$1; + + /** + * ### .getMessage(object, message, negateMessage) + * + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. + * + * Message template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getMessage + * @api public + */ + + var getMessage$1 = function getMessage(obj, args) { + var negate = flag$2(obj, 'negate') + , val = flag$2(obj, 'object') + , expected = args[3] + , actual = getActual(obj, args) + , msg = negate ? args[2] : args[1] + , flagMsg = flag$2(obj, 'message'); + + if(typeof msg === "function") msg = msg(); + msg = msg || ''; + msg = msg + .replace(/#\{this\}/g, function () { return objDisplay(val); }) + .replace(/#\{act\}/g, function () { return objDisplay(actual); }) + .replace(/#\{exp\}/g, function () { return objDisplay(expected); }); + + return flagMsg ? flagMsg + ': ' + msg : msg; + }; + + /*! + * Chai - transferFlags utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .transferFlags(assertion, object, includeAll = true) + * + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, `lockSsfi`, + * and `message`) will not be transferred. + * + * + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); + * + * var anotherAssertion = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); + * + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags to; usually a new assertion + * @param {Boolean} includeAll + * @namespace Utils + * @name transferFlags + * @api private + */ + + var transferFlags = function transferFlags(assertion, object, includeAll) { + var flags = assertion.__flags || (assertion.__flags = Object.create(null)); - // Mark that a method should not be used. - // Returns a modified function which warns once by default. - // If --no-deprecation is set, then it is a no-op. - exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; + if (!object.__flags) { + object.__flags = Object.create(null); } - if (process.noDeprecation === true) { - return fn; - } + includeAll = arguments.length === 3 ? includeAll : true; - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; + for (var flag in flags) { + if (includeAll || + (flag !== 'object' && flag !== 'ssfi' && flag !== 'lockSsfi' && flag != 'message')) { + object.__flags[flag] = flags[flag]; } - return fn.apply(this, arguments); } - - return deprecated; }; + var deepEql = {exports: {}}; - var debugs = {}; - var debugEnviron; - exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; + /* globals Symbol: false, Uint8Array: false, WeakMap: false */ + /*! + * deep-eql + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + + var type$1 = typeDetectExports; + function FakeMap() { + this._key = 'chai/deep-eql__' + Math.random() + Date.now(); + } + + FakeMap.prototype = { + get: function get(key) { + return key[this._key]; + }, + set: function set(key, value) { + if (Object.isExtensible(key)) { + Object.defineProperty(key, this._key, { + value: value, + configurable: true, + }); } - } - return debugs[set]; + }, }; + var MemoizeMap = typeof WeakMap === 'function' ? WeakMap : FakeMap; + /*! + * Check to see if the MemoizeMap has recorded a result of the two operands + * + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {MemoizeMap} memoizeMap + * @returns {Boolean|null} result + */ + function memoizeCompare(leftHandOperand, rightHandOperand, memoizeMap) { + // Technically, WeakMap keys can *only* be objects, not primitives. + if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) { + return null; + } + var leftHandMap = memoizeMap.get(leftHandOperand); + if (leftHandMap) { + var result = leftHandMap.get(rightHandOperand); + if (typeof result === 'boolean') { + return result; + } + } + return null; + } + + /*! + * Set the result of the equality into the MemoizeMap + * + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {MemoizeMap} memoizeMap + * @param {Boolean} result + */ + function memoizeSet(leftHandOperand, rightHandOperand, memoizeMap, result) { + // Technically, WeakMap keys can *only* be objects, not primitives. + if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) { + return; + } + var leftHandMap = memoizeMap.get(leftHandOperand); + if (leftHandMap) { + leftHandMap.set(rightHandOperand, result); + } else { + leftHandMap = new MemoizeMap(); + leftHandMap.set(rightHandOperand, result); + memoizeMap.set(leftHandOperand, leftHandMap); + } + } + + /*! + * Primary Export + */ + + deepEql.exports = deepEqual; + deepEql.exports.MemoizeMap = MemoizeMap; /** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. + * Assert deeply nested sameValue equality between two objects of any type. * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (optional) Additional options + * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality. + * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of + complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular + references to blow the stack. + * @return {Boolean} equal match */ - /* legacy: obj, showHidden, depth, colors*/ - function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); + function deepEqual(leftHandOperand, rightHandOperand, options) { + // If we have a comparator, we can't assume anything; so bail to its check first. + if (options && options.comparator) { + return extensiveDeepEqual(leftHandOperand, rightHandOperand, options); } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); + + var simpleResult = simpleEqual(leftHandOperand, rightHandOperand); + if (simpleResult !== null) { + return simpleResult; + } + + // Deeper comparisons are pushed through to a larger function + return extensiveDeepEqual(leftHandOperand, rightHandOperand, options); } - exports.inspect = inspect; + /** + * Many comparisons can be canceled out early via simple equality or primitive checks. + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @return {Boolean|null} equal match + */ + function simpleEqual(leftHandOperand, rightHandOperand) { + // Equal references (except for Numbers) can be returned early + if (leftHandOperand === rightHandOperand) { + // Handle +-0 cases + return leftHandOperand !== 0 || 1 / leftHandOperand === 1 / rightHandOperand; + } - // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics - inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] - }; + // handle NaN cases + if ( + leftHandOperand !== leftHandOperand && // eslint-disable-line no-self-compare + rightHandOperand !== rightHandOperand // eslint-disable-line no-self-compare + ) { + return true; + } - // Don't use 'blue' not visible on cmd.exe - inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' - }; + // Anything that is not an 'object', i.e. symbols, functions, booleans, numbers, + // strings, and undefined, can be compared by reference. + if (isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) { + // Easy out b/c it would have passed the first equality check + return false; + } + return null; + } + /*! + * The main logic of the `deepEqual` function. + * + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (optional) Additional options + * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality. + * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of + complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular + references to blow the stack. + * @return {Boolean} equal match + */ + function extensiveDeepEqual(leftHandOperand, rightHandOperand, options) { + options = options || {}; + options.memoize = options.memoize === false ? false : options.memoize || new MemoizeMap(); + var comparator = options && options.comparator; - function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; + // Check if a memoized result exists. + var memoizeResultLeft = memoizeCompare(leftHandOperand, rightHandOperand, options.memoize); + if (memoizeResultLeft !== null) { + return memoizeResultLeft; + } + var memoizeResultRight = memoizeCompare(rightHandOperand, leftHandOperand, options.memoize); + if (memoizeResultRight !== null) { + return memoizeResultRight; + } - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; + // If a comparator is present, use it. + if (comparator) { + var comparatorResult = comparator(leftHandOperand, rightHandOperand); + // Comparators may return null, in which case we want to go back to default behavior. + if (comparatorResult === false || comparatorResult === true) { + memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult); + return comparatorResult; + } + // To allow comparators to override *any* behavior, we ran them first. Since it didn't decide + // what to do, we need to make sure to return the basic tests first before we move on. + var simpleResult = simpleEqual(leftHandOperand, rightHandOperand); + if (simpleResult !== null) { + // Don't memoize this, it takes longer to set/retrieve than to just compare. + return simpleResult; + } } - } + var leftHandType = type$1(leftHandOperand); + if (leftHandType !== type$1(rightHandOperand)) { + memoizeSet(leftHandOperand, rightHandOperand, options.memoize, false); + return false; + } - function stylizeNoColor(str, styleType) { - return str; - } + // Temporarily set the operands in the memoize object to prevent blowing the stack + memoizeSet(leftHandOperand, rightHandOperand, options.memoize, true); + var result = extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options); + memoizeSet(leftHandOperand, rightHandOperand, options.memoize, result); + return result; + } - function arrayToHash(array) { - var hash = {}; + function extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options) { + switch (leftHandType) { + case 'String': + case 'Number': + case 'Boolean': + case 'Date': + // If these types are their instance types (e.g. `new Number`) then re-deepEqual against their values + return deepEqual(leftHandOperand.valueOf(), rightHandOperand.valueOf()); + case 'Promise': + case 'Symbol': + case 'function': + case 'WeakMap': + case 'WeakSet': + return leftHandOperand === rightHandOperand; + case 'Error': + return keysEqual(leftHandOperand, rightHandOperand, [ 'name', 'message', 'code' ], options); + case 'Arguments': + case 'Int8Array': + case 'Uint8Array': + case 'Uint8ClampedArray': + case 'Int16Array': + case 'Uint16Array': + case 'Int32Array': + case 'Uint32Array': + case 'Float32Array': + case 'Float64Array': + case 'Array': + return iterableEqual(leftHandOperand, rightHandOperand, options); + case 'RegExp': + return regexpEqual(leftHandOperand, rightHandOperand); + case 'Generator': + return generatorEqual(leftHandOperand, rightHandOperand, options); + case 'DataView': + return iterableEqual(new Uint8Array(leftHandOperand.buffer), new Uint8Array(rightHandOperand.buffer), options); + case 'ArrayBuffer': + return iterableEqual(new Uint8Array(leftHandOperand), new Uint8Array(rightHandOperand), options); + case 'Set': + return entriesEqual(leftHandOperand, rightHandOperand, options); + case 'Map': + return entriesEqual(leftHandOperand, rightHandOperand, options); + case 'Temporal.PlainDate': + case 'Temporal.PlainTime': + case 'Temporal.PlainDateTime': + case 'Temporal.Instant': + case 'Temporal.ZonedDateTime': + case 'Temporal.PlainYearMonth': + case 'Temporal.PlainMonthDay': + return leftHandOperand.equals(rightHandOperand); + case 'Temporal.Duration': + return leftHandOperand.total('nanoseconds') === rightHandOperand.total('nanoseconds'); + case 'Temporal.TimeZone': + case 'Temporal.Calendar': + return leftHandOperand.toString() === rightHandOperand.toString(); + default: + return objectEqual(leftHandOperand, rightHandOperand, options); + } + } - array.forEach(function(val, idx) { - hash[val] = true; - }); + /*! + * Compare two Regular Expressions for equality. + * + * @param {RegExp} leftHandOperand + * @param {RegExp} rightHandOperand + * @return {Boolean} result + */ - return hash; + function regexpEqual(leftHandOperand, rightHandOperand) { + return leftHandOperand.toString() === rightHandOperand.toString(); } + /*! + * Compare two Sets/Maps for equality. Faster than other equality functions. + * + * @param {Set} leftHandOperand + * @param {Set} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ - function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; + function entriesEqual(leftHandOperand, rightHandOperand, options) { + // IE11 doesn't support Set#entries or Set#@@iterator, so we need manually populate using Set#forEach + if (leftHandOperand.size !== rightHandOperand.size) { + return false; } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; + if (leftHandOperand.size === 0) { + return true; } + var leftHandItems = []; + var rightHandItems = []; + leftHandOperand.forEach(function gatherEntries(key, value) { + leftHandItems.push([ key, value ]); + }); + rightHandOperand.forEach(function gatherEntries(key, value) { + rightHandItems.push([ key, value ]); + }); + return iterableEqual(leftHandItems.sort(), rightHandItems.sort(), options); + } - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); + /*! + * Simple equality for flat iterable objects such as Arrays, TypedArrays or Node.js buffers. + * + * @param {Iterable} leftHandOperand + * @param {Iterable} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); + function iterableEqual(leftHandOperand, rightHandOperand, options) { + var length = leftHandOperand.length; + if (length !== rightHandOperand.length) { + return false; } - - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); + if (length === 0) { + return true; } - - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); + var index = -1; + while (++index < length) { + if (deepEqual(leftHandOperand[index], rightHandOperand[index], options) === false) { + return false; } } + return true; + } - var base = '', array = false, braces = ['{', '}']; + /*! + * Simple equality for generator objects such as those returned by generator functions. + * + * @param {Iterable} leftHandOperand + * @param {Iterable} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } + function generatorEqual(leftHandOperand, rightHandOperand, options) { + return iterableEqual(getGeneratorEntries(leftHandOperand), getGeneratorEntries(rightHandOperand), options); + } + + /*! + * Determine if the given object has an @@iterator function. + * + * @param {Object} target + * @return {Boolean} `true` if the object has an @@iterator function. + */ + function hasIteratorFunction(target) { + return typeof Symbol !== 'undefined' && + typeof target === 'object' && + typeof Symbol.iterator !== 'undefined' && + typeof target[Symbol.iterator] === 'function'; + } - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; + /*! + * Gets all iterator entries from the given Object. If the Object has no @@iterator function, returns an empty array. + * This will consume the iterator - which could have side effects depending on the @@iterator implementation. + * + * @param {Object} target + * @returns {Array} an array of entries from the @@iterator function + */ + function getIteratorEntries(target) { + if (hasIteratorFunction(target)) { + try { + return getGeneratorEntries(target[Symbol.iterator]()); + } catch (iteratorError) { + return []; + } } + return []; + } - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); + /*! + * Gets all entries from a Generator. This will consume the generator - which could have side effects. + * + * @param {Generator} target + * @returns {Array} an array of entries from the Generator. + */ + function getGeneratorEntries(generator) { + var generatorResult = generator.next(); + var accumulator = [ generatorResult.value ]; + while (generatorResult.done === false) { + generatorResult = generator.next(); + accumulator.push(generatorResult.value); } + return accumulator; + } - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); + /*! + * Gets all own and inherited enumerable keys from a target. + * + * @param {Object} target + * @returns {Array} an array of own and inherited enumerable keys from the target. + */ + function getEnumerableKeys(target) { + var keys = []; + for (var key in target) { + keys.push(key); } + return keys; + } - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); + function getEnumerableSymbols(target) { + var keys = []; + var allKeys = Object.getOwnPropertySymbols(target); + for (var i = 0; i < allKeys.length; i += 1) { + var key = allKeys[i]; + if (Object.getOwnPropertyDescriptor(target, key).enumerable) { + keys.push(key); + } } + return keys; + } - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; + /*! + * Determines if two objects have matching values, given a set of keys. Defers to deepEqual for the equality check of + * each key. If any value of the given key is not equal, the function will return false (early). + * + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Array} keys An array of keys to compare the values of leftHandOperand and rightHandOperand against + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ + function keysEqual(leftHandOperand, rightHandOperand, keys, options) { + var length = keys.length; + if (length === 0) { + return true; + } + for (var i = 0; i < length; i += 1) { + if (deepEqual(leftHandOperand[keys[i]], rightHandOperand[keys[i]], options) === false) { + return false; + } } + return true; + } - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); + /*! + * Recursively check the equality of two Objects. Once basic sameness has been established it will defer to `deepEqual` + * for each enumerable key in the object. + * + * @param {Mixed} leftHandOperand + * @param {Mixed} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ + function objectEqual(leftHandOperand, rightHandOperand, options) { + var leftHandKeys = getEnumerableKeys(leftHandOperand); + var rightHandKeys = getEnumerableKeys(rightHandOperand); + var leftHandSymbols = getEnumerableSymbols(leftHandOperand); + var rightHandSymbols = getEnumerableSymbols(rightHandOperand); + leftHandKeys = leftHandKeys.concat(leftHandSymbols); + rightHandKeys = rightHandKeys.concat(rightHandSymbols); + + if (leftHandKeys.length && leftHandKeys.length === rightHandKeys.length) { + if (iterableEqual(mapSymbols(leftHandKeys).sort(), mapSymbols(rightHandKeys).sort()) === false) { + return false; } + return keysEqual(leftHandOperand, rightHandOperand, leftHandKeys, options); } - ctx.seen.push(value); + var leftHandEntries = getIteratorEntries(leftHandOperand); + var rightHandEntries = getIteratorEntries(rightHandOperand); + if (leftHandEntries.length && leftHandEntries.length === rightHandEntries.length) { + leftHandEntries.sort(); + rightHandEntries.sort(); + return iterableEqual(leftHandEntries, rightHandEntries, options); + } - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); + if (leftHandKeys.length === 0 && + leftHandEntries.length === 0 && + rightHandKeys.length === 0 && + rightHandEntries.length === 0) { + return true; } - ctx.seen.pop(); + return false; + } - return reduceToSingleString(output, base, braces); + /*! + * Returns true if the argument is a primitive. + * + * This intentionally returns true for all objects that can be compared by reference, + * including functions and symbols. + * + * @param {Mixed} value + * @return {Boolean} result + */ + function isPrimitive(value) { + return value === null || typeof value !== 'object'; } + function mapSymbols(arr) { + return arr.map(function mapSymbol(entry) { + if (typeof entry === 'symbol') { + return entry.toString(); + } - function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); + return entry; + }); } + var deepEqlExports = deepEql.exports; - function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; + var config$2 = config$5; + + /*! + * Chai - isProxyEnabled helper + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .isProxyEnabled() + * + * Helper function to check if Chai's proxy protection feature is enabled. If + * proxies are unsupported or disabled via the user's Chai config, then return + * false. Otherwise, return true. + * + * @namespace Utils + * @name isProxyEnabled + */ + + var isProxyEnabled$1 = function isProxyEnabled() { + return config$2.useProxy && + typeof Proxy !== 'undefined' && + typeof Reflect !== 'undefined'; + }; + + /*! + * Chai - addProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + var addProperty; + var hasRequiredAddProperty; + + function requireAddProperty () { + if (hasRequiredAddProperty) return addProperty; + hasRequiredAddProperty = 1; + var chai = requireChai(); + var flag = flag$5; + var isProxyEnabled = isProxyEnabled$1; + var transferFlags$1 = transferFlags; + + /** + * ### .addProperty(ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @namespace Utils + * @name addProperty + * @api public + */ + + addProperty = function addProperty(ctx, name, getter) { + getter = getter === undefined ? function () {} : getter; + + Object.defineProperty(ctx, name, + { get: function propertyGetter() { + // Setting the `ssfi` flag to `propertyGetter` causes this function to + // be the starting point for removing implementation frames from the + // stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set and proxy protection is disabled. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked + // from inside of another assertion. In the first case, the `ssfi` flag + // has already been set by the overwriting assertion. In the second + // case, the `ssfi` flag has already been set by the outer assertion. + // + // If proxy protection is enabled, then the `ssfi` flag has already been + // set by the proxy getter. + if (!isProxyEnabled() && !flag(this, 'lockSsfi')) { + flag(this, 'ssfi', propertyGetter); + } + + var result = getter.call(this); + if (result !== undefined) + return result; + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + } + , configurable: true + }); + }; + return addProperty; } + var fnLengthDesc = Object.getOwnPropertyDescriptor(function () {}, 'length'); - function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); + /*! + * Chai - addLengthGuard utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .addLengthGuard(fn, assertionName, isChainable) + * + * Define `length` as a getter on the given uninvoked method assertion. The + * getter acts as a guard against chaining `length` directly off of an uninvoked + * method assertion, which is a problem because it references `function`'s + * built-in `length` property instead of Chai's `length` assertion. When the + * getter catches the user making this mistake, it throws an error with a + * helpful message. + * + * There are two ways in which this mistake can be made. The first way is by + * chaining the `length` assertion directly off of an uninvoked chainable + * method. In this case, Chai suggests that the user use `lengthOf` instead. The + * second way is by chaining the `length` assertion directly off of an uninvoked + * non-chainable method. Non-chainable methods must be invoked prior to + * chaining. In this case, Chai suggests that the user consult the docs for the + * given assertion. + * + * If the `length` property of functions is unconfigurable, then return `fn` + * without modification. + * + * Note that in ES6, the function's `length` property is configurable, so once + * support for legacy environments is dropped, Chai's `length` property can + * replace the built-in function's `length` property, and this length guard will + * no longer be necessary. In the mean time, maintaining consistency across all + * environments is the priority. + * + * @param {Function} fn + * @param {String} assertionName + * @param {Boolean} isChainable + * @namespace Utils + * @name addLengthGuard + */ + + var addLengthGuard = function addLengthGuard (fn, assertionName, isChainable) { + if (!fnLengthDesc.configurable) return fn; + + Object.defineProperty(fn, 'length', { + get: function () { + if (isChainable) { + throw Error('Invalid Chai property: ' + assertionName + '.length. Due' + + ' to a compatibility issue, "length" cannot directly follow "' + + assertionName + '". Use "' + assertionName + '.lengthOf" instead.'); + } + + throw Error('Invalid Chai property: ' + assertionName + '.length. See' + + ' docs for proper usage of "' + assertionName + '".'); } }); - return output; - } + return fn; + }; - function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); + /*! + * Chai - getProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .getProperties(object) + * + * This allows the retrieval of property names of an object, enumerable or not, + * inherited or not. + * + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getProperties + * @api public + */ + + var getProperties$1 = function getProperties(object) { + var result = Object.getOwnPropertyNames(object); + + function addProperty(property) { + if (result.indexOf(property) === -1) { + result.push(property); } } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; + + var proto = Object.getPrototypeOf(object); + while (proto !== null) { + Object.getOwnPropertyNames(proto).forEach(addProperty); + proto = Object.getPrototypeOf(proto); } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); + + return result; + }; + + var config$1 = config$5; + var flag$1 = flag$5; + var getProperties = getProperties$1; + var isProxyEnabled = isProxyEnabled$1; + + /*! + * Chai - proxify utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + + /** + * ### .proxify(object) + * + * Return a proxy of given object that throws an error when a non-existent + * property is read. By default, the root cause is assumed to be a misspelled + * property, and thus an attempt is made to offer a reasonable suggestion from + * the list of existing properties. However, if a nonChainableMethodName is + * provided, then the root cause is instead a failure to invoke a non-chainable + * method prior to reading the non-existent property. + * + * If proxies are unsupported or disabled via the user's Chai config, then + * return object without modification. + * + * @param {Object} obj + * @param {String} nonChainableMethodName + * @namespace Utils + * @name proxify + */ + + var builtins = ['__flags', '__methods', '_obj', 'assert']; + + var proxify = function proxify(obj, nonChainableMethodName) { + if (!isProxyEnabled()) return obj; + + return new Proxy(obj, { + get: function proxyGetter(target, property) { + // This check is here because we should not throw errors on Symbol properties + // such as `Symbol.toStringTag`. + // The values for which an error should be thrown can be configured using + // the `config.proxyExcludedKeys` setting. + if (typeof property === 'string' && + config$1.proxyExcludedKeys.indexOf(property) === -1 && + !Reflect.has(target, property)) { + // Special message for invalid property access of non-chainable methods. + if (nonChainableMethodName) { + throw Error('Invalid Chai property: ' + nonChainableMethodName + '.' + + property + '. See docs for proper usage of "' + + nonChainableMethodName + '".'); + } + + // If the property is reasonably close to an existing Chai property, + // suggest that property to the user. Only suggest properties with a + // distance less than 4. + var suggestion = null; + var suggestionDistance = 4; + getProperties(target).forEach(function(prop) { + if ( + !Object.prototype.hasOwnProperty(prop) && + builtins.indexOf(prop) === -1 + ) { + var dist = stringDistanceCapped( + property, + prop, + suggestionDistance + ); + if (dist < suggestionDistance) { + suggestion = prop; + suggestionDistance = dist; + } + } + }); + + if (suggestion !== null) { + throw Error('Invalid Chai property: ' + property + + '. Did you mean "' + suggestion + '"?'); } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); + throw Error('Invalid Chai property: ' + property); } } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - return name + ': ' + str; - } + // Use this proxy getter as the starting point for removing implementation + // frames from the stack trace of a failed assertion. For property + // assertions, this prevents the proxy getter from showing up in the stack + // trace since it's invoked before the property getter. For method and + // chainable method assertions, this flag will end up getting changed to + // the method wrapper, which is good since this frame will no longer be in + // the stack once the method is invoked. Note that Chai builtin assertion + // properties such as `__flags` are skipped since this is only meant to + // capture the starting point of an assertion. This step is also skipped + // if the `lockSsfi` flag is set, thus indicating that this assertion is + // being called from within another assertion. In that case, the `ssfi` + // flag is already set to the outer assertion's starting point. + if (builtins.indexOf(property) === -1 && !flag$1(target, 'lockSsfi')) { + flag$1(target, 'ssfi', proxyGetter); + } + return Reflect.get(target, property); + } + }); + }; - function reduceToSingleString(output, base, braces) { - var length = output.reduce(function(prev, cur) { - if (cur.indexOf('\n') >= 0) ; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); + /** + * # stringDistanceCapped(strA, strB, cap) + * Return the Levenshtein distance between two strings, but no more than cap. + * @param {string} strA + * @param {string} strB + * @param {number} number + * @return {number} min(string distance between strA and strB, cap) + * @api private + */ - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; + function stringDistanceCapped(strA, strB, cap) { + if (Math.abs(strA.length - strB.length) >= cap) { + return cap; } - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; - } - - - // NOTE: These type checking functions intentionally don't use `instanceof` - // because it is fragile and can be easily faked with `Object.create()`. - function isArray(ar) { - return Array.isArray(ar); - } - exports.isArray = isArray; + var memo = []; + // `memo` is a two-dimensional array containing distances. + // memo[i][j] is the distance between strA.slice(0, i) and + // strB.slice(0, j). + for (var i = 0; i <= strA.length; i++) { + memo[i] = Array(strB.length + 1).fill(0); + memo[i][0] = i; + } + for (var j = 0; j < strB.length; j++) { + memo[0][j] = j; + } - function isBoolean(arg) { - return typeof arg === 'boolean'; - } - exports.isBoolean = isBoolean; + for (var i = 1; i <= strA.length; i++) { + var ch = strA.charCodeAt(i - 1); + for (var j = 1; j <= strB.length; j++) { + if (Math.abs(i - j) >= cap) { + memo[i][j] = cap; + continue; + } + memo[i][j] = Math.min( + memo[i - 1][j] + 1, + memo[i][j - 1] + 1, + memo[i - 1][j - 1] + + (ch === strB.charCodeAt(j - 1) ? 0 : 1) + ); + } + } - function isNull(arg) { - return arg === null; + return memo[strA.length][strB.length]; } - exports.isNull = isNull; - function isNullOrUndefined(arg) { - return arg == null; - } - exports.isNullOrUndefined = isNullOrUndefined; + /*! + * Chai - addMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - function isNumber(arg) { - return typeof arg === 'number'; + var addMethod; + var hasRequiredAddMethod; + + function requireAddMethod () { + if (hasRequiredAddMethod) return addMethod; + hasRequiredAddMethod = 1; + var addLengthGuard$1 = addLengthGuard; + var chai = requireChai(); + var flag = flag$5; + var proxify$1 = proxify; + var transferFlags$1 = transferFlags; + + /** + * ### .addMethod(ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @namespace Utils + * @name addMethod + * @api public + */ + + addMethod = function addMethod(ctx, name, method) { + var methodWrapper = function () { + // Setting the `ssfi` flag to `methodWrapper` causes this function to be the + // starting point for removing implementation frames from the stack trace of + // a failed assertion. + // + // However, we only want to use this function as the starting point if the + // `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked from + // inside of another assertion. In the first case, the `ssfi` flag has + // already been set by the overwriting assertion. In the second case, the + // `ssfi` flag has already been set by the outer assertion. + if (!flag(this, 'lockSsfi')) { + flag(this, 'ssfi', methodWrapper); + } + + var result = method.apply(this, arguments); + if (result !== undefined) + return result; + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + }; + + addLengthGuard$1(methodWrapper, name, false); + ctx[name] = proxify$1(methodWrapper, name); + }; + return addMethod; } - exports.isNumber = isNumber; - function isString(arg) { - return typeof arg === 'string'; - } - exports.isString = isString; + /*! + * Chai - overwriteProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - function isSymbol(arg) { - return typeof arg === 'symbol'; + var overwriteProperty; + var hasRequiredOverwriteProperty; + + function requireOverwriteProperty () { + if (hasRequiredOverwriteProperty) return overwriteProperty; + hasRequiredOverwriteProperty = 1; + var chai = requireChai(); + var flag = flag$5; + var isProxyEnabled = isProxyEnabled$1; + var transferFlags$1 = transferFlags; + + /** + * ### .overwriteProperty(ctx, name, fn) + * + * Overwrites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @namespace Utils + * @name overwriteProperty + * @api public + */ + + overwriteProperty = function overwriteProperty(ctx, name, getter) { + var _get = Object.getOwnPropertyDescriptor(ctx, name) + , _super = function () {}; + + if (_get && 'function' === typeof _get.get) + _super = _get.get; + + Object.defineProperty(ctx, name, + { get: function overwritingPropertyGetter() { + // Setting the `ssfi` flag to `overwritingPropertyGetter` causes this + // function to be the starting point for removing implementation frames + // from the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set and proxy protection is disabled. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked + // from inside of another assertion. In the first case, the `ssfi` flag + // has already been set by the overwriting assertion. In the second + // case, the `ssfi` flag has already been set by the outer assertion. + // + // If proxy protection is enabled, then the `ssfi` flag has already been + // set by the proxy getter. + if (!isProxyEnabled() && !flag(this, 'lockSsfi')) { + flag(this, 'ssfi', overwritingPropertyGetter); + } + + // Setting the `lockSsfi` flag to `true` prevents the overwritten + // assertion from changing the `ssfi` flag. By this point, the `ssfi` + // flag is already set to the correct starting point for this assertion. + var origLockSsfi = flag(this, 'lockSsfi'); + flag(this, 'lockSsfi', true); + var result = getter(_super).call(this); + flag(this, 'lockSsfi', origLockSsfi); + + if (result !== undefined) { + return result; + } + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + } + , configurable: true + }); + }; + return overwriteProperty; } - exports.isSymbol = isSymbol; - function isUndefined(arg) { - return arg === void 0; - } - exports.isUndefined = isUndefined; + /*! + * Chai - overwriteMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; + var overwriteMethod; + var hasRequiredOverwriteMethod; + + function requireOverwriteMethod () { + if (hasRequiredOverwriteMethod) return overwriteMethod; + hasRequiredOverwriteMethod = 1; + var addLengthGuard$1 = addLengthGuard; + var chai = requireChai(); + var flag = flag$5; + var proxify$1 = proxify; + var transferFlags$1 = transferFlags; + + /** + * ### .overwriteMethod(ctx, name, fn) + * + * Overwrites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @namespace Utils + * @name overwriteMethod + * @api public + */ + + overwriteMethod = function overwriteMethod(ctx, name, method) { + var _method = ctx[name] + , _super = function () { + throw new Error(name + ' is not a function'); + }; + + if (_method && 'function' === typeof _method) + _super = _method; + + var overwritingMethodWrapper = function () { + // Setting the `ssfi` flag to `overwritingMethodWrapper` causes this + // function to be the starting point for removing implementation frames from + // the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if the + // `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then either this assertion has been + // overwritten by another assertion, or this assertion is being invoked from + // inside of another assertion. In the first case, the `ssfi` flag has + // already been set by the overwriting assertion. In the second case, the + // `ssfi` flag has already been set by the outer assertion. + if (!flag(this, 'lockSsfi')) { + flag(this, 'ssfi', overwritingMethodWrapper); + } + + // Setting the `lockSsfi` flag to `true` prevents the overwritten assertion + // from changing the `ssfi` flag. By this point, the `ssfi` flag is already + // set to the correct starting point for this assertion. + var origLockSsfi = flag(this, 'lockSsfi'); + flag(this, 'lockSsfi', true); + var result = method(_super).apply(this, arguments); + flag(this, 'lockSsfi', origLockSsfi); + + if (result !== undefined) { + return result; + } + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + }; + + addLengthGuard$1(overwritingMethodWrapper, name, false); + ctx[name] = proxify$1(overwritingMethodWrapper, name); + }; + return overwriteMethod; } - exports.isRegExp = isRegExp; - function isObject(arg) { - return typeof arg === 'object' && arg !== null; - } - exports.isObject = isObject; + /*! + * Chai - addChainingMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; + var addChainableMethod; + var hasRequiredAddChainableMethod; + + function requireAddChainableMethod () { + if (hasRequiredAddChainableMethod) return addChainableMethod; + hasRequiredAddChainableMethod = 1; + /*! + * Module dependencies + */ + + var addLengthGuard$1 = addLengthGuard; + var chai = requireChai(); + var flag = flag$5; + var proxify$1 = proxify; + var transferFlags$1 = transferFlags; + + /*! + * Module variables + */ + + // Check whether `Object.setPrototypeOf` is supported + var canSetPrototype = typeof Object.setPrototypeOf === 'function'; + + // Without `Object.setPrototypeOf` support, this module will need to add properties to a function. + // However, some of functions' own props are not configurable and should be skipped. + var testFn = function() {}; + var excludeNames = Object.getOwnPropertyNames(testFn).filter(function(name) { + var propDesc = Object.getOwnPropertyDescriptor(testFn, name); + + // Note: PhantomJS 1.x includes `callee` as one of `testFn`'s own properties, + // but then returns `undefined` as the property descriptor for `callee`. As a + // workaround, we perform an otherwise unnecessary type-check for `propDesc`, + // and then filter it out if it's not an object as it should be. + if (typeof propDesc !== 'object') + return true; + + return !propDesc.configurable; + }); + + // Cache `Function` properties + var call = Function.prototype.call, + apply = Function.prototype.apply; + + /** + * ### .addChainableMethod(ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @namespace Utils + * @name addChainableMethod + * @api public + */ + + addChainableMethod = function addChainableMethod(ctx, name, method, chainingBehavior) { + if (typeof chainingBehavior !== 'function') { + chainingBehavior = function () { }; + } + + var chainableBehavior = { + method: method + , chainingBehavior: chainingBehavior + }; + + // save the methods so we can overwrite them later, if we need to. + if (!ctx.__methods) { + ctx.__methods = {}; + } + ctx.__methods[name] = chainableBehavior; + + Object.defineProperty(ctx, name, + { get: function chainableMethodGetter() { + chainableBehavior.chainingBehavior.call(this); + + var chainableMethodWrapper = function () { + // Setting the `ssfi` flag to `chainableMethodWrapper` causes this + // function to be the starting point for removing implementation + // frames from the stack trace of a failed assertion. + // + // However, we only want to use this function as the starting point if + // the `lockSsfi` flag isn't set. + // + // If the `lockSsfi` flag is set, then this assertion is being + // invoked from inside of another assertion. In this case, the `ssfi` + // flag has already been set by the outer assertion. + // + // Note that overwriting a chainable method merely replaces the saved + // methods in `ctx.__methods` instead of completely replacing the + // overwritten assertion. Therefore, an overwriting assertion won't + // set the `ssfi` or `lockSsfi` flags. + if (!flag(this, 'lockSsfi')) { + flag(this, 'ssfi', chainableMethodWrapper); + } + + var result = chainableBehavior.method.apply(this, arguments); + if (result !== undefined) { + return result; + } + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + }; + + addLengthGuard$1(chainableMethodWrapper, name, true); + + // Use `Object.setPrototypeOf` if available + if (canSetPrototype) { + // Inherit all properties from the object by replacing the `Function` prototype + var prototype = Object.create(this); + // Restore the `call` and `apply` methods from `Function` + prototype.call = call; + prototype.apply = apply; + Object.setPrototypeOf(chainableMethodWrapper, prototype); + } + // Otherwise, redefine all properties (slow!) + else { + var asserterNames = Object.getOwnPropertyNames(ctx); + asserterNames.forEach(function (asserterName) { + if (excludeNames.indexOf(asserterName) !== -1) { + return; + } + + var pd = Object.getOwnPropertyDescriptor(ctx, asserterName); + Object.defineProperty(chainableMethodWrapper, asserterName, pd); + }); + } + + transferFlags$1(this, chainableMethodWrapper); + return proxify$1(chainableMethodWrapper); + } + , configurable: true + }); + }; + return addChainableMethod; } - exports.isDate = isDate; - function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); - } - exports.isError = isError; + /*! + * Chai - overwriteChainableMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ - function isFunction(arg) { - return typeof arg === 'function'; + var overwriteChainableMethod; + var hasRequiredOverwriteChainableMethod; + + function requireOverwriteChainableMethod () { + if (hasRequiredOverwriteChainableMethod) return overwriteChainableMethod; + hasRequiredOverwriteChainableMethod = 1; + var chai = requireChai(); + var transferFlags$1 = transferFlags; + + /** + * ### .overwriteChainableMethod(ctx, name, method, chainingBehavior) + * + * Overwrites an already existing chainable method + * and provides access to the previous function or + * property. Must return functions to be used for + * name. + * + * utils.overwriteChainableMethod(chai.Assertion.prototype, 'lengthOf', + * function (_super) { + * } + * , function (_super) { + * } + * ); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteChainableMethod('foo', fn, fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.have.lengthOf(3); + * expect(myFoo).to.have.lengthOf.above(3); + * + * @param {Object} ctx object whose method / property is to be overwritten + * @param {String} name of method / property to overwrite + * @param {Function} method function that returns a function to be used for name + * @param {Function} chainingBehavior function that returns a function to be used for property + * @namespace Utils + * @name overwriteChainableMethod + * @api public + */ + + overwriteChainableMethod = function overwriteChainableMethod(ctx, name, method, chainingBehavior) { + var chainableBehavior = ctx.__methods[name]; + + var _chainingBehavior = chainableBehavior.chainingBehavior; + chainableBehavior.chainingBehavior = function overwritingChainableMethodGetter() { + var result = chainingBehavior(_chainingBehavior).call(this); + if (result !== undefined) { + return result; + } + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + }; + + var _method = chainableBehavior.method; + chainableBehavior.method = function overwritingChainableMethodWrapper() { + var result = method(_method).apply(this, arguments); + if (result !== undefined) { + return result; + } + + var newAssertion = new chai.Assertion(); + transferFlags$1(this, newAssertion); + return newAssertion; + }; + }; + return overwriteChainableMethod; } - exports.isFunction = isFunction; - function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; - } - exports.isPrimitive = isPrimitive; + /*! + * Chai - compareByInspect utility + * Copyright(c) 2011-2016 Jake Luer + * MIT Licensed + */ - exports.isBuffer = require('./support/isBuffer'); + /*! + * Module dependencies + */ - function objectToString(o) { - return Object.prototype.toString.call(o); - } + var inspect = inspect_1; + /** + * ### .compareByInspect(mixed, mixed) + * + * To be used as a compareFunction with Array.prototype.sort. Compares elements + * using inspect instead of default behavior of using toString so that Symbols + * and objects with irregular/missing toString can still be sorted without a + * TypeError. + * + * @param {Mixed} first element to compare + * @param {Mixed} second element to compare + * @returns {Number} -1 if 'a' should come before 'b'; otherwise 1 + * @name compareByInspect + * @namespace Utils + * @api public + */ - function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); - } + var compareByInspect = function compareByInspect(a, b) { + return inspect(a) < inspect(b) ? -1 : 1; + }; + /*! + * Chai - getOwnEnumerablePropertySymbols utility + * Copyright(c) 2011-2016 Jake Luer + * MIT Licensed + */ - var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; + /** + * ### .getOwnEnumerablePropertySymbols(object) + * + * This allows the retrieval of directly-owned enumerable property symbols of an + * object. This function is necessary because Object.getOwnPropertySymbols + * returns both enumerable and non-enumerable property symbols. + * + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getOwnEnumerablePropertySymbols + * @api public + */ - // 26 Feb 16:19:34 - function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); - } + var getOwnEnumerablePropertySymbols$1 = function getOwnEnumerablePropertySymbols(obj) { + if (typeof Object.getOwnPropertySymbols !== 'function') return []; + return Object.getOwnPropertySymbols(obj).filter(function (sym) { + return Object.getOwnPropertyDescriptor(obj, sym).enumerable; + }); + }; - // log is just a thin wrapper to console.log that prepends a timestamp - exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); + /*! + * Chai - getOwnEnumerableProperties utility + * Copyright(c) 2011-2016 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies + */ + + var getOwnEnumerablePropertySymbols = getOwnEnumerablePropertySymbols$1; + + /** + * ### .getOwnEnumerableProperties(object) + * + * This allows the retrieval of directly-owned enumerable property names and + * symbols of an object. This function is necessary because Object.keys only + * returns enumerable property names, not enumerable property symbols. + * + * @param {Object} object + * @returns {Array} + * @namespace Utils + * @name getOwnEnumerableProperties + * @api public + */ + + var getOwnEnumerableProperties = function getOwnEnumerableProperties(obj) { + return Object.keys(obj).concat(getOwnEnumerablePropertySymbols(obj)); }; + /* ! + * Chai - checkError utility + * Copyright(c) 2012-2016 Jake Luer + * MIT Licensed + */ + var getFunctionName = getFuncName_1; /** - * Inherit the prototype methods from one constructor into another. + * ### .checkError * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). + * Checks that an error conforms to a given set of criteria and/or retrieves information about it. * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. + * @api public */ - exports.inherits = require('inherits'); - exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; + /** + * ### .compatibleInstance(thrown, errorLike) + * + * Checks if two instances are compatible (strict equal). + * Returns false if errorLike is not an instance of Error, because instances + * can only be compatible if they're both error instances. + * + * @name compatibleInstance + * @param {Error} thrown error + * @param {Error|ErrorConstructor} errorLike object to compare against + * @namespace Utils + * @api public + */ - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; + function compatibleInstance(thrown, errorLike) { + return errorLike instanceof Error && thrown === errorLike; + } + + /** + * ### .compatibleConstructor(thrown, errorLike) + * + * Checks if two constructors are compatible. + * This function can receive either an error constructor or + * an error instance as the `errorLike` argument. + * Constructors are compatible if they're the same or if one is + * an instance of another. + * + * @name compatibleConstructor + * @param {Error} thrown error + * @param {Error|ErrorConstructor} errorLike object to compare against + * @namespace Utils + * @api public + */ + + function compatibleConstructor(thrown, errorLike) { + if (errorLike instanceof Error) { + // If `errorLike` is an instance of any error we compare their constructors + return thrown.constructor === errorLike.constructor || thrown instanceof errorLike.constructor; + } else if (errorLike.prototype instanceof Error || errorLike === Error) { + // If `errorLike` is a constructor that inherits from Error, we compare `thrown` to `errorLike` directly + return thrown.constructor === errorLike || thrown instanceof errorLike; } - return origin; - }; - function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); + return false; } - },{"./support/isBuffer":112,"inherits":111}],114:[function(require,module,exports){ - /*! + /** + * ### .compatibleMessage(thrown, errMatcher) + * + * Checks if an error's message is compatible with a matcher (String or RegExp). + * If the message contains the String or passes the RegExp test, + * it is considered compatible. + * + * @name compatibleMessage + * @param {Error} thrown error + * @param {String|RegExp} errMatcher to look for into the message + * @namespace Utils + * @api public + */ - diff v5.1.0 + function compatibleMessage(thrown, errMatcher) { + var comparisonString = typeof thrown === 'string' ? thrown : thrown.message; + if (errMatcher instanceof RegExp) { + return errMatcher.test(comparisonString); + } else if (typeof errMatcher === 'string') { + return comparisonString.indexOf(errMatcher) !== -1; // eslint-disable-line no-magic-numbers + } - Software License Agreement (BSD License) + return false; + } - Copyright (c) 2009-2015, Kevin Decker + /** + * ### .getConstructorName(errorLike) + * + * Gets the constructor name for an Error instance or constructor itself. + * + * @name getConstructorName + * @param {Error|ErrorConstructor} errorLike + * @namespace Utils + * @api public + */ - All rights reserved. + function getConstructorName(errorLike) { + var constructorName = errorLike; + if (errorLike instanceof Error) { + constructorName = getFunctionName(errorLike.constructor); + } else if (typeof errorLike === 'function') { + // If `err` is not an instance of Error it is an error constructor itself or another function. + // If we've got a common function we get its name, otherwise we may need to create a new instance + // of the error just in case it's a poorly-constructed error. Please see chaijs/chai/issues/45 to know more. + constructorName = getFunctionName(errorLike); + if (constructorName === '') { + var newConstructorName = getFunctionName(new errorLike()); // eslint-disable-line new-cap + constructorName = newConstructorName || constructorName; + } + } - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: + return constructorName; + } - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. + /** + * ### .getMessage(errorLike) + * + * Gets the error message from an error. + * If `err` is a String itself, we return it. + * If the error has no message, we return an empty string. + * + * @name getMessage + * @param {Error|String} errorLike + * @namespace Utils + * @api public + */ - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. + function getMessage(errorLike) { + var msg = ''; + if (errorLike && errorLike.message) { + msg = errorLike.message; + } else if (typeof errorLike === 'string') { + msg = errorLike; + } - * Neither the name of Kevin Decker nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission. + return msg; + } - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - @license - */ - (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = global || self, factory(global.Diff = {})); - }(this, (function (exports) { - function Diff() {} - Diff.prototype = { - diff: function diff(oldString, newString) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var callback = options.callback; + var checkError = { + compatibleInstance: compatibleInstance, + compatibleConstructor: compatibleConstructor, + compatibleMessage: compatibleMessage, + getMessage: getMessage, + getConstructorName: getConstructorName, + }; - if (typeof options === 'function') { - callback = options; - options = {}; - } + /*! + * Chai - isNaN utility + * Copyright(c) 2012-2015 Sakthipriyan Vairamani + * MIT Licensed + */ - this.options = options; - var self = this; + /** + * ### .isNaN(value) + * + * Checks if the given value is NaN or not. + * + * utils.isNaN(NaN); // true + * + * @param {Value} The value which has to be checked if it is NaN + * @name isNaN + * @api private + */ - function done(value) { - if (callback) { - setTimeout(function () { - callback(undefined, value); - }, 0); - return true; - } else { - return value; - } - } // Allow subclasses to massage the input prior to running + function isNaN$1(value) { + // Refer http://www.ecma-international.org/ecma-262/6.0/#sec-isnan-number + // section's NOTE. + return value !== value; + } + // If ECMAScript 6's Number.isNaN is present, prefer that. + var _isNaN = Number.isNaN || isNaN$1; - oldString = this.castInput(oldString); - newString = this.castInput(newString); - oldString = this.removeEmpty(this.tokenize(oldString)); - newString = this.removeEmpty(this.tokenize(newString)); - var newLen = newString.length, - oldLen = oldString.length; - var editLength = 1; - var maxEditLength = newLen + oldLen; + var type = typeDetectExports; - if (options.maxEditLength) { - maxEditLength = Math.min(maxEditLength, options.maxEditLength); - } + var flag = flag$5; + + function isObjectType(obj) { + var objectType = type(obj); + var objectTypes = ['Array', 'Object', 'function']; + + return objectTypes.indexOf(objectType) !== -1; + } - var bestPath = [{ - newPos: -1, - components: [] - }]; // Seed editLength = 0, i.e. the content starts with the same values + /** + * ### .getOperator(message) + * + * Extract the operator from error message. + * Operator defined is based on below link + * https://nodejs.org/api/assert.html#assert_assert. + * + * Returns the `operator` or `undefined` value for an Assertion. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @namespace Utils + * @name getOperator + * @api public + */ - var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); + var getOperator = function getOperator(obj, args) { + var operator = flag(obj, 'operator'); + var negate = flag(obj, 'negate'); + var expected = args[3]; + var msg = negate ? args[2] : args[1]; - if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { - // Identity per the equality and tokenizer - return done([{ - value: this.join(newString), - count: newString.length - }]); - } // Main worker method. checks all permutations of a given edit length for acceptance. + if (operator) { + return operator; + } + if (typeof msg === 'function') msg = msg(); - function execEditLength() { - for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { - var basePath = void 0; + msg = msg || ''; + if (!msg) { + return undefined; + } - var addPath = bestPath[diagonalPath - 1], - removePath = bestPath[diagonalPath + 1], - _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (/\shave\s/.test(msg)) { + return undefined; + } - if (addPath) { - // No one else is going to attempt to use this value, clear it - bestPath[diagonalPath - 1] = undefined; - } + var isObject = isObjectType(expected); + if (/\snot\s/.test(msg)) { + return isObject ? 'notDeepStrictEqual' : 'notStrictEqual'; + } - var canAdd = addPath && addPath.newPos + 1 < newLen, - canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen; + return isObject ? 'deepStrictEqual' : 'strictEqual'; + }; - if (!canAdd && !canRemove) { - // If this path is a terminal then prune - bestPath[diagonalPath] = undefined; - continue; - } // Select the diagonal that we want to branch from. We select the prior - // path whose position in the new string is the farthest from the origin - // and does not pass the bounds of the diff graph + /*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */ + var hasRequiredUtils; - if (!canAdd || canRemove && addPath.newPos < removePath.newPos) { - basePath = clonePath(removePath); - self.pushComponent(basePath.components, undefined, true); - } else { - basePath = addPath; // No need to clone, we've pulled it from the list + function requireUtils () { + if (hasRequiredUtils) return utils; + hasRequiredUtils = 1; + /*! + * Dependencies that are used for multiple exports are required here only once + */ - basePath.newPos++; - self.pushComponent(basePath.components, true, undefined); - } + var pathval$1 = pathval; - _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done + /*! + * test utility + */ - if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) { - return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken)); - } else { - // Otherwise track this path as a potential candidate and continue. - bestPath[diagonalPath] = basePath; - } - } + utils.test = test; - editLength++; - } // Performs the length of edit iteration. Is a bit fugly as this has to support the - // sync and async mode which is never fun. Loops over execEditLength until a value - // is produced, or until the edit length exceeds options.maxEditLength (if given), - // in which case it will return undefined. + /*! + * type utility + */ + utils.type = typeDetectExports; - if (callback) { - (function exec() { - setTimeout(function () { - if (editLength > maxEditLength) { - return callback(); - } + /*! + * expectTypes utility + */ + utils.expectTypes = expectTypes; - if (!execEditLength()) { - exec(); - } - }, 0); - })(); - } else { - while (editLength <= maxEditLength) { - var ret = execEditLength(); + /*! + * message utility + */ - if (ret) { - return ret; - } - } - } - }, - pushComponent: function pushComponent(components, added, removed) { - var last = components[components.length - 1]; + utils.getMessage = getMessage$1; - if (last && last.added === added && last.removed === removed) { - // We need to clone here as the component clone operation is just - // as shallow array clone - components[components.length - 1] = { - count: last.count + 1, - added: added, - removed: removed - }; - } else { - components.push({ - count: 1, - added: added, - removed: removed - }); - } - }, - extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) { - var newLen = newString.length, - oldLen = oldString.length, - newPos = basePath.newPos, - oldPos = newPos - diagonalPath, - commonCount = 0; + /*! + * actual utility + */ - while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) { - newPos++; - oldPos++; - commonCount++; - } + utils.getActual = getActual$1; - if (commonCount) { - basePath.components.push({ - count: commonCount - }); - } + /*! + * Inspect util + */ - basePath.newPos = newPos; - return oldPos; - }, - equals: function equals(left, right) { - if (this.options.comparator) { - return this.options.comparator(left, right); - } else { - return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase(); - } - }, - removeEmpty: function removeEmpty(array) { - var ret = []; + utils.inspect = inspect_1; - for (var i = 0; i < array.length; i++) { - if (array[i]) { - ret.push(array[i]); - } - } + /*! + * Object Display util + */ - return ret; - }, - castInput: function castInput(value) { - return value; - }, - tokenize: function tokenize(value) { - return value.split(''); - }, - join: function join(chars) { - return chars.join(''); - } - }; + utils.objDisplay = objDisplay$1; - function buildValues(diff, components, newString, oldString, useLongestToken) { - var componentPos = 0, - componentLen = components.length, - newPos = 0, - oldPos = 0; + /*! + * Flag utility + */ - for (; componentPos < componentLen; componentPos++) { - var component = components[componentPos]; + utils.flag = flag$5; - if (!component.removed) { - if (!component.added && useLongestToken) { - var value = newString.slice(newPos, newPos + component.count); - value = value.map(function (value, i) { - var oldValue = oldString[oldPos + i]; - return oldValue.length > value.length ? oldValue : value; - }); - component.value = diff.join(value); - } else { - component.value = diff.join(newString.slice(newPos, newPos + component.count)); - } + /*! + * Flag transferring utility + */ - newPos += component.count; // Common case + utils.transferFlags = transferFlags; - if (!component.added) { - oldPos += component.count; - } - } else { - component.value = diff.join(oldString.slice(oldPos, oldPos + component.count)); - oldPos += component.count; // Reverse add and remove so removes are output first to match common convention - // The diffing algorithm is tied to add then remove output and this is the simplest - // route to get the desired output with minimal overhead. + /*! + * Deep equal utility + */ - if (componentPos && components[componentPos - 1].added) { - var tmp = components[componentPos - 1]; - components[componentPos - 1] = components[componentPos]; - components[componentPos] = tmp; - } - } - } // Special case handle for when one terminal is ignored (i.e. whitespace). - // For this case we merge the terminal into the prior string and drop the change. - // This is only available for string mode. + utils.eql = deepEqlExports; + /*! + * Deep path info + */ - var lastComponent = components[componentLen - 1]; + utils.getPathInfo = pathval$1.getPathInfo; - if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { - components[componentLen - 2].value += lastComponent.value; - components.pop(); - } + /*! + * Check if a property exists + */ - return components; - } + utils.hasProperty = pathval$1.hasProperty; - function clonePath(path) { - return { - newPos: path.newPos, - components: path.components.slice(0) - }; - } + /*! + * Function name + */ - var characterDiff = new Diff(); - function diffChars(oldStr, newStr, options) { - return characterDiff.diff(oldStr, newStr, options); - } + utils.getName = getFuncName_1; - function generateOptions(options, defaults) { - if (typeof options === 'function') { - defaults.callback = options; - } else if (options) { - for (var name in options) { - /* istanbul ignore else */ - if (options.hasOwnProperty(name)) { - defaults[name] = options[name]; - } - } - } + /*! + * add Property + */ - return defaults; - } + utils.addProperty = requireAddProperty(); - // - // Ranges and exceptions: - // Latin-1 Supplement, 0080–00FF - // - U+00D7 × Multiplication sign - // - U+00F7 ÷ Division sign - // Latin Extended-A, 0100–017F - // Latin Extended-B, 0180–024F - // IPA Extensions, 0250–02AF - // Spacing Modifier Letters, 02B0–02FF - // - U+02C7 ˇ ˇ Caron - // - U+02D8 ˘ ˘ Breve - // - U+02D9 ˙ ˙ Dot Above - // - U+02DA ˚ ˚ Ring Above - // - U+02DB ˛ ˛ Ogonek - // - U+02DC ˜ ˜ Small Tilde - // - U+02DD ˝ ˝ Double Acute Accent - // Latin Extended Additional, 1E00–1EFF + /*! + * add Method + */ - var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/; - var reWhitespace = /\S/; - var wordDiff = new Diff(); + utils.addMethod = requireAddMethod(); - wordDiff.equals = function (left, right) { - if (this.options.ignoreCase) { - left = left.toLowerCase(); - right = right.toLowerCase(); - } + /*! + * overwrite Property + */ - return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right); - }; + utils.overwriteProperty = requireOverwriteProperty(); - wordDiff.tokenize = function (value) { - // All whitespace symbols except newline group into one token, each newline - in separate token - var tokens = value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/); // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set. + /*! + * overwrite Method + */ - for (var i = 0; i < tokens.length - 1; i++) { - // If we have an empty string in the next field and we have only word chars before and after, merge - if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) { - tokens[i] += tokens[i + 2]; - tokens.splice(i + 1, 2); - i--; - } - } + utils.overwriteMethod = requireOverwriteMethod(); - return tokens; - }; + /*! + * Add a chainable method + */ - function diffWords(oldStr, newStr, options) { - options = generateOptions(options, { - ignoreWhitespace: true - }); - return wordDiff.diff(oldStr, newStr, options); - } - function diffWordsWithSpace(oldStr, newStr, options) { - return wordDiff.diff(oldStr, newStr, options); - } + utils.addChainableMethod = requireAddChainableMethod(); - var lineDiff = new Diff(); + /*! + * Overwrite chainable method + */ - lineDiff.tokenize = function (value) { - var retLines = [], - linesAndNewlines = value.split(/(\n|\r\n)/); // Ignore the final empty token that occurs if the string ends with a new line + utils.overwriteChainableMethod = requireOverwriteChainableMethod(); - if (!linesAndNewlines[linesAndNewlines.length - 1]) { - linesAndNewlines.pop(); - } // Merge the content and line separators into single tokens + /*! + * Compare by inspect method + */ + utils.compareByInspect = compareByInspect; - for (var i = 0; i < linesAndNewlines.length; i++) { - var line = linesAndNewlines[i]; + /*! + * Get own enumerable property symbols method + */ - if (i % 2 && !this.options.newlineIsToken) { - retLines[retLines.length - 1] += line; - } else { - if (this.options.ignoreWhitespace) { - line = line.trim(); - } + utils.getOwnEnumerablePropertySymbols = getOwnEnumerablePropertySymbols$1; - retLines.push(line); - } - } + /*! + * Get own enumerable properties method + */ - return retLines; - }; + utils.getOwnEnumerableProperties = getOwnEnumerableProperties; - function diffLines(oldStr, newStr, callback) { - return lineDiff.diff(oldStr, newStr, callback); - } - function diffTrimmedLines(oldStr, newStr, callback) { - var options = generateOptions(callback, { - ignoreWhitespace: true - }); - return lineDiff.diff(oldStr, newStr, options); - } + /*! + * Checks error against a given set of criteria + */ - var sentenceDiff = new Diff(); + utils.checkError = checkError; - sentenceDiff.tokenize = function (value) { - return value.split(/(\S.+?[.!?])(?=\s+|$)/); - }; + /*! + * Proxify util + */ - function diffSentences(oldStr, newStr, callback) { - return sentenceDiff.diff(oldStr, newStr, callback); - } + utils.proxify = proxify; - var cssDiff = new Diff(); + /*! + * addLengthGuard util + */ - cssDiff.tokenize = function (value) { - return value.split(/([{}:;,]|\s+)/); - }; + utils.addLengthGuard = addLengthGuard; - function diffCss(oldStr, newStr, callback) { - return cssDiff.diff(oldStr, newStr, callback); - } + /*! + * isProxyEnabled helper + */ - function _typeof(obj) { - "@babel/helpers - typeof"; + utils.isProxyEnabled = isProxyEnabled$1; - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - _typeof = function (obj) { - return typeof obj; - }; - } else { - _typeof = function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } + /*! + * isNaN method + */ - return _typeof(obj); - } + utils.isNaN = _isNaN; - function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); - } + /*! + * getOperator method + */ - function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) return _arrayLikeToArray(arr); - } + utils.getOperator = getOperator; + return utils; + } - function _iterableToArray(iter) { - if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); - } + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ - function _unsupportedIterableToArray(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); - } + var config = config$5; - function _arrayLikeToArray(arr, len) { - if (len == null || len > arr.length) len = arr.length; + var assertion = function (_chai, util) { + /*! + * Module dependencies. + */ - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + var AssertionError = _chai.AssertionError + , flag = util.flag; - return arr2; - } + /*! + * Module export. + */ - function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + _chai.Assertion = Assertion; + + /*! + * Assertion Constructor + * + * Creates object for chaining. + * + * `Assertion` objects contain metadata in the form of flags. Three flags can + * be assigned during instantiation by passing arguments to this constructor: + * + * - `object`: This flag contains the target of the assertion. For example, in + * the assertion `expect(numKittens).to.equal(7);`, the `object` flag will + * contain `numKittens` so that the `equal` assertion can reference it when + * needed. + * + * - `message`: This flag contains an optional custom error message to be + * prepended to the error message that's generated by the assertion when it + * fails. + * + * - `ssfi`: This flag stands for "start stack function indicator". It + * contains a function reference that serves as the starting point for + * removing frames from the stack trace of the error that's created by the + * assertion when it fails. The goal is to provide a cleaner stack trace to + * end users by removing Chai's internal functions. Note that it only works + * in environments that support `Error.captureStackTrace`, and only when + * `Chai.config.includeStack` hasn't been set to `false`. + * + * - `lockSsfi`: This flag controls whether or not the given `ssfi` flag + * should retain its current value, even as assertions are chained off of + * this object. This is usually set to `true` when creating a new assertion + * from within another assertion. It's also temporarily set to `true` before + * an overwritten assertion gets called by the overwriting assertion. + * + * @param {Mixed} obj target of the assertion + * @param {String} msg (optional) custom error message + * @param {Function} ssfi (optional) starting point for removing stack frames + * @param {Boolean} lockSsfi (optional) whether or not the ssfi flag is locked + * @api private + */ + + function Assertion (obj, msg, ssfi, lockSsfi) { + flag(this, 'ssfi', ssfi || Assertion); + flag(this, 'lockSsfi', lockSsfi); + flag(this, 'object', obj); + flag(this, 'message', msg); + + return util.proxify(this); } - var objectPrototypeToString = Object.prototype.toString; - var jsonDiff = new Diff(); // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a - // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: + Object.defineProperty(Assertion, 'includeStack', { + get: function() { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + return config.includeStack; + }, + set: function(value) { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + config.includeStack = value; + } + }); - jsonDiff.useLongestToken = true; - jsonDiff.tokenize = lineDiff.tokenize; + Object.defineProperty(Assertion, 'showDiff', { + get: function() { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + return config.showDiff; + }, + set: function(value) { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + config.showDiff = value; + } + }); - jsonDiff.castInput = function (value) { - var _this$options = this.options, - undefinedReplacement = _this$options.undefinedReplacement, - _this$options$stringi = _this$options.stringifyReplacer, - stringifyReplacer = _this$options$stringi === void 0 ? function (k, v) { - return typeof v === 'undefined' ? undefinedReplacement : v; - } : _this$options$stringi; - return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); + Assertion.addProperty = function (name, fn) { + util.addProperty(this.prototype, name, fn); }; - jsonDiff.equals = function (left, right) { - return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')); + Assertion.addMethod = function (name, fn) { + util.addMethod(this.prototype, name, fn); }; - function diffJson(oldObj, newObj, options) { - return jsonDiff.diff(oldObj, newObj, options); - } // This function handles the presence of circular references by bailing out when encountering an - // object that is already on the "stack" of items being processed. Accepts an optional replacer + Assertion.addChainableMethod = function (name, fn, chainingBehavior) { + util.addChainableMethod(this.prototype, name, fn, chainingBehavior); + }; - function canonicalize(obj, stack, replacementStack, replacer, key) { - stack = stack || []; - replacementStack = replacementStack || []; + Assertion.overwriteProperty = function (name, fn) { + util.overwriteProperty(this.prototype, name, fn); + }; - if (replacer) { - obj = replacer(key, obj); - } + Assertion.overwriteMethod = function (name, fn) { + util.overwriteMethod(this.prototype, name, fn); + }; - var i; + Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { + util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); + }; - for (i = 0; i < stack.length; i += 1) { - if (stack[i] === obj) { - return replacementStack[i]; + /** + * ### .assert(expression, message, negateMessage, expected, actual, showDiff) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String|Function} message or function that returns message to display if expression fails + * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails + * @api private + */ + + Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { + var ok = util.test(this, arguments); + if (false !== showDiff) showDiff = true; + if (undefined === expected && undefined === _actual) showDiff = false; + if (true !== config.showDiff) showDiff = false; + + if (!ok) { + msg = util.getMessage(this, arguments); + var actual = util.getActual(this, arguments); + var assertionErrorObjectProperties = { + actual: actual + , expected: expected + , showDiff: showDiff + }; + + var operator = util.getOperator(this, arguments); + if (operator) { + assertionErrorObjectProperties.operator = operator; } - } - var canonicalizedObj; + throw new AssertionError( + msg, + assertionErrorObjectProperties, + (config.includeStack) ? this.assert : flag(this, 'ssfi')); + } + }; - if ('[object Array]' === objectPrototypeToString.call(obj)) { - stack.push(obj); - canonicalizedObj = new Array(obj.length); - replacementStack.push(canonicalizedObj); + /*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */ - for (i = 0; i < obj.length; i += 1) { - canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key); + Object.defineProperty(Assertion.prototype, '_obj', + { get: function () { + return flag(this, 'object'); + } + , set: function (val) { + flag(this, 'object', val); } + }); + }; - stack.pop(); - replacementStack.pop(); - return canonicalizedObj; - } + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ - if (obj && obj.toJSON) { - obj = obj.toJSON(); - } + var assertions = function (chai, _) { + var Assertion = chai.Assertion + , AssertionError = chai.AssertionError + , flag = _.flag; - if (_typeof(obj) === 'object' && obj !== null) { - stack.push(obj); - canonicalizedObj = {}; - replacementStack.push(canonicalizedObj); + /** + * ### Language Chains + * + * The following are provided as chainable getters to improve the readability + * of your assertions. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - which + * - and + * - has + * - have + * - with + * - at + * - of + * - same + * - but + * - does + * - still + * - also + * + * @name language chains + * @namespace BDD + * @api public + */ - var sortedKeys = [], - _key; + [ 'to', 'be', 'been', 'is' + , 'and', 'has', 'have', 'with' + , 'that', 'which', 'at', 'of' + , 'same', 'but', 'does', 'still', "also" ].forEach(function (chain) { + Assertion.addProperty(chain); + }); + + /** + * ### .not + * + * Negates all assertions that follow in the chain. + * + * expect(function () {}).to.not.throw(); + * expect({a: 1}).to.not.have.property('b'); + * expect([1, 2]).to.be.an('array').that.does.not.include(3); + * + * Just because you can negate any assertion with `.not` doesn't mean you + * should. With great power comes great responsibility. It's often best to + * assert that the one expected output was produced, rather than asserting + * that one of countless unexpected outputs wasn't produced. See individual + * assertions for specific guidance. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.not.equal(1); // Not recommended + * + * @name not + * @namespace BDD + * @api public + */ + + Assertion.addProperty('not', function () { + flag(this, 'negate', true); + }); + + /** + * ### .deep + * + * Causes all `.equal`, `.include`, `.members`, `.keys`, and `.property` + * assertions that follow in the chain to use deep equality instead of strict + * (`===`) equality. See the `deep-eql` project page for info on the deep + * equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) equals `{a: 1}` + * expect({a: 1}).to.deep.equal({a: 1}); + * expect({a: 1}).to.not.equal({a: 1}); + * + * // Target array deeply (but not strictly) includes `{a: 1}` + * expect([{a: 1}]).to.deep.include({a: 1}); + * expect([{a: 1}]).to.not.include({a: 1}); + * + * // Target object deeply (but not strictly) includes `x: {a: 1}` + * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); + * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); + * + * // Target array deeply (but not strictly) has member `{a: 1}` + * expect([{a: 1}]).to.have.deep.members([{a: 1}]); + * expect([{a: 1}]).to.not.have.members([{a: 1}]); + * + * // Target set deeply (but not strictly) has key `{a: 1}` + * expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]); + * expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]); + * + * // Target object deeply (but not strictly) has property `x: {a: 1}` + * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); + * expect({x: {a: 1}}).to.not.have.property('x', {a: 1}); + * + * @name deep + * @namespace BDD + * @api public + */ + + Assertion.addProperty('deep', function () { + flag(this, 'deep', true); + }); + + /** + * ### .nested + * + * Enables dot- and bracket-notation in all `.property` and `.include` + * assertions that follow in the chain. + * + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]'); + * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]'); + * expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\.a.\\[b\\]': 'x'}); + * + * `.nested` cannot be combined with `.own`. + * + * @name nested + * @namespace BDD + * @api public + */ + + Assertion.addProperty('nested', function () { + flag(this, 'nested', true); + }); + + /** + * ### .own + * + * Causes all `.property` and `.include` assertions that follow in the chain + * to ignore inherited properties. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.have.own.property('a'); + * expect({a: 1}).to.have.property('b'); + * expect({a: 1}).to.not.have.own.property('b'); + * + * expect({a: 1}).to.own.include({a: 1}); + * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); + * + * `.own` cannot be combined with `.nested`. + * + * @name own + * @namespace BDD + * @api public + */ + + Assertion.addProperty('own', function () { + flag(this, 'own', true); + }); + + /** + * ### .ordered + * + * Causes all `.members` assertions that follow in the chain to require that + * members be in the same order. + * + * expect([1, 2]).to.have.ordered.members([1, 2]) + * .but.not.have.ordered.members([2, 1]); + * + * When `.include` and `.ordered` are combined, the ordering begins at the + * start of both arrays. + * + * expect([1, 2, 3]).to.include.ordered.members([1, 2]) + * .but.not.include.ordered.members([2, 3]); + * + * @name ordered + * @namespace BDD + * @api public + */ + + Assertion.addProperty('ordered', function () { + flag(this, 'ordered', true); + }); + + /** + * ### .any + * + * Causes all `.keys` assertions that follow in the chain to only require that + * the target have at least one of the given keys. This is the opposite of + * `.all`, which requires that the target have all of the given keys. + * + * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd'); + * + * See the `.keys` doc for guidance on when to use `.any` or `.all`. + * + * @name any + * @namespace BDD + * @api public + */ + + Assertion.addProperty('any', function () { + flag(this, 'any', true); + flag(this, 'all', false); + }); - for (_key in obj) { - /* istanbul ignore else */ - if (obj.hasOwnProperty(_key)) { - sortedKeys.push(_key); - } - } + /** + * ### .all + * + * Causes all `.keys` assertions that follow in the chain to require that the + * target have all of the given keys. This is the opposite of `.any`, which + * only requires that the target have at least one of the given keys. + * + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * + * Note that `.all` is used by default when neither `.all` nor `.any` are + * added earlier in the chain. However, it's often best to add `.all` anyway + * because it improves readability. + * + * See the `.keys` doc for guidance on when to use `.any` or `.all`. + * + * @name all + * @namespace BDD + * @api public + */ - sortedKeys.sort(); + Assertion.addProperty('all', function () { + flag(this, 'all', true); + flag(this, 'any', false); + }); - for (i = 0; i < sortedKeys.length; i += 1) { - _key = sortedKeys[i]; - canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key); - } + /** + * ### .a(type[, msg]) + * + * Asserts that the target's type is equal to the given string `type`. Types + * are case insensitive. See the `type-detect` project page for info on the + * type detection algorithm: https://github.com/chaijs/type-detect. + * + * expect('foo').to.be.a('string'); + * expect({a: 1}).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * expect(new Error).to.be.an('error'); + * expect(Promise.resolve()).to.be.a('promise'); + * expect(new Float32Array).to.be.a('float32array'); + * expect(Symbol()).to.be.a('symbol'); + * + * `.a` supports objects that have a custom type set via `Symbol.toStringTag`. + * + * var myObj = { + * [Symbol.toStringTag]: 'myCustomType' + * }; + * + * expect(myObj).to.be.a('myCustomType').but.not.an('object'); + * + * It's often best to use `.a` to check a target's type before making more + * assertions on the same target. That way, you avoid unexpected behavior from + * any assertion that does different things based on the target's type. + * + * expect([1, 2, 3]).to.be.an('array').that.includes(2); + * expect([]).to.be.an('array').that.is.empty; + * + * Add `.not` earlier in the chain to negate `.a`. However, it's often best to + * assert that the target is the expected type, rather than asserting that it + * isn't one of many unexpected types. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.an('array'); // Not recommended + * + * `.a` accepts an optional `msg` argument which is a custom error message to + * show when the assertion fails. The message can also be given as the second + * argument to `expect`. + * + * expect(1).to.be.a('string', 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.a('string'); + * + * `.a` can also be used as a language chain to improve the readability of + * your assertions. + * + * expect({b: 2}).to.have.a.property('b'); + * + * The alias `.an` can be used interchangeably with `.a`. + * + * @name a + * @alias an + * @param {String} type + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - stack.pop(); - replacementStack.pop(); - } else { - canonicalizedObj = obj; - } + function an (type, msg) { + if (msg) flag(this, 'message', msg); + type = type.toLowerCase(); + var obj = flag(this, 'object') + , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a '; - return canonicalizedObj; + this.assert( + type === _.type(obj).toLowerCase() + , 'expected #{this} to be ' + article + type + , 'expected #{this} not to be ' + article + type + ); } - var arrayDiff = new Diff(); + Assertion.addChainableMethod('an', an); + Assertion.addChainableMethod('a', an); - arrayDiff.tokenize = function (value) { - return value.slice(); - }; + /** + * ### .include(val[, msg]) + * + * When the target is a string, `.include` asserts that the given string `val` + * is a substring of the target. + * + * expect('foobar').to.include('foo'); + * + * When the target is an array, `.include` asserts that the given `val` is a + * member of the target. + * + * expect([1, 2, 3]).to.include(2); + * + * When the target is an object, `.include` asserts that the given object + * `val`'s properties are a subset of the target's properties. + * + * expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2}); + * + * When the target is a Set or WeakSet, `.include` asserts that the given `val` is a + * member of the target. SameValueZero equality algorithm is used. + * + * expect(new Set([1, 2])).to.include(2); + * + * When the target is a Map, `.include` asserts that the given `val` is one of + * the values of the target. SameValueZero equality algorithm is used. + * + * expect(new Map([['a', 1], ['b', 2]])).to.include(2); + * + * Because `.include` does different things based on the target's type, it's + * important to check the target's type before using `.include`. See the `.a` + * doc for info on testing a target's type. + * + * expect([1, 2, 3]).to.be.an('array').that.includes(2); + * + * By default, strict (`===`) equality is used to compare array members and + * object properties. Add `.deep` earlier in the chain to use deep equality + * instead (WeakSet targets are not supported). See the `deep-eql` project + * page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target array deeply (but not strictly) includes `{a: 1}` + * expect([{a: 1}]).to.deep.include({a: 1}); + * expect([{a: 1}]).to.not.include({a: 1}); + * + * // Target object deeply (but not strictly) includes `x: {a: 1}` + * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); + * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); + * + * By default, all of the target's properties are searched when working with + * objects. This includes properties that are inherited and/or non-enumerable. + * Add `.own` earlier in the chain to exclude the target's inherited + * properties from the search. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.own.include({a: 1}); + * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); + * + * Note that a target object is always only searched for `val`'s own + * enumerable properties. + * + * `.deep` and `.own` can be combined. + * + * expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}}); + * + * Add `.nested` earlier in the chain to enable dot- and bracket-notation when + * referencing nested properties. + * + * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2}); + * + * `.deep` and `.nested` can be combined. + * + * expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}}); + * + * `.own` and `.nested` cannot be combined. + * + * Add `.not` earlier in the chain to negate `.include`. + * + * expect('foobar').to.not.include('taco'); + * expect([1, 2, 3]).to.not.include(4); + * + * However, it's dangerous to negate `.include` when the target is an object. + * The problem is that it creates uncertain expectations by asserting that the + * target object doesn't have all of `val`'s key/value pairs but may or may + * not have some of them. It's often best to identify the exact output that's + * expected, and then write an assertion that only accepts that exact output. + * + * When the target object isn't even expected to have `val`'s keys, it's + * often best to assert exactly that. + * + * expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended + * expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended + * + * When the target object is expected to have `val`'s keys, it's often best to + * assert that each of the properties has its expected value, rather than + * asserting that each property doesn't have one of many unexpected values. + * + * expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended + * expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended + * + * `.include` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2, 3]).to.include(4, 'nooo why fail??'); + * expect([1, 2, 3], 'nooo why fail??').to.include(4); + * + * `.include` can also be used as a language chain, causing all `.members` and + * `.keys` assertions that follow in the chain to require the target to be a + * superset of the expected set, rather than an identical set. Note that + * `.members` ignores duplicates in the subset when `.include` is added. + * + * // Target object's keys are a superset of ['a', 'b'] but not identical + * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b'); + * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b'); + * + * // Target array is a superset of [1, 2] but not identical + * expect([1, 2, 3]).to.include.members([1, 2]); + * expect([1, 2, 3]).to.not.have.members([1, 2]); + * + * // Duplicates in the subset are ignored + * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]); + * + * Note that adding `.any` earlier in the chain causes the `.keys` assertion + * to ignore `.include`. + * + * // Both assertions are identical + * expect({a: 1}).to.include.any.keys('a', 'b'); + * expect({a: 1}).to.have.any.keys('a', 'b'); + * + * The aliases `.includes`, `.contain`, and `.contains` can be used + * interchangeably with `.include`. + * + * @name include + * @alias contain + * @alias includes + * @alias contains + * @param {Mixed} val + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - arrayDiff.join = arrayDiff.removeEmpty = function (value) { - return value; - }; + function SameValueZero(a, b) { + return (_.isNaN(a) && _.isNaN(b)) || a === b; + } - function diffArrays(oldArr, newArr, callback) { - return arrayDiff.diff(oldArr, newArr, callback); + function includeChainingBehavior () { + flag(this, 'contains', true); } - function parsePatch(uniDiff) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/), - delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [], - list = [], - i = 0; + function include (val, msg) { + if (msg) flag(this, 'message', msg); - function parseIndex() { - var index = {}; - list.push(index); // Parse diff metadata + var obj = flag(this, 'object') + , objType = _.type(obj).toLowerCase() + , flagMsg = flag(this, 'message') + , negate = flag(this, 'negate') + , ssfi = flag(this, 'ssfi') + , isDeep = flag(this, 'deep') + , descriptor = isDeep ? 'deep ' : ''; - while (i < diffstr.length) { - var line = diffstr[i]; // File header found, end parsing diff metadata + flagMsg = flagMsg ? flagMsg + ': ' : ''; - if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) { - break; - } // Diff index + var included = false; + switch (objType) { + case 'string': + included = obj.indexOf(val) !== -1; + break; - var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line); + case 'weakset': + if (isDeep) { + throw new AssertionError( + flagMsg + 'unable to use .deep.include with WeakSet', + undefined, + ssfi + ); + } - if (header) { - index.index = header[1]; + included = obj.has(val); + break; + + case 'map': + var isEql = isDeep ? _.eql : SameValueZero; + obj.forEach(function (item) { + included = included || isEql(item, val); + }); + break; + + case 'set': + if (isDeep) { + obj.forEach(function (item) { + included = included || _.eql(item, val); + }); + } else { + included = obj.has(val); } + break; - i++; - } // Parse file headers if they are defined. Unified diff requires them, but - // there's no technical issues to have an isolated hunk without file header + case 'array': + if (isDeep) { + included = obj.some(function (item) { + return _.eql(item, val); + }); + } else { + included = obj.indexOf(val) !== -1; + } + break; + default: + // This block is for asserting a subset of properties in an object. + // `_.expectTypes` isn't used here because `.include` should work with + // objects with a custom `@@toStringTag`. + if (val !== Object(val)) { + throw new AssertionError( + flagMsg + 'the given combination of arguments (' + + objType + ' and ' + + _.type(val).toLowerCase() + ')' + + ' is invalid for this assertion. ' + + 'You can use an array, a map, an object, a set, a string, ' + + 'or a weakset instead of a ' + + _.type(val).toLowerCase(), + undefined, + ssfi + ); + } - parseFileHeader(index); - parseFileHeader(index); // Parse hunks + var props = Object.keys(val) + , firstErr = null + , numErrs = 0; - index.hunks = []; + props.forEach(function (prop) { + var propAssertion = new Assertion(obj); + _.transferFlags(this, propAssertion, true); + flag(propAssertion, 'lockSsfi', true); - while (i < diffstr.length) { - var _line = diffstr[i]; + if (!negate || props.length === 1) { + propAssertion.property(prop, val[prop]); + return; + } - if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) { - break; - } else if (/^@@/.test(_line)) { - index.hunks.push(parseHunk()); - } else if (_line && options.strict) { - // Ignore unexpected content unless in strict mode - throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line)); - } else { - i++; + try { + propAssertion.property(prop, val[prop]); + } catch (err) { + if (!_.checkError.compatibleConstructor(err, AssertionError)) { + throw err; + } + if (firstErr === null) firstErr = err; + numErrs++; + } + }, this); + + // When validating .not.include with multiple properties, we only want + // to throw an assertion error if all of the properties are included, + // in which case we throw the first property assertion error that we + // encountered. + if (negate && props.length > 1 && numErrs === props.length) { + throw firstErr; } - } - } // Parses the --- and +++ headers, if none are found, no lines - // are consumed. + return; + } + // Assert inclusion in collection or substring in a string. + this.assert( + included + , 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val) + , 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val)); + } - function parseFileHeader(index) { - var fileHeader = /^(---|\+\+\+)\s+(.*)$/.exec(diffstr[i]); + Assertion.addChainableMethod('include', include, includeChainingBehavior); + Assertion.addChainableMethod('contain', include, includeChainingBehavior); + Assertion.addChainableMethod('contains', include, includeChainingBehavior); + Assertion.addChainableMethod('includes', include, includeChainingBehavior); - if (fileHeader) { - var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; - var data = fileHeader[2].split('\t', 2); - var fileName = data[0].replace(/\\\\/g, '\\'); + /** + * ### .ok + * + * Asserts that the target is a truthy value (considered `true` in boolean context). + * However, it's often best to assert that the target is strictly (`===`) or + * deeply equal to its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.ok; // Not recommended + * + * expect(true).to.be.true; // Recommended + * expect(true).to.be.ok; // Not recommended + * + * Add `.not` earlier in the chain to negate `.ok`. + * + * expect(0).to.equal(0); // Recommended + * expect(0).to.not.be.ok; // Not recommended + * + * expect(false).to.be.false; // Recommended + * expect(false).to.not.be.ok; // Not recommended + * + * expect(null).to.be.null; // Recommended + * expect(null).to.not.be.ok; // Not recommended + * + * expect(undefined).to.be.undefined; // Recommended + * expect(undefined).to.not.be.ok; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(false, 'nooo why fail??').to.be.ok; + * + * @name ok + * @namespace BDD + * @api public + */ - if (/^".*"$/.test(fileName)) { - fileName = fileName.substr(1, fileName.length - 2); - } + Assertion.addProperty('ok', function () { + this.assert( + flag(this, 'object') + , 'expected #{this} to be truthy' + , 'expected #{this} to be falsy'); + }); - index[keyPrefix + 'FileName'] = fileName; - index[keyPrefix + 'Header'] = (data[1] || '').trim(); - i++; - } - } // Parses a hunk - // This assumes that we are at the start of a hunk. + /** + * ### .true + * + * Asserts that the target is strictly (`===`) equal to `true`. + * + * expect(true).to.be.true; + * + * Add `.not` earlier in the chain to negate `.true`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `true`. + * + * expect(false).to.be.false; // Recommended + * expect(false).to.not.be.true; // Not recommended + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.true; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(false, 'nooo why fail??').to.be.true; + * + * @name true + * @namespace BDD + * @api public + */ + Assertion.addProperty('true', function () { + this.assert( + true === flag(this, 'object') + , 'expected #{this} to be true' + , 'expected #{this} to be false' + , flag(this, 'negate') ? false : true + ); + }); - function parseHunk() { - var chunkHeaderIndex = i, - chunkHeaderLine = diffstr[i++], - chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/); - var hunk = { - oldStart: +chunkHeader[1], - oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2], - newStart: +chunkHeader[3], - newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4], - lines: [], - linedelimiters: [] - }; // Unified Diff Format quirk: If the chunk size is 0, - // the first number is one lower than one would expect. - // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + /** + * ### .false + * + * Asserts that the target is strictly (`===`) equal to `false`. + * + * expect(false).to.be.false; + * + * Add `.not` earlier in the chain to negate `.false`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to `false`. + * + * expect(true).to.be.true; // Recommended + * expect(true).to.not.be.false; // Not recommended + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.false; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(true, 'nooo why fail??').to.be.false; + * + * @name false + * @namespace BDD + * @api public + */ - if (hunk.oldLines === 0) { - hunk.oldStart += 1; - } + Assertion.addProperty('false', function () { + this.assert( + false === flag(this, 'object') + , 'expected #{this} to be false' + , 'expected #{this} to be true' + , flag(this, 'negate') ? true : false + ); + }); - if (hunk.newLines === 0) { - hunk.newStart += 1; - } + /** + * ### .null + * + * Asserts that the target is strictly (`===`) equal to `null`. + * + * expect(null).to.be.null; + * + * Add `.not` earlier in the chain to negate `.null`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `null`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.null; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.null; + * + * @name null + * @namespace BDD + * @api public + */ + + Assertion.addProperty('null', function () { + this.assert( + null === flag(this, 'object') + , 'expected #{this} to be null' + , 'expected #{this} not to be null' + ); + }); + + /** + * ### .undefined + * + * Asserts that the target is strictly (`===`) equal to `undefined`. + * + * expect(undefined).to.be.undefined; + * + * Add `.not` earlier in the chain to negate `.undefined`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to `undefined`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.undefined; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.undefined; + * + * @name undefined + * @namespace BDD + * @api public + */ - var addCount = 0, - removeCount = 0; + Assertion.addProperty('undefined', function () { + this.assert( + undefined === flag(this, 'object') + , 'expected #{this} to be undefined' + , 'expected #{this} not to be undefined' + ); + }); - for (; i < diffstr.length; i++) { - // Lines starting with '---' could be mistaken for the "remove line" operation - // But they could be the header for the next file. Therefore prune such cases out. - if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) { - break; - } + /** + * ### .NaN + * + * Asserts that the target is exactly `NaN`. + * + * expect(NaN).to.be.NaN; + * + * Add `.not` earlier in the chain to negate `.NaN`. However, it's often best + * to assert that the target is equal to its expected value, rather than not + * equal to `NaN`. + * + * expect('foo').to.equal('foo'); // Recommended + * expect('foo').to.not.be.NaN; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(42, 'nooo why fail??').to.be.NaN; + * + * @name NaN + * @namespace BDD + * @api public + */ - var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0]; + Assertion.addProperty('NaN', function () { + this.assert( + _.isNaN(flag(this, 'object')) + , 'expected #{this} to be NaN' + , 'expected #{this} not to be NaN' + ); + }); - if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { - hunk.lines.push(diffstr[i]); - hunk.linedelimiters.push(delimiters[i] || '\n'); + /** + * ### .exist + * + * Asserts that the target is not strictly (`===`) equal to either `null` or + * `undefined`. However, it's often best to assert that the target is equal to + * its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.exist; // Not recommended + * + * expect(0).to.equal(0); // Recommended + * expect(0).to.exist; // Not recommended + * + * Add `.not` earlier in the chain to negate `.exist`. + * + * expect(null).to.be.null; // Recommended + * expect(null).to.not.exist; // Not recommended + * + * expect(undefined).to.be.undefined; // Recommended + * expect(undefined).to.not.exist; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(null, 'nooo why fail??').to.exist; + * + * The alias `.exists` can be used interchangeably with `.exist`. + * + * @name exist + * @alias exists + * @namespace BDD + * @api public + */ - if (operation === '+') { - addCount++; - } else if (operation === '-') { - removeCount++; - } else if (operation === ' ') { - addCount++; - removeCount++; - } - } else { - break; - } - } // Handle the empty block count case + function assertExist () { + var val = flag(this, 'object'); + this.assert( + val !== null && val !== undefined + , 'expected #{this} to exist' + , 'expected #{this} to not exist' + ); + } + Assertion.addProperty('exist', assertExist); + Assertion.addProperty('exists', assertExist); - if (!addCount && hunk.newLines === 1) { - hunk.newLines = 0; - } + /** + * ### .empty + * + * When the target is a string or array, `.empty` asserts that the target's + * `length` property is strictly (`===`) equal to `0`. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * + * When the target is a map or set, `.empty` asserts that the target's `size` + * property is strictly equal to `0`. + * + * expect(new Set()).to.be.empty; + * expect(new Map()).to.be.empty; + * + * When the target is a non-function object, `.empty` asserts that the target + * doesn't have any own enumerable properties. Properties with Symbol-based + * keys are excluded from the count. + * + * expect({}).to.be.empty; + * + * Because `.empty` does different things based on the target's type, it's + * important to check the target's type before using `.empty`. See the `.a` + * doc for info on testing a target's type. + * + * expect([]).to.be.an('array').that.is.empty; + * + * Add `.not` earlier in the chain to negate `.empty`. However, it's often + * best to assert that the target contains its expected number of values, + * rather than asserting that it's not empty. + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.not.be.empty; // Not recommended + * + * expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended + * expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended + * + * expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended + * expect({a: 1}).to.not.be.empty; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect([1, 2, 3], 'nooo why fail??').to.be.empty; + * + * @name empty + * @namespace BDD + * @api public + */ - if (!removeCount && hunk.oldLines === 1) { - hunk.oldLines = 0; - } // Perform optional sanity checking + Assertion.addProperty('empty', function () { + var val = flag(this, 'object') + , ssfi = flag(this, 'ssfi') + , flagMsg = flag(this, 'message') + , itemsCount; + flagMsg = flagMsg ? flagMsg + ': ' : ''; - if (options.strict) { - if (addCount !== hunk.newLines) { - throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); + switch (_.type(val).toLowerCase()) { + case 'array': + case 'string': + itemsCount = val.length; + break; + case 'map': + case 'set': + itemsCount = val.size; + break; + case 'weakmap': + case 'weakset': + throw new AssertionError( + flagMsg + '.empty was passed a weak collection', + undefined, + ssfi + ); + case 'function': + var msg = flagMsg + '.empty was passed a function ' + _.getName(val); + throw new AssertionError(msg.trim(), undefined, ssfi); + default: + if (val !== Object(val)) { + throw new AssertionError( + flagMsg + '.empty was passed non-string primitive ' + _.inspect(val), + undefined, + ssfi + ); } + itemsCount = Object.keys(val).length; + } - if (removeCount !== hunk.oldLines) { - throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); - } - } + this.assert( + 0 === itemsCount + , 'expected #{this} to be empty' + , 'expected #{this} not to be empty' + ); + }); - return hunk; - } + /** + * ### .arguments + * + * Asserts that the target is an `arguments` object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * test(); + * + * Add `.not` earlier in the chain to negate `.arguments`. However, it's often + * best to assert which type the target is expected to be, rather than + * asserting that it’s not an `arguments` object. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.arguments; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({}, 'nooo why fail??').to.be.arguments; + * + * The alias `.Arguments` can be used interchangeably with `.arguments`. + * + * @name arguments + * @alias Arguments + * @namespace BDD + * @api public + */ - while (i < diffstr.length) { - parseIndex(); - } + function checkArguments () { + var obj = flag(this, 'object') + , type = _.type(obj); + this.assert( + 'Arguments' === type + , 'expected #{this} to be arguments but got ' + type + , 'expected #{this} to not be arguments' + ); + } - return list; + Assertion.addProperty('arguments', checkArguments); + Assertion.addProperty('Arguments', checkArguments); + + /** + * ### .equal(val[, msg]) + * + * Asserts that the target is strictly (`===`) equal to the given `val`. + * + * expect(1).to.equal(1); + * expect('foo').to.equal('foo'); + * + * Add `.deep` earlier in the chain to use deep equality instead. See the + * `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) equals `{a: 1}` + * expect({a: 1}).to.deep.equal({a: 1}); + * expect({a: 1}).to.not.equal({a: 1}); + * + * // Target array deeply (but not strictly) equals `[1, 2]` + * expect([1, 2]).to.deep.equal([1, 2]); + * expect([1, 2]).to.not.equal([1, 2]); + * + * Add `.not` earlier in the chain to negate `.equal`. However, it's often + * best to assert that the target is equal to its expected value, rather than + * not equal to one of countless unexpected values. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.equal(2); // Not recommended + * + * `.equal` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.equal(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.equal(2); + * + * The aliases `.equals` and `eq` can be used interchangeably with `.equal`. + * + * @name equal + * @alias equals + * @alias eq + * @param {Mixed} val + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + + function assertEqual (val, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'deep')) { + var prevLockSsfi = flag(this, 'lockSsfi'); + flag(this, 'lockSsfi', true); + this.eql(val); + flag(this, 'lockSsfi', prevLockSsfi); + } else { + this.assert( + val === obj + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{exp}' + , val + , this._obj + , true + ); + } } - // Iterator that traverses in the range of [min, max], stepping - // by distance from a given start position. I.e. for [0, 4], with - // start of 2, this will iterate 2, 3, 1, 4, 0. - function distanceIterator (start, minLine, maxLine) { - var wantForward = true, - backwardExhausted = false, - forwardExhausted = false, - localOffset = 1; - return function iterator() { - if (wantForward && !forwardExhausted) { - if (backwardExhausted) { - localOffset++; - } else { - wantForward = false; - } // Check if trying to fit beyond text length, and if not, check it fits - // after offset location (or desired location on first iteration) + Assertion.addMethod('equal', assertEqual); + Assertion.addMethod('equals', assertEqual); + Assertion.addMethod('eq', assertEqual); + /** + * ### .eql(obj[, msg]) + * + * Asserts that the target is deeply equal to the given `obj`. See the + * `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target object is deeply (but not strictly) equal to {a: 1} + * expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1}); + * + * // Target array is deeply (but not strictly) equal to [1, 2] + * expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]); + * + * Add `.not` earlier in the chain to negate `.eql`. However, it's often best + * to assert that the target is deeply equal to its expected value, rather + * than not deeply equal to one of countless unexpected values. + * + * expect({a: 1}).to.eql({a: 1}); // Recommended + * expect({a: 1}).to.not.eql({b: 2}); // Not recommended + * + * `.eql` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect({a: 1}).to.eql({b: 2}, 'nooo why fail??'); + * expect({a: 1}, 'nooo why fail??').to.eql({b: 2}); + * + * The alias `.eqls` can be used interchangeably with `.eql`. + * + * The `.deep.equal` assertion is almost identical to `.eql` but with one + * difference: `.deep.equal` causes deep equality comparisons to also be used + * for any other assertions that follow in the chain. + * + * @name eql + * @alias eqls + * @param {Mixed} obj + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - if (start + localOffset <= maxLine) { - return localOffset; - } + function assertEql(obj, msg) { + if (msg) flag(this, 'message', msg); + this.assert( + _.eql(obj, flag(this, 'object')) + , 'expected #{this} to deeply equal #{exp}' + , 'expected #{this} to not deeply equal #{exp}' + , obj + , this._obj + , true + ); + } - forwardExhausted = true; - } + Assertion.addMethod('eql', assertEql); + Assertion.addMethod('eqls', assertEql); - if (!backwardExhausted) { - if (!forwardExhausted) { - wantForward = true; - } // Check if trying to fit before text beginning, and if not, check it fits - // before offset location + /** + * ### .above(n[, msg]) + * + * Asserts that the target is a number or a date greater than the given number or date `n` respectively. + * However, it's often best to assert that the target is equal to its expected + * value. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.be.above(1); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is greater than the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.above(2); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.above(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.above`. + * + * expect(2).to.equal(2); // Recommended + * expect(1).to.not.be.above(2); // Not recommended + * + * `.above` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.above(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.above(2); + * + * The aliases `.gt` and `.greaterThan` can be used interchangeably with + * `.above`. + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + function assertAbove (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , doLength = flag(this, 'doLength') + , flagMsg = flag(this, 'message') + , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') + , ssfi = flag(this, 'ssfi') + , objType = _.type(obj).toLowerCase() + , nType = _.type(n).toLowerCase() + , errorMessage + , shouldThrow = true; + + if (doLength && objType !== 'map' && objType !== 'set') { + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); + } - if (minLine <= start - localOffset) { - return -localOffset++; - } + if (!doLength && (objType === 'date' && nType !== 'date')) { + errorMessage = msgPrefix + 'the argument to above must be a date'; + } else if (nType !== 'number' && (doLength || objType === 'number')) { + errorMessage = msgPrefix + 'the argument to above must be a number'; + } else if (!doLength && (objType !== 'date' && objType !== 'number')) { + var printObj = (objType === 'string') ? "'" + obj + "'" : obj; + errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; + } else { + shouldThrow = false; + } - backwardExhausted = true; - return iterator(); - } // We tried to fit hunk before text beginning and beyond text length, then - // hunk can't fit on the text. Return undefined + if (shouldThrow) { + throw new AssertionError(errorMessage, undefined, ssfi); + } - }; + if (doLength) { + var descriptor = 'length' + , itemsCount; + if (objType === 'map' || objType === 'set') { + descriptor = 'size'; + itemsCount = obj.size; + } else { + itemsCount = obj.length; + } + this.assert( + itemsCount > n + , 'expected #{this} to have a ' + descriptor + ' above #{exp} but got #{act}' + , 'expected #{this} to not have a ' + descriptor + ' above #{exp}' + , n + , itemsCount + ); + } else { + this.assert( + obj > n + , 'expected #{this} to be above #{exp}' + , 'expected #{this} to be at most #{exp}' + , n + ); + } } - function applyPatch(source, uniDiff) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + Assertion.addMethod('above', assertAbove); + Assertion.addMethod('gt', assertAbove); + Assertion.addMethod('greaterThan', assertAbove); - if (typeof uniDiff === 'string') { - uniDiff = parsePatch(uniDiff); + /** + * ### .least(n[, msg]) + * + * Asserts that the target is a number or a date greater than or equal to the given + * number or date `n` respectively. However, it's often best to assert that the target is equal to + * its expected value. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.be.at.least(1); // Not recommended + * expect(2).to.be.at.least(2); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is greater than or equal to the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.at.least(2); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.at.least(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.least`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.at.least(2); // Not recommended + * + * `.least` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.at.least(2, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.at.least(2); + * + * The aliases `.gte` and `.greaterThanOrEqual` can be used interchangeably with + * `.least`. + * + * @name least + * @alias gte + * @alias greaterThanOrEqual + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + + function assertLeast (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , doLength = flag(this, 'doLength') + , flagMsg = flag(this, 'message') + , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') + , ssfi = flag(this, 'ssfi') + , objType = _.type(obj).toLowerCase() + , nType = _.type(n).toLowerCase() + , errorMessage + , shouldThrow = true; + + if (doLength && objType !== 'map' && objType !== 'set') { + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); } - if (Array.isArray(uniDiff)) { - if (uniDiff.length > 1) { - throw new Error('applyPatch only works with a single input.'); - } + if (!doLength && (objType === 'date' && nType !== 'date')) { + errorMessage = msgPrefix + 'the argument to least must be a date'; + } else if (nType !== 'number' && (doLength || objType === 'number')) { + errorMessage = msgPrefix + 'the argument to least must be a number'; + } else if (!doLength && (objType !== 'date' && objType !== 'number')) { + var printObj = (objType === 'string') ? "'" + obj + "'" : obj; + errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; + } else { + shouldThrow = false; + } - uniDiff = uniDiff[0]; - } // Apply the diff to the input + if (shouldThrow) { + throw new AssertionError(errorMessage, undefined, ssfi); + } + if (doLength) { + var descriptor = 'length' + , itemsCount; + if (objType === 'map' || objType === 'set') { + descriptor = 'size'; + itemsCount = obj.size; + } else { + itemsCount = obj.length; + } + this.assert( + itemsCount >= n + , 'expected #{this} to have a ' + descriptor + ' at least #{exp} but got #{act}' + , 'expected #{this} to have a ' + descriptor + ' below #{exp}' + , n + , itemsCount + ); + } else { + this.assert( + obj >= n + , 'expected #{this} to be at least #{exp}' + , 'expected #{this} to be below #{exp}' + , n + ); + } + } - var lines = source.split(/\r\n|[\n\v\f\r\x85]/), - delimiters = source.match(/\r\n|[\n\v\f\r\x85]/g) || [], - hunks = uniDiff.hunks, - compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) { - return line === patchContent; - }, - errorCount = 0, - fuzzFactor = options.fuzzFactor || 0, - minLine = 0, - offset = 0, - removeEOFNL, - addEOFNL; - /** - * Checks if the hunk exactly fits on the provided location - */ + Assertion.addMethod('least', assertLeast); + Assertion.addMethod('gte', assertLeast); + Assertion.addMethod('greaterThanOrEqual', assertLeast); + /** + * ### .below(n[, msg]) + * + * Asserts that the target is a number or a date less than the given number or date `n` respectively. + * However, it's often best to assert that the target is equal to its expected + * value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.below(2); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is less than the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.below(4); // Not recommended + * + * expect([1, 2, 3]).to.have.length(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.below(4); // Not recommended + * + * Add `.not` earlier in the chain to negate `.below`. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.not.be.below(1); // Not recommended + * + * `.below` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(2).to.be.below(1, 'nooo why fail??'); + * expect(2, 'nooo why fail??').to.be.below(1); + * + * The aliases `.lt` and `.lessThan` can be used interchangeably with + * `.below`. + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - function hunkFits(hunk, toPos) { - for (var j = 0; j < hunk.lines.length; j++) { - var line = hunk.lines[j], - operation = line.length > 0 ? line[0] : ' ', - content = line.length > 0 ? line.substr(1) : line; + function assertBelow (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , doLength = flag(this, 'doLength') + , flagMsg = flag(this, 'message') + , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') + , ssfi = flag(this, 'ssfi') + , objType = _.type(obj).toLowerCase() + , nType = _.type(n).toLowerCase() + , errorMessage + , shouldThrow = true; + + if (doLength && objType !== 'map' && objType !== 'set') { + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); + } - if (operation === ' ' || operation === '-') { - // Context sanity check - if (!compareLine(toPos + 1, lines[toPos], operation, content)) { - errorCount++; + if (!doLength && (objType === 'date' && nType !== 'date')) { + errorMessage = msgPrefix + 'the argument to below must be a date'; + } else if (nType !== 'number' && (doLength || objType === 'number')) { + errorMessage = msgPrefix + 'the argument to below must be a number'; + } else if (!doLength && (objType !== 'date' && objType !== 'number')) { + var printObj = (objType === 'string') ? "'" + obj + "'" : obj; + errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; + } else { + shouldThrow = false; + } - if (errorCount > fuzzFactor) { - return false; - } - } + if (shouldThrow) { + throw new AssertionError(errorMessage, undefined, ssfi); + } - toPos++; - } + if (doLength) { + var descriptor = 'length' + , itemsCount; + if (objType === 'map' || objType === 'set') { + descriptor = 'size'; + itemsCount = obj.size; + } else { + itemsCount = obj.length; } + this.assert( + itemsCount < n + , 'expected #{this} to have a ' + descriptor + ' below #{exp} but got #{act}' + , 'expected #{this} to not have a ' + descriptor + ' below #{exp}' + , n + , itemsCount + ); + } else { + this.assert( + obj < n + , 'expected #{this} to be below #{exp}' + , 'expected #{this} to be at least #{exp}' + , n + ); + } + } - return true; - } // Search best fit offsets for each hunk based on the previous ones + Assertion.addMethod('below', assertBelow); + Assertion.addMethod('lt', assertBelow); + Assertion.addMethod('lessThan', assertBelow); + /** + * ### .most(n[, msg]) + * + * Asserts that the target is a number or a date less than or equal to the given number + * or date `n` respectively. However, it's often best to assert that the target is equal to its + * expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.at.most(2); // Not recommended + * expect(1).to.be.at.most(1); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is less than or equal to the given number `n`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.at.most(4); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.at.most(4); // Not recommended + * + * Add `.not` earlier in the chain to negate `.most`. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.not.be.at.most(1); // Not recommended + * + * `.most` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(2).to.be.at.most(1, 'nooo why fail??'); + * expect(2, 'nooo why fail??').to.be.at.most(1); + * + * The aliases `.lte` and `.lessThanOrEqual` can be used interchangeably with + * `.most`. + * + * @name most + * @alias lte + * @alias lessThanOrEqual + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - for (var i = 0; i < hunks.length; i++) { - var hunk = hunks[i], - maxLine = lines.length - hunk.oldLines, - localOffset = 0, - toPos = offset + hunk.oldStart - 1; - var iterator = distanceIterator(toPos, minLine, maxLine); + function assertMost (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , doLength = flag(this, 'doLength') + , flagMsg = flag(this, 'message') + , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') + , ssfi = flag(this, 'ssfi') + , objType = _.type(obj).toLowerCase() + , nType = _.type(n).toLowerCase() + , errorMessage + , shouldThrow = true; + + if (doLength && objType !== 'map' && objType !== 'set') { + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); + } - for (; localOffset !== undefined; localOffset = iterator()) { - if (hunkFits(hunk, toPos + localOffset)) { - hunk.offset = offset += localOffset; - break; - } - } + if (!doLength && (objType === 'date' && nType !== 'date')) { + errorMessage = msgPrefix + 'the argument to most must be a date'; + } else if (nType !== 'number' && (doLength || objType === 'number')) { + errorMessage = msgPrefix + 'the argument to most must be a number'; + } else if (!doLength && (objType !== 'date' && objType !== 'number')) { + var printObj = (objType === 'string') ? "'" + obj + "'" : obj; + errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; + } else { + shouldThrow = false; + } - if (localOffset === undefined) { - return false; - } // Set lower text limit to end of the current hunk, so next ones don't try - // to fit over already patched text + if (shouldThrow) { + throw new AssertionError(errorMessage, undefined, ssfi); + } + if (doLength) { + var descriptor = 'length' + , itemsCount; + if (objType === 'map' || objType === 'set') { + descriptor = 'size'; + itemsCount = obj.size; + } else { + itemsCount = obj.length; + } + this.assert( + itemsCount <= n + , 'expected #{this} to have a ' + descriptor + ' at most #{exp} but got #{act}' + , 'expected #{this} to have a ' + descriptor + ' above #{exp}' + , n + , itemsCount + ); + } else { + this.assert( + obj <= n + , 'expected #{this} to be at most #{exp}' + , 'expected #{this} to be above #{exp}' + , n + ); + } + } - minLine = hunk.offset + hunk.oldStart + hunk.oldLines; - } // Apply patch hunks + Assertion.addMethod('most', assertMost); + Assertion.addMethod('lte', assertMost); + Assertion.addMethod('lessThanOrEqual', assertMost); + /** + * ### .within(start, finish[, msg]) + * + * Asserts that the target is a number or a date greater than or equal to the given + * number or date `start`, and less than or equal to the given number or date `finish` respectively. + * However, it's often best to assert that the target is equal to its expected + * value. + * + * expect(2).to.equal(2); // Recommended + * expect(2).to.be.within(1, 3); // Not recommended + * expect(2).to.be.within(2, 3); // Not recommended + * expect(2).to.be.within(1, 2); // Not recommended + * + * Add `.lengthOf` earlier in the chain to assert that the target's `length` + * or `size` is greater than or equal to the given number `start`, and less + * than or equal to the given number `finish`. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.have.lengthOf.within(2, 4); // Not recommended + * + * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended + * expect([1, 2, 3]).to.have.lengthOf.within(2, 4); // Not recommended + * + * Add `.not` earlier in the chain to negate `.within`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.within(2, 4); // Not recommended + * + * `.within` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(4).to.be.within(1, 3, 'nooo why fail??'); + * expect(4, 'nooo why fail??').to.be.within(1, 3); + * + * @name within + * @param {Number} start lower bound inclusive + * @param {Number} finish upper bound inclusive + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - var diffOffset = 0; + Assertion.addMethod('within', function (start, finish, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , doLength = flag(this, 'doLength') + , flagMsg = flag(this, 'message') + , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') + , ssfi = flag(this, 'ssfi') + , objType = _.type(obj).toLowerCase() + , startType = _.type(start).toLowerCase() + , finishType = _.type(finish).toLowerCase() + , errorMessage + , shouldThrow = true + , range = (startType === 'date' && finishType === 'date') + ? start.toISOString() + '..' + finish.toISOString() + : start + '..' + finish; + + if (doLength && objType !== 'map' && objType !== 'set') { + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); + } - for (var _i = 0; _i < hunks.length; _i++) { - var _hunk = hunks[_i], - _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1; + if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) { + errorMessage = msgPrefix + 'the arguments to within must be dates'; + } else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) { + errorMessage = msgPrefix + 'the arguments to within must be numbers'; + } else if (!doLength && (objType !== 'date' && objType !== 'number')) { + var printObj = (objType === 'string') ? "'" + obj + "'" : obj; + errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; + } else { + shouldThrow = false; + } - diffOffset += _hunk.newLines - _hunk.oldLines; + if (shouldThrow) { + throw new AssertionError(errorMessage, undefined, ssfi); + } - for (var j = 0; j < _hunk.lines.length; j++) { - var line = _hunk.lines[j], - operation = line.length > 0 ? line[0] : ' ', - content = line.length > 0 ? line.substr(1) : line, - delimiter = _hunk.linedelimiters[j]; + if (doLength) { + var descriptor = 'length' + , itemsCount; + if (objType === 'map' || objType === 'set') { + descriptor = 'size'; + itemsCount = obj.size; + } else { + itemsCount = obj.length; + } + this.assert( + itemsCount >= start && itemsCount <= finish + , 'expected #{this} to have a ' + descriptor + ' within ' + range + , 'expected #{this} to not have a ' + descriptor + ' within ' + range + ); + } else { + this.assert( + obj >= start && obj <= finish + , 'expected #{this} to be within ' + range + , 'expected #{this} to not be within ' + range + ); + } + }); - if (operation === ' ') { - _toPos++; - } else if (operation === '-') { - lines.splice(_toPos, 1); - delimiters.splice(_toPos, 1); - /* istanbul ignore else */ - } else if (operation === '+') { - lines.splice(_toPos, 0, content); - delimiters.splice(_toPos, 0, delimiter); - _toPos++; - } else if (operation === '\\') { - var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; + /** + * ### .instanceof(constructor[, msg]) + * + * Asserts that the target is an instance of the given `constructor`. + * + * function Cat () { } + * + * expect(new Cat()).to.be.an.instanceof(Cat); + * expect([1, 2]).to.be.an.instanceof(Array); + * + * Add `.not` earlier in the chain to negate `.instanceof`. + * + * expect({a: 1}).to.not.be.an.instanceof(Array); + * + * `.instanceof` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1).to.be.an.instanceof(Array, 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.an.instanceof(Array); + * + * Due to limitations in ES5, `.instanceof` may not always work as expected + * when using a transpiler such as Babel or TypeScript. In particular, it may + * produce unexpected results when subclassing built-in object such as + * `Array`, `Error`, and `Map`. See your transpiler's docs for details: + * + * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes)) + * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work)) + * + * The alias `.instanceOf` can be used interchangeably with `.instanceof`. + * + * @name instanceof + * @param {Constructor} constructor + * @param {String} msg _optional_ + * @alias instanceOf + * @namespace BDD + * @api public + */ - if (previousOperation === '+') { - removeEOFNL = true; - } else if (previousOperation === '-') { - addEOFNL = true; - } - } - } - } // Handle EOFNL insertion/removal + function assertInstanceOf (constructor, msg) { + if (msg) flag(this, 'message', msg); + var target = flag(this, 'object'); + var ssfi = flag(this, 'ssfi'); + var flagMsg = flag(this, 'message'); - if (removeEOFNL) { - while (!lines[lines.length - 1]) { - lines.pop(); - delimiters.pop(); + try { + var isInstanceOf = target instanceof constructor; + } catch (err) { + if (err instanceof TypeError) { + flagMsg = flagMsg ? flagMsg + ': ' : ''; + throw new AssertionError( + flagMsg + 'The instanceof assertion needs a constructor but ' + + _.type(constructor) + ' was given.', + undefined, + ssfi + ); } - } else if (addEOFNL) { - lines.push(''); - delimiters.push('\n'); - } - - for (var _k = 0; _k < lines.length - 1; _k++) { - lines[_k] = lines[_k] + delimiters[_k]; + throw err; } - return lines.join(''); - } // Wrapper that supports multiple file patches via callbacks. - - function applyPatches(uniDiff, options) { - if (typeof uniDiff === 'string') { - uniDiff = parsePatch(uniDiff); + var name = _.getName(constructor); + if (name === null) { + name = 'an unnamed constructor'; } - var currentIndex = 0; + this.assert( + isInstanceOf + , 'expected #{this} to be an instance of ' + name + , 'expected #{this} to not be an instance of ' + name + ); + } + Assertion.addMethod('instanceof', assertInstanceOf); + Assertion.addMethod('instanceOf', assertInstanceOf); - function processIndex() { - var index = uniDiff[currentIndex++]; + /** + * ### .property(name[, val[, msg]]) + * + * Asserts that the target has a property with the given key `name`. + * + * expect({a: 1}).to.have.property('a'); + * + * When `val` is provided, `.property` also asserts that the property's value + * is equal to the given `val`. + * + * expect({a: 1}).to.have.property('a', 1); + * + * By default, strict (`===`) equality is used. Add `.deep` earlier in the + * chain to use deep equality instead. See the `deep-eql` project page for + * info on the deep equality algorithm: https://github.com/chaijs/deep-eql. + * + * // Target object deeply (but not strictly) has property `x: {a: 1}` + * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); + * expect({x: {a: 1}}).to.not.have.property('x', {a: 1}); + * + * The target's enumerable and non-enumerable properties are always included + * in the search. By default, both own and inherited properties are included. + * Add `.own` earlier in the chain to exclude inherited properties from the + * search. + * + * Object.prototype.b = 2; + * + * expect({a: 1}).to.have.own.property('a'); + * expect({a: 1}).to.have.own.property('a', 1); + * expect({a: 1}).to.have.property('b'); + * expect({a: 1}).to.not.have.own.property('b'); + * + * `.deep` and `.own` can be combined. + * + * expect({x: {a: 1}}).to.have.deep.own.property('x', {a: 1}); + * + * Add `.nested` earlier in the chain to enable dot- and bracket-notation when + * referencing nested properties. + * + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]'); + * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]', 'y'); + * + * If `.` or `[]` are part of an actual property name, they can be escaped by + * adding two backslashes before them. + * + * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]'); + * + * `.deep` and `.nested` can be combined. + * + * expect({a: {b: [{c: 3}]}}) + * .to.have.deep.nested.property('a.b[0]', {c: 3}); + * + * `.own` and `.nested` cannot be combined. + * + * Add `.not` earlier in the chain to negate `.property`. + * + * expect({a: 1}).to.not.have.property('b'); + * + * However, it's dangerous to negate `.property` when providing `val`. The + * problem is that it creates uncertain expectations by asserting that the + * target either doesn't have a property with the given key `name`, or that it + * does have a property with the given key `name` but its value isn't equal to + * the given `val`. It's often best to identify the exact output that's + * expected, and then write an assertion that only accepts that exact output. + * + * When the target isn't expected to have a property with the given key + * `name`, it's often best to assert exactly that. + * + * expect({b: 2}).to.not.have.property('a'); // Recommended + * expect({b: 2}).to.not.have.property('a', 1); // Not recommended + * + * When the target is expected to have a property with the given key `name`, + * it's often best to assert that the property has its expected value, rather + * than asserting that it doesn't have one of many unexpected values. + * + * expect({a: 3}).to.have.property('a', 3); // Recommended + * expect({a: 3}).to.not.have.property('a', 1); // Not recommended + * + * `.property` changes the target of any assertions that follow in the chain + * to be the value of the property from the original target object. + * + * expect({a: 1}).to.have.property('a').that.is.a('number'); + * + * `.property` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing `val`, only use the + * second form. + * + * // Recommended + * expect({a: 1}).to.have.property('a', 2, 'nooo why fail??'); + * expect({a: 1}, 'nooo why fail??').to.have.property('a', 2); + * expect({a: 1}, 'nooo why fail??').to.have.property('b'); + * + * // Not recommended + * expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??'); + * + * The above assertion isn't the same thing as not providing `val`. Instead, + * it's asserting that the target object has a `b` property that's equal to + * `undefined`. + * + * The assertions `.ownProperty` and `.haveOwnProperty` can be used + * interchangeably with `.own.property`. + * + * @name property + * @param {String} name + * @param {Mixed} val (optional) + * @param {String} msg _optional_ + * @returns value of property for chaining + * @namespace BDD + * @api public + */ - if (!index) { - return options.complete(); - } + function assertProperty (name, val, msg) { + if (msg) flag(this, 'message', msg); - options.loadFile(index, function (err, data) { - if (err) { - return options.complete(err); - } + var isNested = flag(this, 'nested') + , isOwn = flag(this, 'own') + , flagMsg = flag(this, 'message') + , obj = flag(this, 'object') + , ssfi = flag(this, 'ssfi') + , nameType = typeof name; - var updatedContent = applyPatch(data, index, options); - options.patched(index, updatedContent, function (err) { - if (err) { - return options.complete(err); - } + flagMsg = flagMsg ? flagMsg + ': ' : ''; - processIndex(); - }); - }); + if (isNested) { + if (nameType !== 'string') { + throw new AssertionError( + flagMsg + 'the argument to property must be a string when using nested syntax', + undefined, + ssfi + ); + } + } else { + if (nameType !== 'string' && nameType !== 'number' && nameType !== 'symbol') { + throw new AssertionError( + flagMsg + 'the argument to property must be a string, number, or symbol', + undefined, + ssfi + ); + } } - processIndex(); - } - - function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { - if (!options) { - options = {}; + if (isNested && isOwn) { + throw new AssertionError( + flagMsg + 'The "nested" and "own" flags cannot be combined.', + undefined, + ssfi + ); } - if (typeof options.context === 'undefined') { - options.context = 4; + if (obj === null || obj === undefined) { + throw new AssertionError( + flagMsg + 'Target cannot be null or undefined.', + undefined, + ssfi + ); } - var diff = diffLines(oldStr, newStr, options); + var isDeep = flag(this, 'deep') + , negate = flag(this, 'negate') + , pathInfo = isNested ? _.getPathInfo(obj, name) : null + , value = isNested ? pathInfo.value : obj[name]; + + var descriptor = ''; + if (isDeep) descriptor += 'deep '; + if (isOwn) descriptor += 'own '; + if (isNested) descriptor += 'nested '; + descriptor += 'property '; + + var hasProperty; + if (isOwn) hasProperty = Object.prototype.hasOwnProperty.call(obj, name); + else if (isNested) hasProperty = pathInfo.exists; + else hasProperty = _.hasProperty(obj, name); + + // When performing a negated assertion for both name and val, merely having + // a property with the given name isn't enough to cause the assertion to + // fail. It must both have a property with the given name, and the value of + // that property must equal the given val. Therefore, skip this assertion in + // favor of the next. + if (!negate || arguments.length === 1) { + this.assert( + hasProperty + , 'expected #{this} to have ' + descriptor + _.inspect(name) + , 'expected #{this} to not have ' + descriptor + _.inspect(name)); + } - if (!diff) { - return; + if (arguments.length > 1) { + this.assert( + hasProperty && (isDeep ? _.eql(val, value) : val === value) + , 'expected #{this} to have ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' + , 'expected #{this} to not have ' + descriptor + _.inspect(name) + ' of #{act}' + , val + , value + ); } - diff.push({ - value: '', - lines: [] - }); // Append an empty value to make cleanup easier + flag(this, 'object', value); + } - function contextLines(lines) { - return lines.map(function (entry) { - return ' ' + entry; - }); - } + Assertion.addMethod('property', assertProperty); - var hunks = []; - var oldRangeStart = 0, - newRangeStart = 0, - curRange = [], - oldLine = 1, - newLine = 1; + function assertOwnProperty (name, value, msg) { + flag(this, 'own', true); + assertProperty.apply(this, arguments); + } - var _loop = function _loop(i) { - var current = diff[i], - lines = current.lines || current.value.replace(/\n$/, '').split('\n'); - current.lines = lines; + Assertion.addMethod('ownProperty', assertOwnProperty); + Assertion.addMethod('haveOwnProperty', assertOwnProperty); - if (current.added || current.removed) { - var _curRange; + /** + * ### .ownPropertyDescriptor(name[, descriptor[, msg]]) + * + * Asserts that the target has its own property descriptor with the given key + * `name`. Enumerable and non-enumerable properties are included in the + * search. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a'); + * + * When `descriptor` is provided, `.ownPropertyDescriptor` also asserts that + * the property's descriptor is deeply equal to the given `descriptor`. See + * the `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`. + * + * expect({a: 1}).to.not.have.ownPropertyDescriptor('b'); + * + * However, it's dangerous to negate `.ownPropertyDescriptor` when providing + * a `descriptor`. The problem is that it creates uncertain expectations by + * asserting that the target either doesn't have a property descriptor with + * the given key `name`, or that it does have a property descriptor with the + * given key `name` but it’s not deeply equal to the given `descriptor`. It's + * often best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to have a property descriptor with the given + * key `name`, it's often best to assert exactly that. + * + * // Recommended + * expect({b: 2}).to.not.have.ownPropertyDescriptor('a'); + * + * // Not recommended + * expect({b: 2}).to.not.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * When the target is expected to have a property descriptor with the given + * key `name`, it's often best to assert that the property has its expected + * descriptor, rather than asserting that it doesn't have one of many + * unexpected descriptors. + * + * // Recommended + * expect({a: 3}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 3, + * }); + * + * // Not recommended + * expect({a: 3}).to.not.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 1, + * }); + * + * `.ownPropertyDescriptor` changes the target of any assertions that follow + * in the chain to be the value of the property descriptor from the original + * target object. + * + * expect({a: 1}).to.have.ownPropertyDescriptor('a') + * .that.has.property('enumerable', true); + * + * `.ownPropertyDescriptor` accepts an optional `msg` argument which is a + * custom error message to show when the assertion fails. The message can also + * be given as the second argument to `expect`. When not providing + * `descriptor`, only use the second form. + * + * // Recommended + * expect({a: 1}).to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 2, + * }, 'nooo why fail??'); + * + * // Recommended + * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', { + * configurable: true, + * enumerable: true, + * writable: true, + * value: 2, + * }); + * + * // Recommended + * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b'); + * + * // Not recommended + * expect({a: 1}) + * .to.have.ownPropertyDescriptor('b', undefined, 'nooo why fail??'); + * + * The above assertion isn't the same thing as not providing `descriptor`. + * Instead, it's asserting that the target object has a `b` property + * descriptor that's deeply equal to `undefined`. + * + * The alias `.haveOwnPropertyDescriptor` can be used interchangeably with + * `.ownPropertyDescriptor`. + * + * @name ownPropertyDescriptor + * @alias haveOwnPropertyDescriptor + * @param {String} name + * @param {Object} descriptor _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - // If we have previous context, start with that - if (!oldRangeStart) { - var prev = diff[i - 1]; - oldRangeStart = oldLine; - newRangeStart = newLine; + function assertOwnPropertyDescriptor (name, descriptor, msg) { + if (typeof descriptor === 'string') { + msg = descriptor; + descriptor = null; + } + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name); + if (actualDescriptor && descriptor) { + this.assert( + _.eql(descriptor, actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor) + , descriptor + , actualDescriptor + , true + ); + } else { + this.assert( + actualDescriptor + , 'expected #{this} to have an own property descriptor for ' + _.inspect(name) + , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name) + ); + } + flag(this, 'object', actualDescriptor); + } - if (prev) { - curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; - oldRangeStart -= curRange.length; - newRangeStart -= curRange.length; - } - } // Output our changes + Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor); + Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor); + /** + * ### .lengthOf(n[, msg]) + * + * Asserts that the target's `length` or `size` is equal to the given number + * `n`. + * + * expect([1, 2, 3]).to.have.lengthOf(3); + * expect('foo').to.have.lengthOf(3); + * expect(new Set([1, 2, 3])).to.have.lengthOf(3); + * expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3); + * + * Add `.not` earlier in the chain to negate `.lengthOf`. However, it's often + * best to assert that the target's `length` property is equal to its expected + * value, rather than not equal to one of many unexpected values. + * + * expect('foo').to.have.lengthOf(3); // Recommended + * expect('foo').to.not.have.lengthOf(4); // Not recommended + * + * `.lengthOf` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2, 3]).to.have.lengthOf(2, 'nooo why fail??'); + * expect([1, 2, 3], 'nooo why fail??').to.have.lengthOf(2); + * + * `.lengthOf` can also be used as a language chain, causing all `.above`, + * `.below`, `.least`, `.most`, and `.within` assertions that follow in the + * chain to use the target's `length` property as the target. However, it's + * often best to assert that the target's `length` property is equal to its + * expected length, rather than asserting that its `length` property falls + * within some range of values. + * + * // Recommended + * expect([1, 2, 3]).to.have.lengthOf(3); + * + * // Not recommended + * expect([1, 2, 3]).to.have.lengthOf.above(2); + * expect([1, 2, 3]).to.have.lengthOf.below(4); + * expect([1, 2, 3]).to.have.lengthOf.at.least(3); + * expect([1, 2, 3]).to.have.lengthOf.at.most(3); + * expect([1, 2, 3]).to.have.lengthOf.within(2,4); + * + * Due to a compatibility issue, the alias `.length` can't be chained directly + * off of an uninvoked method such as `.a`. Therefore, `.length` can't be used + * interchangeably with `.lengthOf` in every situation. It's recommended to + * always use `.lengthOf` instead of `.length`. + * + * expect([1, 2, 3]).to.have.a.length(3); // incompatible; throws error + * expect([1, 2, 3]).to.have.a.lengthOf(3); // passes as expected + * + * @name lengthOf + * @alias length + * @param {Number} n + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) { - return (current.added ? '+' : '-') + entry; - }))); // Track the updated file position + function assertLengthChain () { + flag(this, 'doLength', true); + } + function assertLength (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , objType = _.type(obj).toLowerCase() + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi') + , descriptor = 'length' + , itemsCount; + + switch (objType) { + case 'map': + case 'set': + descriptor = 'size'; + itemsCount = obj.size; + break; + default: + new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); + itemsCount = obj.length; + } - if (current.added) { - newLine += lines.length; - } else { - oldLine += lines.length; - } - } else { - // Identical context lines. Track line changes - if (oldRangeStart) { - // Close out any changes that have been output (or join overlapping) - if (lines.length <= options.context * 2 && i < diff.length - 2) { - var _curRange2; + this.assert( + itemsCount == n + , 'expected #{this} to have a ' + descriptor + ' of #{exp} but got #{act}' + , 'expected #{this} to not have a ' + descriptor + ' of #{act}' + , n + , itemsCount + ); + } - // Overlapping - (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines))); - } else { - var _curRange3; + Assertion.addChainableMethod('length', assertLength, assertLengthChain); + Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain); - // end the range and output - var contextSize = Math.min(lines.length, options.context); + /** + * ### .match(re[, msg]) + * + * Asserts that the target matches the given regular expression `re`. + * + * expect('foobar').to.match(/^foo/); + * + * Add `.not` earlier in the chain to negate `.match`. + * + * expect('foobar').to.not.match(/taco/); + * + * `.match` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect('foobar').to.match(/taco/, 'nooo why fail??'); + * expect('foobar', 'nooo why fail??').to.match(/taco/); + * + * The alias `.matches` can be used interchangeably with `.match`. + * + * @name match + * @alias matches + * @param {RegExp} re + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + function assertMatch(re, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + re.exec(obj) + , 'expected #{this} to match ' + re + , 'expected #{this} not to match ' + re + ); + } - (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize)))); + Assertion.addMethod('match', assertMatch); + Assertion.addMethod('matches', assertMatch); - var hunk = { - oldStart: oldRangeStart, - oldLines: oldLine - oldRangeStart + contextSize, - newStart: newRangeStart, - newLines: newLine - newRangeStart + contextSize, - lines: curRange - }; + /** + * ### .string(str[, msg]) + * + * Asserts that the target string contains the given substring `str`. + * + * expect('foobar').to.have.string('bar'); + * + * Add `.not` earlier in the chain to negate `.string`. + * + * expect('foobar').to.not.have.string('taco'); + * + * `.string` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect('foobar').to.have.string('taco', 'nooo why fail??'); + * expect('foobar', 'nooo why fail??').to.have.string('taco'); + * + * @name string + * @param {String} str + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - if (i >= diff.length - 2 && lines.length <= options.context) { - // EOF is inside this hunk - var oldEOFNewline = /\n$/.test(oldStr); - var newEOFNewline = /\n$/.test(newStr); - var noNlBeforeAdds = lines.length == 0 && curRange.length > hunk.oldLines; + Assertion.addMethod('string', function (str, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); + new Assertion(obj, flagMsg, ssfi, true).is.a('string'); + + this.assert( + ~obj.indexOf(str) + , 'expected #{this} to contain ' + _.inspect(str) + , 'expected #{this} to not contain ' + _.inspect(str) + ); + }); - if (!oldEOFNewline && noNlBeforeAdds && oldStr.length > 0) { - // special case: old has no eol and no trailing context; no-nl can end up before adds - // however, if the old file is empty, do not output the no-nl line - curRange.splice(hunk.oldLines, 0, '\\ No newline at end of file'); - } + /** + * ### .keys(key1[, key2[, ...]]) + * + * Asserts that the target object, array, map, or set has the given keys. Only + * the target's own inherited properties are included in the search. + * + * When the target is an object or array, keys can be provided as one or more + * string arguments, a single array argument, or a single object argument. In + * the latter case, only the keys in the given object matter; the values are + * ignored. + * + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * expect(['x', 'y']).to.have.all.keys(0, 1); + * + * expect({a: 1, b: 2}).to.have.all.keys(['a', 'b']); + * expect(['x', 'y']).to.have.all.keys([0, 1]); + * + * expect({a: 1, b: 2}).to.have.all.keys({a: 4, b: 5}); // ignore 4 and 5 + * expect(['x', 'y']).to.have.all.keys({0: 4, 1: 5}); // ignore 4 and 5 + * + * When the target is a map or set, each key must be provided as a separate + * argument. + * + * expect(new Map([['a', 1], ['b', 2]])).to.have.all.keys('a', 'b'); + * expect(new Set(['a', 'b'])).to.have.all.keys('a', 'b'); + * + * Because `.keys` does different things based on the target's type, it's + * important to check the target's type before using `.keys`. See the `.a` doc + * for info on testing a target's type. + * + * expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b'); + * + * By default, strict (`===`) equality is used to compare keys of maps and + * sets. Add `.deep` earlier in the chain to use deep equality instead. See + * the `deep-eql` project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target set deeply (but not strictly) has key `{a: 1}` + * expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]); + * expect(new Set([{a: 1}])).to.not.have.all.keys([{a: 1}]); + * + * By default, the target must have all of the given keys and no more. Add + * `.any` earlier in the chain to only require that the target have at least + * one of the given keys. Also, add `.not` earlier in the chain to negate + * `.keys`. It's often best to add `.any` when negating `.keys`, and to use + * `.all` when asserting `.keys` without negation. + * + * When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts + * exactly what's expected of the output, whereas `.not.all.keys` creates + * uncertain expectations. + * + * // Recommended; asserts that target doesn't have any of the given keys + * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd'); + * + * // Not recommended; asserts that target doesn't have all of the given + * // keys but may or may not have some of them + * expect({a: 1, b: 2}).to.not.have.all.keys('c', 'd'); + * + * When asserting `.keys` without negation, `.all` is preferred because + * `.all.keys` asserts exactly what's expected of the output, whereas + * `.any.keys` creates uncertain expectations. + * + * // Recommended; asserts that target has all the given keys + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); + * + * // Not recommended; asserts that target has at least one of the given + * // keys but may or may not have more of them + * expect({a: 1, b: 2}).to.have.any.keys('a', 'b'); + * + * Note that `.all` is used by default when neither `.all` nor `.any` appear + * earlier in the chain. However, it's often best to add `.all` anyway because + * it improves readability. + * + * // Both assertions are identical + * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); // Recommended + * expect({a: 1, b: 2}).to.have.keys('a', 'b'); // Not recommended + * + * Add `.include` earlier in the chain to require that the target's keys be a + * superset of the expected keys, rather than identical sets. + * + * // Target object's keys are a superset of ['a', 'b'] but not identical + * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b'); + * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b'); + * + * However, if `.any` and `.include` are combined, only the `.any` takes + * effect. The `.include` is ignored in this case. + * + * // Both assertions are identical + * expect({a: 1}).to.have.any.keys('a', 'b'); + * expect({a: 1}).to.include.any.keys('a', 'b'); + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.have.key('b'); + * + * The alias `.key` can be used interchangeably with `.keys`. + * + * @name keys + * @alias key + * @param {...String|Array|Object} keys + * @namespace BDD + * @api public + */ - if (!oldEOFNewline && !noNlBeforeAdds || !newEOFNewline) { - curRange.push('\\ No newline at end of file'); - } - } + function assertKeys (keys) { + var obj = flag(this, 'object') + , objType = _.type(obj) + , keysType = _.type(keys) + , ssfi = flag(this, 'ssfi') + , isDeep = flag(this, 'deep') + , str + , deepStr = '' + , actual + , ok = true + , flagMsg = flag(this, 'message'); + + flagMsg = flagMsg ? flagMsg + ': ' : ''; + var mixedArgsMsg = flagMsg + 'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments'; + + if (objType === 'Map' || objType === 'Set') { + deepStr = isDeep ? 'deeply ' : ''; + actual = []; + + // Map and Set '.keys' aren't supported in IE 11. Therefore, use .forEach. + obj.forEach(function (val, key) { actual.push(key); }); + + if (keysType !== 'Array') { + keys = Array.prototype.slice.call(arguments); + } + } else { + actual = _.getOwnEnumerableProperties(obj); - hunks.push(hunk); - oldRangeStart = 0; - newRangeStart = 0; - curRange = []; + switch (keysType) { + case 'Array': + if (arguments.length > 1) { + throw new AssertionError(mixedArgsMsg, undefined, ssfi); } - } - - oldLine += lines.length; - newLine += lines.length; + break; + case 'Object': + if (arguments.length > 1) { + throw new AssertionError(mixedArgsMsg, undefined, ssfi); + } + keys = Object.keys(keys); + break; + default: + keys = Array.prototype.slice.call(arguments); } - }; - for (var i = 0; i < diff.length; i++) { - _loop(i); + // Only stringify non-Symbols because Symbols would become "Symbol()" + keys = keys.map(function (val) { + return typeof val === 'symbol' ? val : String(val); + }); } - return { - oldFileName: oldFileName, - newFileName: newFileName, - oldHeader: oldHeader, - newHeader: newHeader, - hunks: hunks - }; - } - function formatPatch(diff) { - var ret = []; + if (!keys.length) { + throw new AssertionError(flagMsg + 'keys required', undefined, ssfi); + } - if (diff.oldFileName == diff.newFileName) { - ret.push('Index: ' + diff.oldFileName); + var len = keys.length + , any = flag(this, 'any') + , all = flag(this, 'all') + , expected = keys; + + if (!any && !all) { + all = true; } - ret.push('==================================================================='); - ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); - ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); + // Has any + if (any) { + ok = expected.some(function(expectedKey) { + return actual.some(function(actualKey) { + if (isDeep) { + return _.eql(expectedKey, actualKey); + } else { + return expectedKey === actualKey; + } + }); + }); + } - for (var i = 0; i < diff.hunks.length; i++) { - var hunk = diff.hunks[i]; // Unified Diff Format quirk: If the chunk size is 0, - // the first number is one lower than one would expect. - // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 + // Has all + if (all) { + ok = expected.every(function(expectedKey) { + return actual.some(function(actualKey) { + if (isDeep) { + return _.eql(expectedKey, actualKey); + } else { + return expectedKey === actualKey; + } + }); + }); - if (hunk.oldLines === 0) { - hunk.oldStart -= 1; + if (!flag(this, 'contains')) { + ok = ok && keys.length == actual.length; } + } - if (hunk.newLines === 0) { - hunk.newStart -= 1; + // Key string + if (len > 1) { + keys = keys.map(function(key) { + return _.inspect(key); + }); + var last = keys.pop(); + if (all) { + str = keys.join(', ') + ', and ' + last; } - - ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@'); - ret.push.apply(ret, hunk.lines); + if (any) { + str = keys.join(', ') + ', or ' + last; + } + } else { + str = _.inspect(keys[0]); } - return ret.join('\n') + '\n'; - } - function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { - return formatPatch(structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)); - } - function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { - return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; + + // Assertion + this.assert( + ok + , 'expected #{this} to ' + deepStr + str + , 'expected #{this} to not ' + deepStr + str + , expected.slice(0).sort(_.compareByInspect) + , actual.sort(_.compareByInspect) + , true + ); } - function arrayEqual(a, b) { - if (a.length !== b.length) { - return false; + Assertion.addMethod('keys', assertKeys); + Assertion.addMethod('key', assertKeys); + + /** + * ### .throw([errorLike], [errMsgMatcher], [msg]) + * + * When no arguments are provided, `.throw` invokes the target function and + * asserts that an error is thrown. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(); + * + * When one argument is provided, and it's an error constructor, `.throw` + * invokes the target function and asserts that an error is thrown that's an + * instance of that error constructor. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(TypeError); + * + * When one argument is provided, and it's an error instance, `.throw` invokes + * the target function and asserts that an error is thrown that's strictly + * (`===`) equal to that error instance. + * + * var err = new TypeError('Illegal salmon!'); + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(err); + * + * When one argument is provided, and it's a string, `.throw` invokes the + * target function and asserts that an error is thrown with a message that + * contains that string. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw('salmon'); + * + * When one argument is provided, and it's a regular expression, `.throw` + * invokes the target function and asserts that an error is thrown with a + * message that matches that regular expression. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(/salmon/); + * + * When two arguments are provided, and the first is an error instance or + * constructor, and the second is a string or regular expression, `.throw` + * invokes the function and asserts that an error is thrown that fulfills both + * conditions as described above. + * + * var err = new TypeError('Illegal salmon!'); + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(TypeError, 'salmon'); + * expect(badFn).to.throw(TypeError, /salmon/); + * expect(badFn).to.throw(err, 'salmon'); + * expect(badFn).to.throw(err, /salmon/); + * + * Add `.not` earlier in the chain to negate `.throw`. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.not.throw(); + * + * However, it's dangerous to negate `.throw` when providing any arguments. + * The problem is that it creates uncertain expectations by asserting that the + * target either doesn't throw an error, or that it throws an error but of a + * different type than the given type, or that it throws an error of the given + * type but with a message that doesn't include the given string. It's often + * best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to throw an error, it's often best to assert + * exactly that. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.not.throw(); // Recommended + * expect(goodFn).to.not.throw(ReferenceError, 'x'); // Not recommended + * + * When the target is expected to throw an error, it's often best to assert + * that the error is of its expected type, and has a message that includes an + * expected string, rather than asserting that it doesn't have one of many + * unexpected types, and doesn't have a message that includes some string. + * + * var badFn = function () { throw new TypeError('Illegal salmon!'); }; + * + * expect(badFn).to.throw(TypeError, 'salmon'); // Recommended + * expect(badFn).to.not.throw(ReferenceError, 'x'); // Not recommended + * + * `.throw` changes the target of any assertions that follow in the chain to + * be the error object that's thrown. + * + * var err = new TypeError('Illegal salmon!'); + * err.code = 42; + * var badFn = function () { throw err; }; + * + * expect(badFn).to.throw(TypeError).with.property('code', 42); + * + * `.throw` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. When not providing two arguments, always use + * the second form. + * + * var goodFn = function () {}; + * + * expect(goodFn).to.throw(TypeError, 'x', 'nooo why fail??'); + * expect(goodFn, 'nooo why fail??').to.throw(); + * + * Due to limitations in ES5, `.throw` may not always work as expected when + * using a transpiler such as Babel or TypeScript. In particular, it may + * produce unexpected results when subclassing the built-in `Error` object and + * then passing the subclassed constructor to `.throw`. See your transpiler's + * docs for details: + * + * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes)) + * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work)) + * + * Beware of some common mistakes when using the `throw` assertion. One common + * mistake is to accidentally invoke the function yourself instead of letting + * the `throw` assertion invoke the function for you. For example, when + * testing if a function named `fn` throws, provide `fn` instead of `fn()` as + * the target for the assertion. + * + * expect(fn).to.throw(); // Good! Tests `fn` as desired + * expect(fn()).to.throw(); // Bad! Tests result of `fn()`, not `fn` + * + * If you need to assert that your function `fn` throws when passed certain + * arguments, then wrap a call to `fn` inside of another function. + * + * expect(function () { fn(42); }).to.throw(); // Function expression + * expect(() => fn(42)).to.throw(); // ES6 arrow function + * + * Another common mistake is to provide an object method (or any stand-alone + * function that relies on `this`) as the target of the assertion. Doing so is + * problematic because the `this` context will be lost when the function is + * invoked by `.throw`; there's no way for it to know what `this` is supposed + * to be. There are two ways around this problem. One solution is to wrap the + * method or function call inside of another function. Another solution is to + * use `bind`. + * + * expect(function () { cat.meow(); }).to.throw(); // Function expression + * expect(() => cat.meow()).to.throw(); // ES6 arrow function + * expect(cat.meow.bind(cat)).to.throw(); // Bind + * + * Finally, it's worth mentioning that it's a best practice in JavaScript to + * only throw `Error` and derivatives of `Error` such as `ReferenceError`, + * `TypeError`, and user-defined objects that extend `Error`. No other type of + * value will generate a stack trace when initialized. With that said, the + * `throw` assertion does technically support any type of value being thrown, + * not just `Error` and its derivatives. + * + * The aliases `.throws` and `.Throw` can be used interchangeably with + * `.throw`. + * + * @name throw + * @alias throws + * @alias Throw + * @param {Error|ErrorConstructor} errorLike + * @param {String|RegExp} errMsgMatcher error message + * @param {String} msg _optional_ + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @returns error for chaining (null if no error) + * @namespace BDD + * @api public + */ + + function assertThrows (errorLike, errMsgMatcher, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , ssfi = flag(this, 'ssfi') + , flagMsg = flag(this, 'message') + , negate = flag(this, 'negate') || false; + new Assertion(obj, flagMsg, ssfi, true).is.a('function'); + + if (errorLike instanceof RegExp || typeof errorLike === 'string') { + errMsgMatcher = errorLike; + errorLike = null; } - return arrayStartsWith(a, b); - } - function arrayStartsWith(array, start) { - if (start.length > array.length) { - return false; + var caughtErr; + try { + obj(); + } catch (err) { + caughtErr = err; } - for (var i = 0; i < start.length; i++) { - if (start[i] !== array[i]) { - return false; + // If we have the negate flag enabled and at least one valid argument it means we do expect an error + // but we want it to match a given set of criteria + var everyArgIsUndefined = errorLike === undefined && errMsgMatcher === undefined; + + // If we've got the negate flag enabled and both args, we should only fail if both aren't compatible + // See Issue #551 and PR #683@GitHub + var everyArgIsDefined = Boolean(errorLike && errMsgMatcher); + var errorLikeFail = false; + var errMsgMatcherFail = false; + + // Checking if error was thrown + if (everyArgIsUndefined || !everyArgIsUndefined && !negate) { + // We need this to display results correctly according to their types + var errorLikeString = 'an error'; + if (errorLike instanceof Error) { + errorLikeString = '#{exp}'; + } else if (errorLike) { + errorLikeString = _.checkError.getConstructorName(errorLike); } - } - - return true; - } - - function calcLineCount(hunk) { - var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines), - oldLines = _calcOldNewLineCount.oldLines, - newLines = _calcOldNewLineCount.newLines; - - if (oldLines !== undefined) { - hunk.oldLines = oldLines; - } else { - delete hunk.oldLines; - } - if (newLines !== undefined) { - hunk.newLines = newLines; - } else { - delete hunk.newLines; + this.assert( + caughtErr + , 'expected #{this} to throw ' + errorLikeString + , 'expected #{this} to not throw an error but #{act} was thrown' + , errorLike && errorLike.toString() + , (caughtErr instanceof Error ? + caughtErr.toString() : (typeof caughtErr === 'string' ? caughtErr : caughtErr && + _.checkError.getConstructorName(caughtErr))) + ); } - } - function merge(mine, theirs, base) { - mine = loadPatch(mine, base); - theirs = loadPatch(theirs, base); - var ret = {}; // For index we just let it pass through as it doesn't have any necessary meaning. - // Leaving sanity checks on this to the API consumer that may know more about the - // meaning in their own context. - if (mine.index || theirs.index) { - ret.index = mine.index || theirs.index; - } + if (errorLike && caughtErr) { + // We should compare instances only if `errorLike` is an instance of `Error` + if (errorLike instanceof Error) { + var isCompatibleInstance = _.checkError.compatibleInstance(caughtErr, errorLike); - if (mine.newFileName || theirs.newFileName) { - if (!fileNameChanged(mine)) { - // No header or no change in ours, use theirs (and ours if theirs does not exist) - ret.oldFileName = theirs.oldFileName || mine.oldFileName; - ret.newFileName = theirs.newFileName || mine.newFileName; - ret.oldHeader = theirs.oldHeader || mine.oldHeader; - ret.newHeader = theirs.newHeader || mine.newHeader; - } else if (!fileNameChanged(theirs)) { - // No header or no change in theirs, use ours - ret.oldFileName = mine.oldFileName; - ret.newFileName = mine.newFileName; - ret.oldHeader = mine.oldHeader; - ret.newHeader = mine.newHeader; - } else { - // Both changed... figure it out - ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName); - ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName); - ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader); - ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader); + if (isCompatibleInstance === negate) { + // These checks were created to ensure we won't fail too soon when we've got both args and a negate + // See Issue #551 and PR #683@GitHub + if (everyArgIsDefined && negate) { + errorLikeFail = true; + } else { + this.assert( + negate + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp}' + (caughtErr && !negate ? ' but #{act} was thrown' : '') + , errorLike.toString() + , caughtErr.toString() + ); + } + } } - } - - ret.hunks = []; - var mineIndex = 0, - theirsIndex = 0, - mineOffset = 0, - theirsOffset = 0; - - while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) { - var mineCurrent = mine.hunks[mineIndex] || { - oldStart: Infinity - }, - theirsCurrent = theirs.hunks[theirsIndex] || { - oldStart: Infinity - }; - if (hunkBefore(mineCurrent, theirsCurrent)) { - // This patch does not overlap with any of the others, yay. - ret.hunks.push(cloneHunk(mineCurrent, mineOffset)); - mineIndex++; - theirsOffset += mineCurrent.newLines - mineCurrent.oldLines; - } else if (hunkBefore(theirsCurrent, mineCurrent)) { - // This patch does not overlap with any of the others, yay. - ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset)); - theirsIndex++; - mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines; - } else { - // Overlap, merge as best we can - var mergedHunk = { - oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart), - oldLines: 0, - newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset), - newLines: 0, - lines: [] - }; - mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines); - theirsIndex++; - mineIndex++; - ret.hunks.push(mergedHunk); + var isCompatibleConstructor = _.checkError.compatibleConstructor(caughtErr, errorLike); + if (isCompatibleConstructor === negate) { + if (everyArgIsDefined && negate) { + errorLikeFail = true; + } else { + this.assert( + negate + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '') + , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike)) + , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr)) + ); + } } } - return ret; - } - - function loadPatch(param, base) { - if (typeof param === 'string') { - if (/^@@/m.test(param) || /^Index:/m.test(param)) { - return parsePatch(param)[0]; + if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) { + // Here we check compatible messages + var placeholder = 'including'; + if (errMsgMatcher instanceof RegExp) { + placeholder = 'matching'; } - if (!base) { - throw new Error('Must provide a base reference or pass in a patch'); + var isCompatibleMessage = _.checkError.compatibleMessage(caughtErr, errMsgMatcher); + if (isCompatibleMessage === negate) { + if (everyArgIsDefined && negate) { + errMsgMatcherFail = true; + } else { + this.assert( + negate + , 'expected #{this} to throw error ' + placeholder + ' #{exp} but got #{act}' + , 'expected #{this} to throw error not ' + placeholder + ' #{exp}' + , errMsgMatcher + , _.checkError.getMessage(caughtErr) + ); + } } + } - return structuredPatch(undefined, undefined, base, param); + // If both assertions failed and both should've matched we throw an error + if (errorLikeFail && errMsgMatcherFail) { + this.assert( + negate + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '') + , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike)) + , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr)) + ); } - return param; + flag(this, 'object', caughtErr); } + Assertion.addMethod('throw', assertThrows); + Assertion.addMethod('throws', assertThrows); + Assertion.addMethod('Throw', assertThrows); - function fileNameChanged(patch) { - return patch.newFileName && patch.newFileName !== patch.oldFileName; - } + /** + * ### .respondTo(method[, msg]) + * + * When the target is a non-function object, `.respondTo` asserts that the + * target has a method with the given name `method`. The method can be own or + * inherited, and it can be enumerable or non-enumerable. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(new Cat()).to.respondTo('meow'); + * + * When the target is a function, `.respondTo` asserts that the target's + * `prototype` property has a method with the given name `method`. Again, the + * method can be own or inherited, and it can be enumerable or non-enumerable. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(Cat).to.respondTo('meow'); + * + * Add `.itself` earlier in the chain to force `.respondTo` to treat the + * target as a non-function object, even if it's a function. Thus, it asserts + * that the target has a method with the given name `method`, rather than + * asserting that the target's `prototype` property has a method with the + * given name `method`. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * Cat.hiss = function () {}; + * + * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow'); + * + * When not adding `.itself`, it's important to check the target's type before + * using `.respondTo`. See the `.a` doc for info on checking a target's type. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * + * expect(new Cat()).to.be.an('object').that.respondsTo('meow'); + * + * Add `.not` earlier in the chain to negate `.respondTo`. + * + * function Dog () {} + * Dog.prototype.bark = function () {}; + * + * expect(new Dog()).to.not.respondTo('meow'); + * + * `.respondTo` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect({}).to.respondTo('meow', 'nooo why fail??'); + * expect({}, 'nooo why fail??').to.respondTo('meow'); + * + * The alias `.respondsTo` can be used interchangeably with `.respondTo`. + * + * @name respondTo + * @alias respondsTo + * @param {String} method + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - function selectField(index, mine, theirs) { - if (mine === theirs) { - return mine; - } else { - index.conflict = true; - return { - mine: mine, - theirs: theirs - }; - } + function respondTo (method, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , itself = flag(this, 'itself') + , context = ('function' === typeof obj && !itself) + ? obj.prototype[method] + : obj[method]; + + this.assert( + 'function' === typeof context + , 'expected #{this} to respond to ' + _.inspect(method) + , 'expected #{this} to not respond to ' + _.inspect(method) + ); } - function hunkBefore(test, check) { - return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart; - } + Assertion.addMethod('respondTo', respondTo); + Assertion.addMethod('respondsTo', respondTo); - function cloneHunk(hunk, offset) { - return { - oldStart: hunk.oldStart, - oldLines: hunk.oldLines, - newStart: hunk.newStart + offset, - newLines: hunk.newLines, - lines: hunk.lines - }; + /** + * ### .itself + * + * Forces all `.respondTo` assertions that follow in the chain to behave as if + * the target is a non-function object, even if it's a function. Thus, it + * causes `.respondTo` to assert that the target has a method with the given + * name, rather than asserting that the target's `prototype` property has a + * method with the given name. + * + * function Cat () {} + * Cat.prototype.meow = function () {}; + * Cat.hiss = function () {}; + * + * expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow'); + * + * @name itself + * @namespace BDD + * @api public + */ + + Assertion.addProperty('itself', function () { + flag(this, 'itself', true); + }); + + /** + * ### .satisfy(matcher[, msg]) + * + * Invokes the given `matcher` function with the target being passed as the + * first argument, and asserts that the value returned is truthy. + * + * expect(1).to.satisfy(function(num) { + * return num > 0; + * }); + * + * Add `.not` earlier in the chain to negate `.satisfy`. + * + * expect(1).to.not.satisfy(function(num) { + * return num > 2; + * }); + * + * `.satisfy` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1).to.satisfy(function(num) { + * return num > 2; + * }, 'nooo why fail??'); + * + * expect(1, 'nooo why fail??').to.satisfy(function(num) { + * return num > 2; + * }); + * + * The alias `.satisfies` can be used interchangeably with `.satisfy`. + * + * @name satisfy + * @alias satisfies + * @param {Function} matcher + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + + function satisfy (matcher, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var result = matcher(obj); + this.assert( + result + , 'expected #{this} to satisfy ' + _.objDisplay(matcher) + , 'expected #{this} to not satisfy' + _.objDisplay(matcher) + , flag(this, 'negate') ? false : true + , result + ); } - function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) { - // This will generally result in a conflicted hunk, but there are cases where the context - // is the only overlap where we can successfully merge the content here. - var mine = { - offset: mineOffset, - lines: mineLines, - index: 0 - }, - their = { - offset: theirOffset, - lines: theirLines, - index: 0 - }; // Handle any leading content + Assertion.addMethod('satisfy', satisfy); + Assertion.addMethod('satisfies', satisfy); - insertLeading(hunk, mine, their); - insertLeading(hunk, their, mine); // Now in the overlap content. Scan through and select the best changes from each. + /** + * ### .closeTo(expected, delta[, msg]) + * + * Asserts that the target is a number that's within a given +/- `delta` range + * of the given number `expected`. However, it's often best to assert that the + * target is equal to its expected value. + * + * // Recommended + * expect(1.5).to.equal(1.5); + * + * // Not recommended + * expect(1.5).to.be.closeTo(1, 0.5); + * expect(1.5).to.be.closeTo(2, 0.5); + * expect(1.5).to.be.closeTo(1, 1); + * + * Add `.not` earlier in the chain to negate `.closeTo`. + * + * expect(1.5).to.equal(1.5); // Recommended + * expect(1.5).to.not.be.closeTo(3, 1); // Not recommended + * + * `.closeTo` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect(1.5).to.be.closeTo(3, 1, 'nooo why fail??'); + * expect(1.5, 'nooo why fail??').to.be.closeTo(3, 1); + * + * The alias `.approximately` can be used interchangeably with `.closeTo`. + * + * @name closeTo + * @alias approximately + * @param {Number} expected + * @param {Number} delta + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - while (mine.index < mine.lines.length && their.index < their.lines.length) { - var mineCurrent = mine.lines[mine.index], - theirCurrent = their.lines[their.index]; + function closeTo(expected, delta, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); + + new Assertion(obj, flagMsg, ssfi, true).is.a('number'); + if (typeof expected !== 'number' || typeof delta !== 'number') { + flagMsg = flagMsg ? flagMsg + ': ' : ''; + var deltaMessage = delta === undefined ? ", and a delta is required" : ""; + throw new AssertionError( + flagMsg + 'the arguments to closeTo or approximately must be numbers' + deltaMessage, + undefined, + ssfi + ); + } - if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) { - // Both modified ... - mutualChange(hunk, mine, their); - } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') { - var _hunk$lines; + this.assert( + Math.abs(obj - expected) <= delta + , 'expected #{this} to be close to ' + expected + ' +/- ' + delta + , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta + ); + } - // Mine inserted - (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine))); - } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') { - var _hunk$lines2; + Assertion.addMethod('closeTo', closeTo); + Assertion.addMethod('approximately', closeTo); - // Theirs inserted - (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their))); - } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') { - // Mine removed or edited - removal(hunk, mine, their); - } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') { - // Their removed or edited - removal(hunk, their, mine, true); - } else if (mineCurrent === theirCurrent) { - // Context identity - hunk.lines.push(mineCurrent); - mine.index++; - their.index++; - } else { - // Context mismatch - conflict(hunk, collectChange(mine), collectChange(their)); - } - } // Now push anything that may be remaining + // Note: Duplicates are ignored if testing for inclusion instead of sameness. + function isSubsetOf(subset, superset, cmp, contains, ordered) { + if (!contains) { + if (subset.length !== superset.length) return false; + superset = superset.slice(); + } + return subset.every(function(elem, idx) { + if (ordered) return cmp ? cmp(elem, superset[idx]) : elem === superset[idx]; - insertTrailing(hunk, mine); - insertTrailing(hunk, their); - calcLineCount(hunk); - } + if (!cmp) { + var matchIdx = superset.indexOf(elem); + if (matchIdx === -1) return false; - function mutualChange(hunk, mine, their) { - var myChanges = collectChange(mine), - theirChanges = collectChange(their); + // Remove match from superset so not counted twice if duplicate in subset. + if (!contains) superset.splice(matchIdx, 1); + return true; + } - if (allRemoves(myChanges) && allRemoves(theirChanges)) { - // Special case for remove changes that are supersets of one another - if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) { - var _hunk$lines3; + return superset.some(function(elem2, matchIdx) { + if (!cmp(elem, elem2)) return false; - (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges)); + // Remove match from superset so not counted twice if duplicate in subset. + if (!contains) superset.splice(matchIdx, 1); + return true; + }); + }); + } - return; - } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) { - var _hunk$lines4; + /** + * ### .members(set[, msg]) + * + * Asserts that the target array has the same members as the given array + * `set`. + * + * expect([1, 2, 3]).to.have.members([2, 1, 3]); + * expect([1, 2, 2]).to.have.members([2, 1, 2]); + * + * By default, members are compared using strict (`===`) equality. Add `.deep` + * earlier in the chain to use deep equality instead. See the `deep-eql` + * project page for info on the deep equality algorithm: + * https://github.com/chaijs/deep-eql. + * + * // Target array deeply (but not strictly) has member `{a: 1}` + * expect([{a: 1}]).to.have.deep.members([{a: 1}]); + * expect([{a: 1}]).to.not.have.members([{a: 1}]); + * + * By default, order doesn't matter. Add `.ordered` earlier in the chain to + * require that members appear in the same order. + * + * expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]); + * expect([1, 2, 3]).to.have.members([2, 1, 3]) + * .but.not.ordered.members([2, 1, 3]); + * + * By default, both arrays must be the same size. Add `.include` earlier in + * the chain to require that the target's members be a superset of the + * expected members. Note that duplicates are ignored in the subset when + * `.include` is added. + * + * // Target array is a superset of [1, 2] but not identical + * expect([1, 2, 3]).to.include.members([1, 2]); + * expect([1, 2, 3]).to.not.have.members([1, 2]); + * + * // Duplicates in the subset are ignored + * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]); + * + * `.deep`, `.ordered`, and `.include` can all be combined. However, if + * `.include` and `.ordered` are combined, the ordering begins at the start of + * both arrays. + * + * expect([{a: 1}, {b: 2}, {c: 3}]) + * .to.include.deep.ordered.members([{a: 1}, {b: 2}]) + * .but.not.include.deep.ordered.members([{b: 2}, {c: 3}]); + * + * Add `.not` earlier in the chain to negate `.members`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the target array doesn't have all of the same members as + * the given array `set` but may or may not have some of them. It's often best + * to identify the exact output that's expected, and then write an assertion + * that only accepts that exact output. + * + * expect([1, 2]).to.not.include(3).and.not.include(4); // Recommended + * expect([1, 2]).to.not.have.members([3, 4]); // Not recommended + * + * `.members` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. + * + * expect([1, 2]).to.have.members([1, 2, 3], 'nooo why fail??'); + * expect([1, 2], 'nooo why fail??').to.have.members([1, 2, 3]); + * + * @name members + * @param {Array} set + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges)); + Assertion.addMethod('members', function (subset, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); - return; - } - } else if (arrayEqual(myChanges, theirChanges)) { - var _hunk$lines5; + new Assertion(obj, flagMsg, ssfi, true).to.be.an('array'); + new Assertion(subset, flagMsg, ssfi, true).to.be.an('array'); - (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges)); + var contains = flag(this, 'contains'); + var ordered = flag(this, 'ordered'); - return; + var subject, failMsg, failNegateMsg; + + if (contains) { + subject = ordered ? 'an ordered superset' : 'a superset'; + failMsg = 'expected #{this} to be ' + subject + ' of #{exp}'; + failNegateMsg = 'expected #{this} to not be ' + subject + ' of #{exp}'; + } else { + subject = ordered ? 'ordered members' : 'members'; + failMsg = 'expected #{this} to have the same ' + subject + ' as #{exp}'; + failNegateMsg = 'expected #{this} to not have the same ' + subject + ' as #{exp}'; } - conflict(hunk, myChanges, theirChanges); - } + var cmp = flag(this, 'deep') ? _.eql : undefined; - function removal(hunk, mine, their, swap) { - var myChanges = collectChange(mine), - theirChanges = collectContext(their, myChanges); + this.assert( + isSubsetOf(subset, obj, cmp, contains, ordered) + , failMsg + , failNegateMsg + , subset + , obj + , true + ); + }); - if (theirChanges.merged) { - var _hunk$lines6; + /** + * ### .oneOf(list[, msg]) + * + * Asserts that the target is a member of the given array `list`. However, + * it's often best to assert that the target is equal to its expected value. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.be.oneOf([1, 2, 3]); // Not recommended + * + * Comparisons are performed using strict (`===`) equality. + * + * Add `.not` earlier in the chain to negate `.oneOf`. + * + * expect(1).to.equal(1); // Recommended + * expect(1).to.not.be.oneOf([2, 3, 4]); // Not recommended + * + * It can also be chained with `.contain` or `.include`, which will work with + * both arrays and strings: + * + * expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy']) + * expect('Today is rainy').to.not.contain.oneOf(['sunny', 'cloudy']) + * expect([1,2,3]).to.contain.oneOf([3,4,5]) + * expect([1,2,3]).to.not.contain.oneOf([4,5,6]) + * + * `.oneOf` accepts an optional `msg` argument which is a custom error message + * to show when the assertion fails. The message can also be given as the + * second argument to `expect`. + * + * expect(1).to.be.oneOf([2, 3, 4], 'nooo why fail??'); + * expect(1, 'nooo why fail??').to.be.oneOf([2, 3, 4]); + * + * @name oneOf + * @param {Array<*>} list + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged)); + function oneOf (list, msg) { + if (msg) flag(this, 'message', msg); + var expected = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi') + , contains = flag(this, 'contains') + , isDeep = flag(this, 'deep'); + new Assertion(list, flagMsg, ssfi, true).to.be.an('array'); + + if (contains) { + this.assert( + list.some(function(possibility) { return expected.indexOf(possibility) > -1 }) + , 'expected #{this} to contain one of #{exp}' + , 'expected #{this} to not contain one of #{exp}' + , list + , expected + ); } else { - conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges); + if (isDeep) { + this.assert( + list.some(function(possibility) { return _.eql(expected, possibility) }) + , 'expected #{this} to deeply equal one of #{exp}' + , 'expected #{this} to deeply equal one of #{exp}' + , list + , expected + ); + } else { + this.assert( + list.indexOf(expected) > -1 + , 'expected #{this} to be one of #{exp}' + , 'expected #{this} to not be one of #{exp}' + , list + , expected + ); + } } } - function conflict(hunk, mine, their) { - hunk.conflict = true; - hunk.lines.push({ - conflict: true, - mine: mine, - theirs: their - }); - } + Assertion.addMethod('oneOf', oneOf); - function insertLeading(hunk, insert, their) { - while (insert.offset < their.offset && insert.index < insert.lines.length) { - var line = insert.lines[insert.index++]; - hunk.lines.push(line); - insert.offset++; - } - } + /** + * ### .change(subject[, prop[, msg]]) + * + * When one argument is provided, `.change` asserts that the given function + * `subject` returns a different value when it's invoked before the target + * function compared to when it's invoked afterward. However, it's often best + * to assert that `subject` is equal to its expected value. + * + * var dots = '' + * , addDot = function () { dots += '.'; } + * , getDots = function () { return dots; }; + * + * // Recommended + * expect(getDots()).to.equal(''); + * addDot(); + * expect(getDots()).to.equal('.'); + * + * // Not recommended + * expect(addDot).to.change(getDots); + * + * When two arguments are provided, `.change` asserts that the value of the + * given object `subject`'s `prop` property is different before invoking the + * target function compared to afterward. + * + * var myObj = {dots: ''} + * , addDot = function () { myObj.dots += '.'; }; + * + * // Recommended + * expect(myObj).to.have.property('dots', ''); + * addDot(); + * expect(myObj).to.have.property('dots', '.'); + * + * // Not recommended + * expect(addDot).to.change(myObj, 'dots'); + * + * Strict (`===`) equality is used to compare before and after values. + * + * Add `.not` earlier in the chain to negate `.change`. + * + * var dots = '' + * , noop = function () {} + * , getDots = function () { return dots; }; + * + * expect(noop).to.not.change(getDots); + * + * var myObj = {dots: ''} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'dots'); + * + * `.change` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {dots: ''} + * , addDot = function () { myObj.dots += '.'; }; + * + * expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??'); + * + * var dots = '' + * , addDot = function () { dots += '.'; } + * , getDots = function () { return dots; }; + * + * expect(addDot, 'nooo why fail??').to.not.change(getDots); + * + * `.change` also causes all `.by` assertions that follow in the chain to + * assert how much a numeric subject was increased or decreased by. However, + * it's dangerous to use `.change.by`. The problem is that it creates + * uncertain expectations by asserting that the subject either increases by + * the given delta, or that it decreases by the given delta. It's often best + * to identify the exact output that's expected, and then write an assertion + * that only accepts that exact output. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; } + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * The alias `.changes` can be used interchangeably with `.change`. + * + * @name change + * @alias changes + * @param {String} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - function insertTrailing(hunk, insert) { - while (insert.index < insert.lines.length) { - var line = insert.lines[insert.index++]; - hunk.lines.push(line); + function assertChanges (subject, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); + new Assertion(fn, flagMsg, ssfi, true).is.a('function'); + + var initial; + if (!prop) { + new Assertion(subject, flagMsg, ssfi, true).is.a('function'); + initial = subject(); + } else { + new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop); + initial = subject[prop]; } - } - function collectChange(state) { - var ret = [], - operation = state.lines[state.index][0]; + fn(); - while (state.index < state.lines.length) { - var line = state.lines[state.index]; // Group additions that are immediately after subtractions and treat them as one "atomic" modify change. + var final = prop === undefined || prop === null ? subject() : subject[prop]; + var msgObj = prop === undefined || prop === null ? initial : '.' + prop; - if (operation === '-' && line[0] === '+') { - operation = '+'; - } + // This gets flagged because of the .by(delta) assertion + flag(this, 'deltaMsgObj', msgObj); + flag(this, 'initialDeltaValue', initial); + flag(this, 'finalDeltaValue', final); + flag(this, 'deltaBehavior', 'change'); + flag(this, 'realDelta', final !== initial); - if (operation === line[0]) { - ret.push(line); - state.index++; - } else { - break; - } + this.assert( + initial !== final + , 'expected ' + msgObj + ' to change' + , 'expected ' + msgObj + ' to not change' + ); + } + + Assertion.addMethod('change', assertChanges); + Assertion.addMethod('changes', assertChanges); + + /** + * ### .increase(subject[, prop[, msg]]) + * + * When one argument is provided, `.increase` asserts that the given function + * `subject` returns a greater number when it's invoked after invoking the + * target function compared to when it's invoked beforehand. `.increase` also + * causes all `.by` assertions that follow in the chain to assert how much + * greater of a number is returned. It's often best to assert that the return + * value increased by the expected amount, rather than asserting it increased + * by any amount. + * + * var val = 1 + * , addTwo = function () { val += 2; } + * , getVal = function () { return val; }; + * + * expect(addTwo).to.increase(getVal).by(2); // Recommended + * expect(addTwo).to.increase(getVal); // Not recommended + * + * When two arguments are provided, `.increase` asserts that the value of the + * given object `subject`'s `prop` property is greater after invoking the + * target function compared to beforehand. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.increase(myObj, 'val'); // Not recommended + * + * Add `.not` earlier in the chain to negate `.increase`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either decreases, or that it stays the same. + * It's often best to identify the exact output that's expected, and then + * write an assertion that only accepts that exact output. + * + * When the subject is expected to decrease, it's often best to assert that it + * decreased by the expected amount. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended + * + * When the subject is expected to stay the same, it's often best to assert + * exactly that. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'val'); // Recommended + * expect(noop).to.not.increase(myObj, 'val'); // Not recommended + * + * `.increase` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.increase(myObj, 'val', 'nooo why fail??'); + * + * var val = 1 + * , noop = function () {} + * , getVal = function () { return val; }; + * + * expect(noop, 'nooo why fail??').to.increase(getVal); + * + * The alias `.increases` can be used interchangeably with `.increase`. + * + * @name increase + * @alias increases + * @param {String|Function} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + + function assertIncreases (subject, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); + new Assertion(fn, flagMsg, ssfi, true).is.a('function'); + + var initial; + if (!prop) { + new Assertion(subject, flagMsg, ssfi, true).is.a('function'); + initial = subject(); + } else { + new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop); + initial = subject[prop]; } - return ret; - } + // Make sure that the target is a number + new Assertion(initial, flagMsg, ssfi, true).is.a('number'); - function collectContext(state, matchChanges) { - var changes = [], - merged = [], - matchIndex = 0, - contextChanges = false, - conflicted = false; + fn(); - while (matchIndex < matchChanges.length && state.index < state.lines.length) { - var change = state.lines[state.index], - match = matchChanges[matchIndex]; // Once we've hit our add, then we are done + var final = prop === undefined || prop === null ? subject() : subject[prop]; + var msgObj = prop === undefined || prop === null ? initial : '.' + prop; - if (match[0] === '+') { - break; - } + flag(this, 'deltaMsgObj', msgObj); + flag(this, 'initialDeltaValue', initial); + flag(this, 'finalDeltaValue', final); + flag(this, 'deltaBehavior', 'increase'); + flag(this, 'realDelta', final - initial); - contextChanges = contextChanges || change[0] !== ' '; - merged.push(match); - matchIndex++; // Consume any additions in the other block as a conflict to attempt - // to pull in the remaining context after this + this.assert( + final - initial > 0 + , 'expected ' + msgObj + ' to increase' + , 'expected ' + msgObj + ' to not increase' + ); + } - if (change[0] === '+') { - conflicted = true; + Assertion.addMethod('increase', assertIncreases); + Assertion.addMethod('increases', assertIncreases); - while (change[0] === '+') { - changes.push(change); - change = state.lines[++state.index]; - } - } + /** + * ### .decrease(subject[, prop[, msg]]) + * + * When one argument is provided, `.decrease` asserts that the given function + * `subject` returns a lesser number when it's invoked after invoking the + * target function compared to when it's invoked beforehand. `.decrease` also + * causes all `.by` assertions that follow in the chain to assert how much + * lesser of a number is returned. It's often best to assert that the return + * value decreased by the expected amount, rather than asserting it decreased + * by any amount. + * + * var val = 1 + * , subtractTwo = function () { val -= 2; } + * , getVal = function () { return val; }; + * + * expect(subtractTwo).to.decrease(getVal).by(2); // Recommended + * expect(subtractTwo).to.decrease(getVal); // Not recommended + * + * When two arguments are provided, `.decrease` asserts that the value of the + * given object `subject`'s `prop` property is lesser after invoking the + * target function compared to beforehand. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.decrease(myObj, 'val'); // Not recommended + * + * Add `.not` earlier in the chain to negate `.decrease`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either increases, or that it stays the same. + * It's often best to identify the exact output that's expected, and then + * write an assertion that only accepts that exact output. + * + * When the subject is expected to increase, it's often best to assert that it + * increased by the expected amount. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.not.decrease(myObj, 'val'); // Not recommended + * + * When the subject is expected to stay the same, it's often best to assert + * exactly that. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.not.change(myObj, 'val'); // Recommended + * expect(noop).to.not.decrease(myObj, 'val'); // Not recommended + * + * `.decrease` accepts an optional `msg` argument which is a custom error + * message to show when the assertion fails. The message can also be given as + * the second argument to `expect`. When not providing two arguments, always + * use the second form. + * + * var myObj = {val: 1} + * , noop = function () {}; + * + * expect(noop).to.decrease(myObj, 'val', 'nooo why fail??'); + * + * var val = 1 + * , noop = function () {} + * , getVal = function () { return val; }; + * + * expect(noop, 'nooo why fail??').to.decrease(getVal); + * + * The alias `.decreases` can be used interchangeably with `.decrease`. + * + * @name decrease + * @alias decreases + * @param {String|Function} subject + * @param {String} prop name _optional_ + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ - if (match.substr(1) === change.substr(1)) { - changes.push(change); - state.index++; - } else { - conflicted = true; - } + function assertDecreases (subject, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object') + , flagMsg = flag(this, 'message') + , ssfi = flag(this, 'ssfi'); + new Assertion(fn, flagMsg, ssfi, true).is.a('function'); + + var initial; + if (!prop) { + new Assertion(subject, flagMsg, ssfi, true).is.a('function'); + initial = subject(); + } else { + new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop); + initial = subject[prop]; } - if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) { - conflicted = true; - } + // Make sure that the target is a number + new Assertion(initial, flagMsg, ssfi, true).is.a('number'); - if (conflicted) { - return changes; - } + fn(); - while (matchIndex < matchChanges.length) { - merged.push(matchChanges[matchIndex++]); - } + var final = prop === undefined || prop === null ? subject() : subject[prop]; + var msgObj = prop === undefined || prop === null ? initial : '.' + prop; - return { - merged: merged, - changes: changes - }; - } + flag(this, 'deltaMsgObj', msgObj); + flag(this, 'initialDeltaValue', initial); + flag(this, 'finalDeltaValue', final); + flag(this, 'deltaBehavior', 'decrease'); + flag(this, 'realDelta', initial - final); - function allRemoves(changes) { - return changes.reduce(function (prev, change) { - return prev && change[0] === '-'; - }, true); + this.assert( + final - initial < 0 + , 'expected ' + msgObj + ' to decrease' + , 'expected ' + msgObj + ' to not decrease' + ); } - function skipRemoveSuperset(state, removeChanges, delta) { - for (var i = 0; i < delta; i++) { - var changeContent = removeChanges[removeChanges.length - delta + i].substr(1); + Assertion.addMethod('decrease', assertDecreases); + Assertion.addMethod('decreases', assertDecreases); + + /** + * ### .by(delta[, msg]) + * + * When following an `.increase` assertion in the chain, `.by` asserts that + * the subject of the `.increase` assertion increased by the given `delta`. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); + * + * When following a `.decrease` assertion in the chain, `.by` asserts that the + * subject of the `.decrease` assertion decreased by the given `delta`. + * + * var myObj = {val: 1} + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); + * + * When following a `.change` assertion in the chain, `.by` asserts that the + * subject of the `.change` assertion either increased or decreased by the + * given `delta`. However, it's dangerous to use `.change.by`. The problem is + * that it creates uncertain expectations. It's often best to identify the + * exact output that's expected, and then write an assertion that only accepts + * that exact output. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; } + * , subtractTwo = function () { myObj.val -= 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended + * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended + * expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended + * + * Add `.not` earlier in the chain to negate `.by`. However, it's often best + * to assert that the subject changed by its expected delta, rather than + * asserting that it didn't change by one of countless unexpected deltas. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * // Recommended + * expect(addTwo).to.increase(myObj, 'val').by(2); + * + * // Not recommended + * expect(addTwo).to.increase(myObj, 'val').but.not.by(3); + * + * `.by` accepts an optional `msg` argument which is a custom error message to + * show when the assertion fails. The message can also be given as the second + * argument to `expect`. + * + * var myObj = {val: 1} + * , addTwo = function () { myObj.val += 2; }; + * + * expect(addTwo).to.increase(myObj, 'val').by(3, 'nooo why fail??'); + * expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3); + * + * @name by + * @param {Number} delta + * @param {String} msg _optional_ + * @namespace BDD + * @api public + */ + + function assertDelta(delta, msg) { + if (msg) flag(this, 'message', msg); - if (state.lines[state.index + i] !== ' ' + changeContent) { - return false; - } + var msgObj = flag(this, 'deltaMsgObj'); + var initial = flag(this, 'initialDeltaValue'); + var final = flag(this, 'finalDeltaValue'); + var behavior = flag(this, 'deltaBehavior'); + var realDelta = flag(this, 'realDelta'); + + var expression; + if (behavior === 'change') { + expression = Math.abs(final - initial) === Math.abs(delta); + } else { + expression = realDelta === Math.abs(delta); } - state.index += delta; - return true; + this.assert( + expression + , 'expected ' + msgObj + ' to ' + behavior + ' by ' + delta + , 'expected ' + msgObj + ' to not ' + behavior + ' by ' + delta + ); } - function calcOldNewLineCount(lines) { - var oldLines = 0; - var newLines = 0; - lines.forEach(function (line) { - if (typeof line !== 'string') { - var myCount = calcOldNewLineCount(line.mine); - var theirCount = calcOldNewLineCount(line.theirs); + Assertion.addMethod('by', assertDelta); - if (oldLines !== undefined) { - if (myCount.oldLines === theirCount.oldLines) { - oldLines += myCount.oldLines; - } else { - oldLines = undefined; - } - } + /** + * ### .extensible + * + * Asserts that the target is extensible, which means that new properties can + * be added to it. Primitives are never extensible. + * + * expect({a: 1}).to.be.extensible; + * + * Add `.not` earlier in the chain to negate `.extensible`. + * + * var nonExtensibleObject = Object.preventExtensions({}) + * , sealedObject = Object.seal({}) + * , frozenObject = Object.freeze({}); + * + * expect(nonExtensibleObject).to.not.be.extensible; + * expect(sealedObject).to.not.be.extensible; + * expect(frozenObject).to.not.be.extensible; + * expect(1).to.not.be.extensible; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect(1, 'nooo why fail??').to.be.extensible; + * + * @name extensible + * @namespace BDD + * @api public + */ - if (newLines !== undefined) { - if (myCount.newLines === theirCount.newLines) { - newLines += myCount.newLines; - } else { - newLines = undefined; - } - } - } else { - if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) { - newLines++; - } + Assertion.addProperty('extensible', function() { + var obj = flag(this, 'object'); - if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) { - oldLines++; - } - } - }); - return { - oldLines: oldLines, - newLines: newLines - }; - } + // In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible + // The following provides ES6 behavior for ES5 environments. - // See: http://code.google.com/p/google-diff-match-patch/wiki/API - function convertChangesToDMP(changes) { - var ret = [], - change, - operation; + var isExtensible = obj === Object(obj) && Object.isExtensible(obj); - for (var i = 0; i < changes.length; i++) { - change = changes[i]; + this.assert( + isExtensible + , 'expected #{this} to be extensible' + , 'expected #{this} to not be extensible' + ); + }); - if (change.added) { - operation = 1; - } else if (change.removed) { - operation = -1; - } else { - operation = 0; - } + /** + * ### .sealed + * + * Asserts that the target is sealed, which means that new properties can't be + * added to it, and its existing properties can't be reconfigured or deleted. + * However, it's possible that its existing properties can still be reassigned + * to different values. Primitives are always sealed. + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * expect(sealedObject).to.be.sealed; + * expect(frozenObject).to.be.sealed; + * expect(1).to.be.sealed; + * + * Add `.not` earlier in the chain to negate `.sealed`. + * + * expect({a: 1}).to.not.be.sealed; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.be.sealed; + * + * @name sealed + * @namespace BDD + * @api public + */ - ret.push([operation, change.value]); - } + Assertion.addProperty('sealed', function() { + var obj = flag(this, 'object'); - return ret; - } + // In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed + // The following provides ES6 behavior for ES5 environments. - function convertChangesToXML(changes) { - var ret = []; + var isSealed = obj === Object(obj) ? Object.isSealed(obj) : true; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; + this.assert( + isSealed + , 'expected #{this} to be sealed' + , 'expected #{this} to not be sealed' + ); + }); - if (change.added) { - ret.push(''); - } else if (change.removed) { - ret.push(''); - } + /** + * ### .frozen + * + * Asserts that the target is frozen, which means that new properties can't be + * added to it, and its existing properties can't be reassigned to different + * values, reconfigured, or deleted. Primitives are always frozen. + * + * var frozenObject = Object.freeze({}); + * + * expect(frozenObject).to.be.frozen; + * expect(1).to.be.frozen; + * + * Add `.not` earlier in the chain to negate `.frozen`. + * + * expect({a: 1}).to.not.be.frozen; + * + * A custom error message can be given as the second argument to `expect`. + * + * expect({a: 1}, 'nooo why fail??').to.be.frozen; + * + * @name frozen + * @namespace BDD + * @api public + */ - ret.push(escapeHTML(change.value)); + Assertion.addProperty('frozen', function() { + var obj = flag(this, 'object'); - if (change.added) { - ret.push(''); - } else if (change.removed) { - ret.push(''); - } - } + // In ES5, if the argument to this method is a primitive, then it will cause a TypeError. + // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen + // The following provides ES6 behavior for ES5 environments. - return ret.join(''); - } + var isFrozen = obj === Object(obj) ? Object.isFrozen(obj) : true; - function escapeHTML(s) { - var n = s; - n = n.replace(/&/g, '&'); - n = n.replace(//g, '>'); - n = n.replace(/"/g, '"'); - return n; - } + this.assert( + isFrozen + , 'expected #{this} to be frozen' + , 'expected #{this} to not be frozen' + ); + }); - exports.Diff = Diff; - exports.applyPatch = applyPatch; - exports.applyPatches = applyPatches; - exports.canonicalize = canonicalize; - exports.convertChangesToDMP = convertChangesToDMP; - exports.convertChangesToXML = convertChangesToXML; - exports.createPatch = createPatch; - exports.createTwoFilesPatch = createTwoFilesPatch; - exports.diffArrays = diffArrays; - exports.diffChars = diffChars; - exports.diffCss = diffCss; - exports.diffJson = diffJson; - exports.diffLines = diffLines; - exports.diffSentences = diffSentences; - exports.diffTrimmedLines = diffTrimmedLines; - exports.diffWords = diffWords; - exports.diffWordsWithSpace = diffWordsWithSpace; - exports.merge = merge; - exports.parsePatch = parsePatch; - exports.structuredPatch = structuredPatch; + /** + * ### .finite + * + * Asserts that the target is a number, and isn't `NaN` or positive/negative + * `Infinity`. + * + * expect(1).to.be.finite; + * + * Add `.not` earlier in the chain to negate `.finite`. However, it's + * dangerous to do so. The problem is that it creates uncertain expectations + * by asserting that the subject either isn't a number, or that it's `NaN`, or + * that it's positive `Infinity`, or that it's negative `Infinity`. It's often + * best to identify the exact output that's expected, and then write an + * assertion that only accepts that exact output. + * + * When the target isn't expected to be a number, it's often best to assert + * that it's the expected type, rather than asserting that it isn't one of + * many unexpected types. + * + * expect('foo').to.be.a('string'); // Recommended + * expect('foo').to.not.be.finite; // Not recommended + * + * When the target is expected to be `NaN`, it's often best to assert exactly + * that. + * + * expect(NaN).to.be.NaN; // Recommended + * expect(NaN).to.not.be.finite; // Not recommended + * + * When the target is expected to be positive infinity, it's often best to + * assert exactly that. + * + * expect(Infinity).to.equal(Infinity); // Recommended + * expect(Infinity).to.not.be.finite; // Not recommended + * + * When the target is expected to be negative infinity, it's often best to + * assert exactly that. + * + * expect(-Infinity).to.equal(-Infinity); // Recommended + * expect(-Infinity).to.not.be.finite; // Not recommended + * + * A custom error message can be given as the second argument to `expect`. + * + * expect('foo', 'nooo why fail??').to.be.finite; + * + * @name finite + * @namespace BDD + * @api public + */ - Object.defineProperty(exports, '__esModule', { value: true }); + Assertion.addProperty('finite', function(msg) { + var obj = flag(this, 'object'); - }))); + this.assert( + typeof obj === 'number' && isFinite(obj) + , 'expected #{this} to be a finite number' + , 'expected #{this} to not be a finite number' + ); + }); + }; - },{}],115:[function(require,module,exports){ - module.exports = extend; + /*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ - /* - var obj = {a: 3, b: 5}; - extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} - obj; // {a: 4, b: 5, c: 8} + var expect$1 = function (chai, util) { + chai.expect = function (val, message) { + return new chai.Assertion(val, message); + }; - var obj = {a: 3, b: 5}; - extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8} - obj; // {a: 3, b: 5} + /** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * expect.fail(); + * expect.fail("custom error message"); + * expect.fail(1, 2); + * expect.fail(1, 2, "custom error message"); + * expect.fail(1, 2, "custom error message", ">"); + * expect.fail(1, 2, undefined, ">"); + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace BDD + * @api public + */ - var arr = [1, 2, 3]; - var obj = {a: 3, b: 5}; - extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} - arr.push(4); - obj; // {a: 3, b: 5, c: [1, 2, 3, 4]} + chai.expect.fail = function (actual, expected, message, operator) { + if (arguments.length < 2) { + message = actual; + actual = undefined; + } - var arr = [1, 2, 3]; - var obj = {a: 3, b: 5}; - extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]} - arr.push(4); - obj; // {a: 3, b: 5, c: [1, 2, 3]} + message = message || 'expect.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, chai.expect.fail); + }; + }; - extend({a: 4, b: 5}); // {a: 4, b: 5} - extend({a: 4, b: 5}, 3); {a: 4, b: 5} - extend({a: 4, b: 5}, true); {a: 4, b: 5} - extend('hello', {a: 4, b: 5}); // throws - extend(3, {a: 4, b: 5}); // throws - */ + /*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ - function extend(/* [deep], obj1, obj2, [objn] */) { - var args = [].slice.call(arguments); - var deep = false; - if (typeof args[0] == 'boolean') { - deep = args.shift(); - } - var result = args[0]; - if (isUnextendable(result)) { - throw new Error('extendee must be an object'); - } - var extenders = args.slice(1); - var len = extenders.length; - for (var i = 0; i < len; i++) { - var extender = extenders[i]; - for (var key in extender) { - if (Object.prototype.hasOwnProperty.call(extender, key)) { - var value = extender[key]; - if (deep && isCloneable(value)) { - var base = Array.isArray(value) ? [] : {}; - result[key] = extend( - true, - Object.prototype.hasOwnProperty.call(result, key) && !isUnextendable(result[key]) - ? result[key] - : base, - value - ); - } else { - result[key] = value; - } + var should = function (chai, util) { + var Assertion = chai.Assertion; + + function loadShould () { + // explicitly define this method as function as to have it's name to include as `ssfi` + function shouldGetter() { + if (this instanceof String + || this instanceof Number + || this instanceof Boolean + || typeof Symbol === 'function' && this instanceof Symbol + || typeof BigInt === 'function' && this instanceof BigInt) { + return new Assertion(this.valueOf(), null, shouldGetter); } + return new Assertion(this, null, shouldGetter); } - } - return result; - } + function shouldSetter(value) { + // See https://github.com/chaijs/chai/issues/86: this makes + // `whatever.should = someValue` actually set `someValue`, which is + // especially useful for `global.should = require('chai').should()`. + // + // Note that we have to use [[DefineProperty]] instead of [[Put]] + // since otherwise we would trigger this very setter! + Object.defineProperty(this, 'should', { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } + // modify Object.prototype to have `should` + Object.defineProperty(Object.prototype, 'should', { + set: shouldSetter + , get: shouldGetter + , configurable: true + }); + + var should = {}; + + /** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * should.fail(); + * should.fail("custom error message"); + * should.fail(1, 2); + * should.fail(1, 2, "custom error message"); + * should.fail(1, 2, "custom error message", ">"); + * should.fail(1, 2, undefined, ">"); + * + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace BDD + * @api public + */ + + should.fail = function (actual, expected, message, operator) { + if (arguments.length < 2) { + message = actual; + actual = undefined; + } + + message = message || 'should.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, should.fail); + }; - function isCloneable(obj) { - return Array.isArray(obj) || {}.toString.call(obj) == '[object Object]'; - } + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * should.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */ - function isUnextendable(val) { - return !val || (typeof val != 'object' && typeof val != 'function'); - } + should.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.equal(val2); + }; - },{}],116:[function(require,module,exports){ - /** - * lodash (Custom Build) - * Build: `lodash modularize exports="npm" -o ./` - * Copyright jQuery Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ + /** + * ### .throw(function, [constructor/string/regexp], [string/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * should.throw(fn, 'function throws a reference error'); + * should.throw(fn, /function throws a reference error/); + * should.throw(fn, ReferenceError); + * should.throw(fn, ReferenceError, 'function throws a reference error'); + * should.throw(fn, ReferenceError, /function throws a reference error/); + * + * @name throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */ - /** Used as the `TypeError` message for "Functions" methods. */ - var FUNC_ERROR_TEXT = 'Expected a function'; + should.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.Throw(errt, errs); + }; - /** Used to stand-in for `undefined` hash values. */ - var HASH_UNDEFINED = '__lodash_hash_undefined__'; + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi'; + * + * should.exist(foo, 'foo exists'); + * + * @name exist + * @namespace Should + * @api public + */ - /** Used as references for various `Number` constants. */ - var INFINITY = 1 / 0; + should.exist = function (val, msg) { + new Assertion(val, msg).to.exist; + }; - /** `Object#toString` result references. */ - var funcTag = '[object Function]', - genTag = '[object GeneratorFunction]', - symbolTag = '[object Symbol]'; + // negation + should.not = {}; - /** Used to match property names within property paths. */ - var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, - reIsPlainProp = /^\w*$/, - reLeadingDot = /^\./, - rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + /** + * ### .not.equal(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * should.not.equal(3, 4, 'these numbers are not equal'); + * + * @name not.equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Should + * @api public + */ - /** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ - var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + should.not.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.not.equal(val2); + }; - /** Used to match backslashes in property paths. */ - var reEscapeChar = /\\(\\)?/g; + /** + * ### .throw(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * should.not.throw(fn, Error, 'function does not throw'); + * + * @name not.throw + * @alias not.Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Should + * @api public + */ - /** Used to detect host constructors (Safari). */ - var reIsHostCtor = /^\[object .+?Constructor\]$/; + should.not.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.not.Throw(errt, errs); + }; - /** Detect free variable `global` from Node.js. */ - var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + /** + * ### .not.exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var bar = null; + * + * should.not.exist(bar, 'bar does not exist'); + * + * @name not.exist + * @namespace Should + * @api public + */ - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + should.not.exist = function (val, msg) { + new Assertion(val, msg).to.not.exist; + }; - /** Used as a reference to the global object. */ - var root = freeGlobal || freeSelf || Function('return this')(); + should['throw'] = should['Throw']; + should.not['throw'] = should.not['Throw']; - /** - * Gets the value at `key` of `object`. - * - * @private - * @param {Object} [object] The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ - function getValue(object, key) { - return object == null ? undefined : object[key]; - } + return should; + } + chai.should = loadShould; + chai.Should = loadShould; + }; - /** - * Checks if `value` is a host object in IE < 9. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + /*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed */ - function isHostObject(value) { - // Many host objects are `Object` objects that can coerce to strings - // despite having improperly defined `toString` methods. - var result = false; - if (value != null && typeof value.toString != 'function') { - try { - result = !!(value + ''); - } catch (e) {} - } - return result; - } - /** Used for built-in method references. */ - var arrayProto = Array.prototype, - funcProto = Function.prototype, - objectProto = Object.prototype; + var assert = function (chai, util) { + /*! + * Chai dependencies. + */ - /** Used to detect overreaching core-js shims. */ - var coreJsData = root['__core-js_shared__']; + var Assertion = chai.Assertion + , flag = util.flag; - /** Used to detect methods masquerading as native. */ - var maskSrcKey = (function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); - return uid ? ('Symbol(src)_1.' + uid) : ''; - }()); + /*! + * Module export. + */ - /** Used to resolve the decompiled source of functions. */ - var funcToString = funcProto.toString; + /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @namespace Assert + * @api public + */ - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; + var assert = chai.assert = function (express, errmsg) { + var test = new Assertion(null, null, chai.assert, true); + test.assert( + express + , errmsg + , '[ negation message unavailable ]' + ); + }; - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var objectToString = objectProto.toString; + /** + * ### .fail([message]) + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * assert.fail(); + * assert.fail("custom error message"); + * assert.fail(1, 2); + * assert.fail(1, 2, "custom error message"); + * assert.fail(1, 2, "custom error message", ">"); + * assert.fail(1, 2, undefined, ">"); + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @namespace Assert + * @api public + */ - /** Used to detect if a method is native. */ - var reIsNative = RegExp('^' + - funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') - .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' - ); + assert.fail = function (actual, expected, message, operator) { + if (arguments.length < 2) { + // Comply with Node's fail([message]) interface - /** Built-in value references. */ - var Symbol = root.Symbol, - splice = arrayProto.splice; + message = actual; + actual = undefined; + } - /* Built-in method references that are verified to be native. */ - var Map = getNative(root, 'Map'), - nativeCreate = getNative(Object, 'create'); + message = message || 'assert.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, assert.fail); + }; - /** Used to convert symbols to primitives and strings. */ - var symbolProto = Symbol ? Symbol.prototype : undefined, - symbolToString = symbolProto ? symbolProto.toString : undefined; + /** + * ### .isOk(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.isOk('everything', 'everything is ok'); + * assert.isOk(false, 'this will fail'); + * + * @name isOk + * @alias ok + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Creates a hash object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function Hash(entries) { - var index = -1, - length = entries ? entries.length : 0; + assert.isOk = function (val, msg) { + new Assertion(val, msg, assert.isOk, true).is.ok; + }; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } + /** + * ### .isNotOk(object, [message]) + * + * Asserts that `object` is falsy. + * + * assert.isNotOk('everything', 'this will fail'); + * assert.isNotOk(false, 'this will pass'); + * + * @name isNotOk + * @alias notOk + * @param {Mixed} object to test + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Removes all key-value entries from the hash. - * - * @private - * @name clear - * @memberOf Hash - */ - function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(null) : {}; - } + assert.isNotOk = function (val, msg) { + new Assertion(val, msg, assert.isNotOk, true).is.not.ok; + }; - /** - * Removes `key` and its value from the hash. - * - * @private - * @name delete - * @memberOf Hash - * @param {Object} hash The hash to modify. - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function hashDelete(key) { - return this.has(key) && delete this.__data__[key]; - } + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Gets the hash value for `key`. - * - * @private - * @name get - * @memberOf Hash - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function hashGet(key) { - var data = this.__data__; - if (nativeCreate) { - var result = data[key]; - return result === HASH_UNDEFINED ? undefined : result; - } - return hasOwnProperty.call(data, key) ? data[key] : undefined; - } + assert.equal = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.equal, true); + + test.assert( + exp == flag(test, 'object') + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{act}' + , exp + , act + , true + ); + }; + + /** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.notEqual = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.notEqual, true); + + test.assert( + exp != flag(test, 'object') + , 'expected #{this} to not equal #{exp}' + , 'expected #{this} to equal #{act}' + , exp + , act + , true + ); + }; + + /** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if a hash value for `key` exists. - * - * @private - * @name has - * @memberOf Hash - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function hashHas(key) { - var data = this.__data__; - return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); - } + assert.strictEqual = function (act, exp, msg) { + new Assertion(act, msg, assert.strictEqual, true).to.equal(exp); + }; - /** - * Sets the hash `key` to `value`. - * - * @private - * @name set - * @memberOf Hash - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the hash instance. - */ - function hashSet(key, value) { - var data = this.__data__; - data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; - return this; - } + /** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ - // Add methods to `Hash`. - Hash.prototype.clear = hashClear; - Hash.prototype['delete'] = hashDelete; - Hash.prototype.get = hashGet; - Hash.prototype.has = hashHas; - Hash.prototype.set = hashSet; + assert.notStrictEqual = function (act, exp, msg) { + new Assertion(act, msg, assert.notStrictEqual, true).to.not.equal(exp); + }; - /** - * Creates an list cache object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function ListCache(entries) { - var index = -1, - length = entries ? entries.length : 0; + /** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @alias deepStrictEqual + * @namespace Assert + * @api public + */ - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } + assert.deepEqual = assert.deepStrictEqual = function (act, exp, msg) { + new Assertion(act, msg, assert.deepEqual, true).to.eql(exp); + }; - /** - * Removes all key-value entries from the list cache. - * - * @private - * @name clear - * @memberOf ListCache - */ - function listCacheClear() { - this.__data__ = []; - } + /** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Removes `key` and its value from the list cache. - * - * @private - * @name delete - * @memberOf ListCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function listCacheDelete(key) { - var data = this.__data__, - index = assocIndexOf(data, key); + assert.notDeepEqual = function (act, exp, msg) { + new Assertion(act, msg, assert.notDeepEqual, true).to.not.eql(exp); + }; - if (index < 0) { - return false; - } - var lastIndex = data.length - 1; - if (index == lastIndex) { - data.pop(); - } else { - splice.call(data, index, 1); - } - return true; - } + /** + * ### .isAbove(valueToCheck, valueToBeAbove, [message]) + * + * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`. + * + * assert.isAbove(5, 2, '5 is strictly greater than 2'); + * + * @name isAbove + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAbove + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Gets the list cache value for `key`. - * - * @private - * @name get - * @memberOf ListCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function listCacheGet(key) { - var data = this.__data__, - index = assocIndexOf(data, key); + assert.isAbove = function (val, abv, msg) { + new Assertion(val, msg, assert.isAbove, true).to.be.above(abv); + }; - return index < 0 ? undefined : data[index][1]; - } + /** + * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message]) + * + * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`. + * + * assert.isAtLeast(5, 2, '5 is greater or equal to 2'); + * assert.isAtLeast(3, 3, '3 is greater or equal to 3'); + * + * @name isAtLeast + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtLeast + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if a list cache value for `key` exists. - * - * @private - * @name has - * @memberOf ListCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function listCacheHas(key) { - return assocIndexOf(this.__data__, key) > -1; - } + assert.isAtLeast = function (val, atlst, msg) { + new Assertion(val, msg, assert.isAtLeast, true).to.be.least(atlst); + }; - /** - * Sets the list cache `key` to `value`. - * - * @private - * @name set - * @memberOf ListCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. - */ - function listCacheSet(key, value) { - var data = this.__data__, - index = assocIndexOf(data, key); + /** + * ### .isBelow(valueToCheck, valueToBeBelow, [message]) + * + * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`. + * + * assert.isBelow(3, 6, '3 is strictly less than 6'); + * + * @name isBelow + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeBelow + * @param {String} message + * @namespace Assert + * @api public + */ - if (index < 0) { - data.push([key, value]); - } else { - data[index][1] = value; - } - return this; - } + assert.isBelow = function (val, blw, msg) { + new Assertion(val, msg, assert.isBelow, true).to.be.below(blw); + }; - // Add methods to `ListCache`. - ListCache.prototype.clear = listCacheClear; - ListCache.prototype['delete'] = listCacheDelete; - ListCache.prototype.get = listCacheGet; - ListCache.prototype.has = listCacheHas; - ListCache.prototype.set = listCacheSet; + /** + * ### .isAtMost(valueToCheck, valueToBeAtMost, [message]) + * + * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`. + * + * assert.isAtMost(3, 6, '3 is less than or equal to 6'); + * assert.isAtMost(4, 4, '4 is less than or equal to 4'); + * + * @name isAtMost + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAtMost + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Creates a map cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function MapCache(entries) { - var index = -1, - length = entries ? entries.length : 0; + assert.isAtMost = function (val, atmst, msg) { + new Assertion(val, msg, assert.isAtMost, true).to.be.most(atmst); + }; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } + /** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Removes all key-value entries from the map. - * - * @private - * @name clear - * @memberOf MapCache - */ - function mapCacheClear() { - this.__data__ = { - 'hash': new Hash, - 'map': new (Map || ListCache), - 'string': new Hash + assert.isTrue = function (val, msg) { + new Assertion(val, msg, assert.isTrue, true).is['true']; }; - } - /** - * Removes `key` and its value from the map. - * - * @private - * @name delete - * @memberOf MapCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function mapCacheDelete(key) { - return getMapData(this, key)['delete'](key); - } + /** + * ### .isNotTrue(value, [message]) + * + * Asserts that `value` is not true. + * + * var tea = 'tasty chai'; + * assert.isNotTrue(tea, 'great, time for tea!'); + * + * @name isNotTrue + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Gets the map value for `key`. - * - * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function mapCacheGet(key) { - return getMapData(this, key).get(key); - } + assert.isNotTrue = function (val, msg) { + new Assertion(val, msg, assert.isNotTrue, true).to.not.equal(true); + }; - /** - * Checks if a map value for `key` exists. - * - * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function mapCacheHas(key) { - return getMapData(this, key).has(key); - } + /** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Sets the map `key` to `value`. - * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */ - function mapCacheSet(key, value) { - getMapData(this, key).set(key, value); - return this; - } + assert.isFalse = function (val, msg) { + new Assertion(val, msg, assert.isFalse, true).is['false']; + }; - // Add methods to `MapCache`. - MapCache.prototype.clear = mapCacheClear; - MapCache.prototype['delete'] = mapCacheDelete; - MapCache.prototype.get = mapCacheGet; - MapCache.prototype.has = mapCacheHas; - MapCache.prototype.set = mapCacheSet; + /** + * ### .isNotFalse(value, [message]) + * + * Asserts that `value` is not false. + * + * var tea = 'tasty chai'; + * assert.isNotFalse(tea, 'great, time for tea!'); + * + * @name isNotFalse + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Gets the index at which the `key` is found in `array` of key-value pairs. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function assocIndexOf(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; - } + assert.isNotFalse = function (val, msg) { + new Assertion(val, msg, assert.isNotFalse, true).to.not.equal(false); + }; - /** - * The base implementation of `_.get` without support for default values. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @returns {*} Returns the resolved value. - */ - function baseGet(object, path) { - path = isKey(path, object) ? [path] : castPath(path); + /** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - var index = 0, - length = path.length; + assert.isNull = function (val, msg) { + new Assertion(val, msg, assert.isNull, true).to.equal(null); + }; - while (object != null && index < length) { - object = object[toKey(path[index++])]; - } - return (index && index == length) ? object : undefined; - } + /** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * The base implementation of `_.isNative` without bad shim checks. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. - */ - function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); - } + assert.isNotNull = function (val, msg) { + new Assertion(val, msg, assert.isNotNull, true).to.not.equal(null); + }; - /** - * The base implementation of `_.toString` which doesn't convert nullish - * values to empty strings. - * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */ - function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; - } + /** + * ### .isNaN + * + * Asserts that value is NaN. + * + * assert.isNaN(NaN, 'NaN is NaN'); + * + * @name isNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Casts `value` to a path array if it's not one. - * - * @private - * @param {*} value The value to inspect. - * @returns {Array} Returns the cast property path array. - */ - function castPath(value) { - return isArray(value) ? value : stringToPath(value); - } + assert.isNaN = function (val, msg) { + new Assertion(val, msg, assert.isNaN, true).to.be.NaN; + }; - /** - * Gets the data for `map`. - * - * @private - * @param {Object} map The map to query. - * @param {string} key The reference key. - * @returns {*} Returns the map data. - */ - function getMapData(map, key) { - var data = map.__data__; - return isKeyable(key) - ? data[typeof key == 'string' ? 'string' : 'hash'] - : data.map; - } + /** + * ### .isNotNaN + * + * Asserts that value is not NaN. + * + * assert.isNotNaN(4, '4 is not NaN'); + * + * @name isNotNaN + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + assert.isNotNaN = function (val, msg) { + new Assertion(val, msg, assert.isNotNaN, true).not.to.be.NaN; + }; - /** - * Gets the native function at `key` of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. - */ - function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined; - } + /** + * ### .exists + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi'; + * + * assert.exists(foo, 'foo is neither `null` nor `undefined`'); + * + * @name exists + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if `value` is a property name and not a property path. - * - * @private - * @param {*} value The value to check. - * @param {Object} [object] The object to query keys on. - * @returns {boolean} Returns `true` if `value` is a property name, else `false`. - */ - function isKey(value, object) { - if (isArray(value)) { - return false; - } - var type = typeof value; - if (type == 'number' || type == 'symbol' || type == 'boolean' || - value == null || isSymbol(value)) { - return true; - } - return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || - (object != null && value in Object(object)); - } + assert.exists = function (val, msg) { + new Assertion(val, msg, assert.exists, true).to.exist; + }; - /** - * Checks if `value` is suitable for use as unique object key. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is suitable, else `false`. - */ - function isKeyable(value) { - var type = typeof value; - return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') - ? (value !== '__proto__') - : (value === null); - } + /** + * ### .notExists + * + * Asserts that the target is either `null` or `undefined`. + * + * var bar = null + * , baz; + * + * assert.notExists(bar); + * assert.notExists(baz, 'baz is either null or undefined'); + * + * @name notExists + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if `func` has its source masked. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. - */ - function isMasked(func) { - return !!maskSrcKey && (maskSrcKey in func); - } + assert.notExists = function (val, msg) { + new Assertion(val, msg, assert.notExists, true).to.not.exist; + }; - /** - * Converts `string` to a property path array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the property path array. - */ - var stringToPath = memoize(function(string) { - string = toString(string); + /** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - var result = []; - if (reLeadingDot.test(string)) { - result.push(''); - } - string.replace(rePropName, function(match, number, quote, string) { - result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); - }); - return result; - }); + assert.isUndefined = function (val, msg) { + new Assertion(val, msg, assert.isUndefined, true).to.equal(undefined); + }; - /** - * Converts `value` to a string key if it's not a string or symbol. - * - * @private - * @param {*} value The value to inspect. - * @returns {string|symbol} Returns the key. - */ - function toKey(value) { - if (typeof value == 'string' || isSymbol(value)) { - return value; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; - } + /** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isDefined + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Converts `func` to its source code. - * - * @private - * @param {Function} func The function to process. - * @returns {string} Returns the source code. - */ - function toSource(func) { - if (func != null) { - try { - return funcToString.call(func); - } catch (e) {} - try { - return (func + ''); - } catch (e) {} - } - return ''; - } + assert.isDefined = function (val, msg) { + new Assertion(val, msg, assert.isDefined, true).to.not.equal(undefined); + }; - /** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided, it determines the cache key for storing the result based on the - * arguments provided to the memoized function. By default, the first argument - * provided to the memoized function is used as the map cache key. The `func` - * is invoked with the `this` binding of the memoized function. - * - * **Note:** The cache is exposed as the `cache` property on the memoized - * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) - * method interface of `delete`, `get`, `has`, and `set`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] The function to resolve the cache key. - * @returns {Function} Returns the new memoized function. - * @example - * - * var object = { 'a': 1, 'b': 2 }; - * var other = { 'c': 3, 'd': 4 }; - * - * var values = _.memoize(_.values); - * values(object); - * // => [1, 2] - * - * values(other); - * // => [3, 4] - * - * object.a = 2; - * values(object); - * // => [1, 2] - * - * // Modify the result cache. - * values.cache.set(object, ['a', 'b']); - * values(object); - * // => ['a', 'b'] - * - * // Replace `_.memoize.Cache`. - * _.memoize.Cache = WeakMap; - */ - function memoize(func, resolver) { - if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { - throw new TypeError(FUNC_ERROR_TEXT); - } - var memoized = function() { - var args = arguments, - key = resolver ? resolver.apply(this, args) : args[0], - cache = memoized.cache; + /** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - if (cache.has(key)) { - return cache.get(key); - } - var result = func.apply(this, args); - memoized.cache = cache.set(key, result); - return result; + assert.isFunction = function (val, msg) { + new Assertion(val, msg, assert.isFunction, true).to.be.a('function'); }; - memoized.cache = new (memoize.Cache || MapCache); - return memoized; - } - // Assign cache to `_.memoize`. - memoize.Cache = MapCache; + /** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ - function eq(value, other) { - return value === other || (value !== value && other !== other); - } + assert.isNotFunction = function (val, msg) { + new Assertion(val, msg, assert.isNotFunction, true).to.not.be.a('function'); + }; - /** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ - var isArray = Array.isArray; + /** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`). + * _The assertion does not match subclassed objects._ + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */ - function isFunction(value) { - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8-9 which returns 'object' for typed array and other constructors. - var tag = isObject(value) ? objectToString.call(value) : ''; - return tag == funcTag || tag == genTag; - } + assert.isObject = function (val, msg) { + new Assertion(val, msg, assert.isObject, true).to.be.a('object'); + }; - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - function isObject(value) { - var type = typeof value; - return !!value && (type == 'object' || type == 'function'); - } + /** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`). + * + * var selection = 'chai' + * assert.isNotObject(selection, 'tea selection is not an object'); + * assert.isNotObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - function isObjectLike(value) { - return !!value && typeof value == 'object'; - } + assert.isNotObject = function (val, msg) { + new Assertion(val, msg, assert.isNotObject, true).to.not.be.a('object'); + }; + + /** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.isArray = function (val, msg) { + new Assertion(val, msg, assert.isArray, true).to.be.an('array'); + }; + + /** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && objectToString.call(value) == symbolTag); - } + assert.isNotArray = function (val, msg) { + new Assertion(val, msg, assert.isNotArray, true).to.not.be.an('array'); + }; - /** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {string} Returns the string. - * @example - * - * _.toString(null); - * // => '' - * - * _.toString(-0); - * // => '-0' - * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */ - function toString(value) { - return value == null ? '' : baseToString(value); - } + /** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - /** - * Gets the value at `path` of `object`. If the resolved value is - * `undefined`, the `defaultValue` is returned in its place. - * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.get(object, 'a[0].b.c'); - * // => 3 - * - * _.get(object, ['a', '0', 'b', 'c']); - * // => 3 - * - * _.get(object, 'a.b.c', 'default'); - * // => 'default' - */ - function get(object, path, defaultValue) { - var result = object == null ? undefined : baseGet(object, path); - return result === undefined ? defaultValue : result; - } + assert.isString = function (val, msg) { + new Assertion(val, msg, assert.isString, true).to.be.a('string'); + }; - module.exports = get; + /** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - },{}],117:[function(require,module,exports){ + assert.isNotString = function (val, msg) { + new Assertion(val, msg, assert.isNotString, true).to.not.be.a('string'); + }; - // cache a reference to setTimeout, so that our reference won't be stubbed out - // when using fake timers and errors will still get logged - // https://github.com/cjohansen/Sinon.JS/issues/381 - var realSetTimeout = setTimeout; + /** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @namespace Assert + * @api public + */ - function configureLogger(config) { - // eslint-disable-next-line no-param-reassign - config = config || {}; - // Function which prints errors. - if (!config.hasOwnProperty("logger")) { - // eslint-disable-next-line no-empty-function - config.logger = function() {}; - } - // When set to true, any errors logged will be thrown immediately; - // If set to false, the errors will be thrown in separate execution frame. - if (!config.hasOwnProperty("useImmediateExceptions")) { - config.useImmediateExceptions = true; - } - // wrap realSetTimeout with something we can stub in tests - if (!config.hasOwnProperty("setTimeout")) { - config.setTimeout = realSetTimeout; - } + assert.isNumber = function (val, msg) { + new Assertion(val, msg, assert.isNumber, true).to.be.a('number'); + }; - return function logError(label, e) { - var msg = `${label} threw exception: `; - var err = { - name: e.name || label, - message: e.message || e.toString(), - stack: e.stack - }; + /** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - function throwLoggedError() { - err.message = msg + err.message; - throw err; - } + assert.isNotNumber = function (val, msg) { + new Assertion(val, msg, assert.isNotNumber, true).to.not.be.a('number'); + }; - config.logger(`${msg}[${err.name}] ${err.message}`); + /** + * ### .isFinite(value, [message]) + * + * Asserts that `value` is a finite number. Unlike `.isNumber`, this will fail for `NaN` and `Infinity`. + * + * var cups = 2; + * assert.isFinite(cups, 'how many cups'); + * + * assert.isFinite(NaN); // throws + * + * @name isFinite + * @param {Number} value + * @param {String} message + * @namespace Assert + * @api public + */ - if (err.stack) { - config.logger(err.stack); - } + assert.isFinite = function (val, msg) { + new Assertion(val, msg, assert.isFinite, true).to.be.finite; + }; - if (config.useImmediateExceptions) { - throwLoggedError(); - } else { - config.setTimeout(throwLoggedError, 0); - } - }; - } + /** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - module.exports = configureLogger; + assert.isBoolean = function (val, msg) { + new Assertion(val, msg, assert.isBoolean, true).to.be.a('boolean'); + }; - },{}],118:[function(require,module,exports){ + /** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - var Event = require("./event"); + assert.isNotBoolean = function (val, msg) { + new Assertion(val, msg, assert.isNotBoolean, true).to.not.be.a('boolean'); + }; - function CustomEvent(type, customData, target) { - this.initEvent(type, false, false, target); - this.detail = customData.detail || null; - } + /** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @namespace Assert + * @api public + */ - CustomEvent.prototype = new Event(); + assert.typeOf = function (val, type, msg) { + new Assertion(val, msg, assert.typeOf, true).to.be.a(type); + }; - CustomEvent.prototype.constructor = CustomEvent; + /** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @namespace Assert + * @api public + */ - module.exports = CustomEvent; + assert.notTypeOf = function (val, type, msg) { + new Assertion(val, msg, assert.notTypeOf, true).to.not.be.a(type); + }; - },{"./event":120}],119:[function(require,module,exports){ + /** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */ - function flattenOptions(options) { - if (options !== Object(options)) { - return { - capture: Boolean(options), - once: false, - passive: false - }; - } - return { - capture: Boolean(options.capture), - once: Boolean(options.once), - passive: Boolean(options.passive) - }; - } - function not(fn) { - return function() { - return !fn.apply(this, arguments); - }; - } - function hasListenerFilter(listener, capture) { - return function(listenerSpec) { - return ( - listenerSpec.capture === capture && - listenerSpec.listener === listener - ); - }; - } + assert.instanceOf = function (val, type, msg) { + new Assertion(val, msg, assert.instanceOf, true).to.be.instanceOf(type); + }; - var EventTarget = { - // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener - addEventListener: function addEventListener( - event, - listener, - providedOptions - ) { - // 3. Let capture, passive, and once be the result of flattening more options. - // Flatten property before executing step 2, - // feture detection is usually based on registering handler with options object, - // that has getter defined - // addEventListener("load", () => {}, { - // get once() { supportsOnce = true; } - // }); - var options = flattenOptions(providedOptions); + /** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @namespace Assert + * @api public + */ - // 2. If callback is null, then return. - if (listener === null || listener === undefined) { - return; - } + assert.notInstanceOf = function (val, type, msg) { + new Assertion(val, msg, assert.notInstanceOf, true) + .to.not.be.instanceOf(type); + }; + + /** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Can be used to assert the + * inclusion of a value in an array, a substring in a string, or a subset of + * properties in an object. + * + * assert.include([1,2,3], 2, 'array contains value'); + * assert.include('foobar', 'foo', 'string contains substring'); + * assert.include({ foo: 'bar', hello: 'universe' }, { foo: 'bar' }, 'object contains property'); + * + * Strict equality (===) is used. When asserting the inclusion of a value in + * an array, the array is searched for an element that's strictly equal to the + * given value. When asserting a subset of properties in an object, the object + * is searched for the given property keys, checking that each one is present + * and strictly equal to the given property value. For instance: + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.include([obj1, obj2], obj1); + * assert.include({foo: obj1, bar: obj2}, {foo: obj1}); + * assert.include({foo: obj1, bar: obj2}, {foo: obj1, bar: obj2}); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ - this.eventListeners = this.eventListeners || {}; - this.eventListeners[event] = this.eventListeners[event] || []; + assert.include = function (exp, inc, msg) { + new Assertion(exp, msg, assert.include, true).include(inc); + }; - // 4. If context object’s associated list of event listener - // does not contain an event listener whose type is type, - // callback is callback, and capture is capture, then append - // a new event listener to it, whose type is type, callback is - // callback, capture is capture, passive is passive, and once is once. - if ( - !this.eventListeners[event].some( - hasListenerFilter(listener, options.capture) - ) - ) { - this.eventListeners[event].push({ - listener: listener, - capture: options.capture, - once: options.once - }); - } - }, + /** + * ### .notInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Can be used to assert + * the absence of a value in an array, a substring in a string, or a subset of + * properties in an object. + * + * assert.notInclude([1,2,3], 4, "array doesn't contain value"); + * assert.notInclude('foobar', 'baz', "string doesn't contain substring"); + * assert.notInclude({ foo: 'bar', hello: 'universe' }, { foo: 'baz' }, 'object doesn't contain property'); + * + * Strict equality (===) is used. When asserting the absence of a value in an + * array, the array is searched to confirm the absence of an element that's + * strictly equal to the given value. When asserting a subset of properties in + * an object, the object is searched to confirm that at least one of the given + * property keys is either not present or not strictly equal to the given + * property value. For instance: + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.notInclude([obj1, obj2], {a: 1}); + * assert.notInclude({foo: obj1, bar: obj2}, {foo: {a: 1}}); + * assert.notInclude({foo: obj1, bar: obj2}, {foo: obj1, bar: {b: 2}}); + * + * @name notInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ - // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener - removeEventListener: function removeEventListener( - event, - listener, - providedOptions - ) { - if (!this.eventListeners || !this.eventListeners[event]) { - return; - } + assert.notInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.notInclude, true).not.include(inc); + }; - // 2. Let capture be the result of flattening options. - var options = flattenOptions(providedOptions); + /** + * ### .deepInclude(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Can be used to assert the + * inclusion of a value in an array or a subset of properties in an object. + * Deep equality is used. + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.deepInclude([obj1, obj2], {a: 1}); + * assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}}); + * assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}}); + * + * @name deepInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ - // 3. If there is an event listener in the associated list of - // event listeners whose type is type, callback is callback, - // and capture is capture, then set that event listener’s - // removed to true and remove it from the associated list of event listeners. - this.eventListeners[event] = this.eventListeners[event].filter( - not(hasListenerFilter(listener, options.capture)) - ); - }, + assert.deepInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.deepInclude, true).deep.include(inc); + }; - dispatchEvent: function dispatchEvent(event) { - if (!this.eventListeners || !this.eventListeners[event.type]) { - return Boolean(event.defaultPrevented); - } + /** + * ### .notDeepInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Can be used to assert + * the absence of a value in an array or a subset of properties in an object. + * Deep equality is used. + * + * var obj1 = {a: 1} + * , obj2 = {b: 2}; + * assert.notDeepInclude([obj1, obj2], {a: 9}); + * assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 9}}); + * assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 9}}); + * + * @name notDeepInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @namespace Assert + * @api public + */ - var self = this; - var type = event.type; - var listeners = self.eventListeners[type]; + assert.notDeepInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.notDeepInclude, true).not.deep.include(inc); + }; - // Remove listeners, that should be dispatched once - // before running dispatch loop to avoid nested dispatch issues - self.eventListeners[type] = listeners.filter(function(listenerSpec) { - return !listenerSpec.once; - }); - listeners.forEach(function(listenerSpec) { - var listener = listenerSpec.listener; - if (typeof listener === "function") { - listener.call(self, event); - } else { - listener.handleEvent(event); - } - }); + /** + * ### .nestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.nestedInclude({'.a': {'b': 'x'}}, {'\\.a.[b]': 'x'}); + * assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'x'}); + * + * @name nestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - return Boolean(event.defaultPrevented); - } - }; + assert.nestedInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.nestedInclude, true).nested.include(inc); + }; - module.exports = EventTarget; + /** + * ### .notNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' does not include 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\.a.b': 'y'}); + * assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'y'}); + * + * @name notNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - },{}],120:[function(require,module,exports){ + assert.notNestedInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.notNestedInclude, true) + .not.nested.include(inc); + }; - function Event(type, bubbles, cancelable, target) { - this.initEvent(type, bubbles, cancelable, target); - } + /** + * ### .deepNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while checking for deep equality. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}}); + * assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}}); + * + * @name deepNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - Event.prototype = { - initEvent: function(type, bubbles, cancelable, target) { - this.type = type; - this.bubbles = bubbles; - this.cancelable = cancelable; - this.target = target; - this.currentTarget = target; - }, + assert.deepNestedInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.deepNestedInclude, true) + .deep.nested.include(inc); + }; - // eslint-disable-next-line no-empty-function - stopPropagation: function() {}, + /** + * ### .notDeepNestedInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' does not include 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while checking for deep equality. + * Enables the use of dot- and bracket-notation for referencing nested + * properties. + * '[]' and '.' in property names can be escaped using double backslashes. + * + * assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}}) + * assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}}); + * + * @name notDeepNestedInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - preventDefault: function() { - this.defaultPrevented = true; - } - }; + assert.notDeepNestedInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.notDeepNestedInclude, true) + .not.deep.nested.include(inc); + }; - module.exports = Event; + /** + * ### .ownInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while ignoring inherited properties. + * + * assert.ownInclude({ a: 1 }, { a: 1 }); + * + * @name ownInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - },{}],121:[function(require,module,exports){ + assert.ownInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.ownInclude, true).own.include(inc); + }; - module.exports = { - Event: require("./event"), - ProgressEvent: require("./progress-event"), - CustomEvent: require("./custom-event"), - EventTarget: require("./event-target") - }; + /** + * ### .notOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while ignoring inherited properties. + * + * Object.prototype.b = 2; + * + * assert.notOwnInclude({ a: 1 }, { b: 2 }); + * + * @name notOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - },{"./custom-event":118,"./event":120,"./event-target":119,"./progress-event":122}],122:[function(require,module,exports){ + assert.notOwnInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.notOwnInclude, true).not.own.include(inc); + }; - var Event = require("./event"); + /** + * ### .deepOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the inclusion of a subset of properties in an + * object while ignoring inherited properties and checking for deep equality. + * + * assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}}); + * + * @name deepOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - function ProgressEvent(type, progressEventRaw, target) { - this.initEvent(type, false, false, target); - this.loaded = - typeof progressEventRaw.loaded === "number" - ? progressEventRaw.loaded - : null; - this.total = - typeof progressEventRaw.total === "number" - ? progressEventRaw.total - : null; - this.lengthComputable = Boolean(progressEventRaw.total); - } + assert.deepOwnInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.deepOwnInclude, true) + .deep.own.include(inc); + }; - ProgressEvent.prototype = new Event(); + /** + * ### .notDeepOwnInclude(haystack, needle, [message]) + * + * Asserts that 'haystack' includes 'needle'. + * Can be used to assert the absence of a subset of properties in an + * object while ignoring inherited properties and checking for deep equality. + * + * assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}}); + * + * @name notDeepOwnInclude + * @param {Object} haystack + * @param {Object} needle + * @param {String} message + * @namespace Assert + * @api public + */ - ProgressEvent.prototype.constructor = ProgressEvent; + assert.notDeepOwnInclude = function(exp, inc, msg) { + new Assertion(exp, msg, assert.notDeepOwnInclude, true) + .not.deep.own.include(inc); + }; - module.exports = ProgressEvent; + /** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */ - },{"./event":120}],123:[function(require,module,exports){ + assert.match = function (exp, re, msg) { + new Assertion(exp, msg, assert.match, true).to.match(re); + }; - var FakeTimers = require("@sinonjs/fake-timers"); - var fakeServer = require("./index"); + /** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @namespace Assert + * @api public + */ - // eslint-disable-next-line no-empty-function - function Server() {} - Server.prototype = fakeServer; + assert.notMatch = function (exp, re, msg) { + new Assertion(exp, msg, assert.notMatch, true).to.not.match(re); + }; - var fakeServerWithClock = new Server(); + /** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * assert.property({ tea: { green: 'matcha' }}, 'toString'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ - fakeServerWithClock.addRequest = function addRequest(xhr) { - if (xhr.async) { - if (typeof setTimeout.clock === "object") { - this.clock = setTimeout.clock; - } else { - this.clock = FakeTimers.install(); - this.resetClock = true; - } + assert.property = function (obj, prop, msg) { + new Assertion(obj, msg, assert.property, true).to.have.property(prop); + }; - if (!this.longestTimeout) { - var clockSetTimeout = this.clock.setTimeout; - var clockSetInterval = this.clock.setInterval; - var server = this; + /** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ - this.clock.setTimeout = function(fn, timeout) { - server.longestTimeout = Math.max( - timeout, - server.longestTimeout || 0 - ); + assert.notProperty = function (obj, prop, msg) { + new Assertion(obj, msg, assert.notProperty, true) + .to.not.have.property(prop); + }; - return clockSetTimeout.apply(this, arguments); - }; + /** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property` with a value given by `value`. Uses a strict equality check + * (===). + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - this.clock.setInterval = function(fn, timeout) { - server.longestTimeout = Math.max( - timeout, - server.longestTimeout || 0 - ); + assert.propertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.propertyVal, true) + .to.have.property(prop, val); + }; - return clockSetInterval.apply(this, arguments); - }; - } - } + /** + * ### .notPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property` with value given by `value`. Uses a strict equality check + * (===). + * + * assert.notPropertyVal({ tea: 'is good' }, 'tea', 'is bad'); + * assert.notPropertyVal({ tea: 'is good' }, 'coffee', 'is good'); + * + * @name notPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - return fakeServer.addRequest.call(this, xhr); - }; + assert.notPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.notPropertyVal, true) + .to.not.have.property(prop, val); + }; - fakeServerWithClock.respond = function respond() { - var returnVal = fakeServer.respond.apply(this, arguments); + /** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property` with a value given by `value`. Uses a deep equality check. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' }); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ + + assert.deepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.deepPropertyVal, true) + .to.have.deep.property(prop, val); + }; - if (this.clock) { - this.clock.tick(this.longestTimeout || 0); - this.longestTimeout = 0; + /** + * ### .notDeepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct or inherited property named + * by `property` with value given by `value`. Uses a deep equality check. + * + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' }); + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' }); + * assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' }); + * + * @name notDeepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - if (this.resetClock) { - this.clock.uninstall(); - this.resetClock = false; - } - } + assert.notDeepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.notDeepPropertyVal, true) + .to.not.have.deep.property(prop, val); + }; - return returnVal; - }; + /** + * ### .ownProperty(object, property, [message]) + * + * Asserts that `object` has a direct property named by `property`. Inherited + * properties aren't checked. + * + * assert.ownProperty({ tea: { green: 'matcha' }}, 'tea'); + * + * @name ownProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ - fakeServerWithClock.restore = function restore() { - if (this.clock) { - this.clock.uninstall(); - } + assert.ownProperty = function (obj, prop, msg) { + new Assertion(obj, msg, assert.ownProperty, true) + .to.have.own.property(prop); + }; - return fakeServer.restore.apply(this, arguments); - }; + /** + * ### .notOwnProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a direct property named by + * `property`. Inherited properties aren't checked. + * + * assert.notOwnProperty({ tea: { green: 'matcha' }}, 'coffee'); + * assert.notOwnProperty({}, 'toString'); + * + * @name notOwnProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ - module.exports = fakeServerWithClock; + assert.notOwnProperty = function (obj, prop, msg) { + new Assertion(obj, msg, assert.notOwnProperty, true) + .to.not.have.own.property(prop); + }; - },{"./index":124,"@sinonjs/fake-timers":61}],124:[function(require,module,exports){ + /** + * ### .ownPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct property named by `property` and a value + * equal to the provided `value`. Uses a strict equality check (===). + * Inherited properties aren't checked. + * + * assert.ownPropertyVal({ coffee: 'is good'}, 'coffee', 'is good'); + * + * @name ownPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ - var fakeXhr = require("../fake-xhr"); - var push = [].push; - var log = require("./log"); - var configureLogError = require("../configure-logger"); - var pathToRegexp = require("path-to-regexp"); + assert.ownPropertyVal = function (obj, prop, value, msg) { + new Assertion(obj, msg, assert.ownPropertyVal, true) + .to.have.own.property(prop, value); + }; - var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + /** + * ### .notOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct property named by `property` + * with a value equal to the provided `value`. Uses a strict equality check + * (===). Inherited properties aren't checked. + * + * assert.notOwnPropertyVal({ tea: 'is better'}, 'tea', 'is worse'); + * assert.notOwnPropertyVal({}, 'toString', Object.prototype.toString); + * + * @name notOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ - function responseArray(handler) { - var response = handler; + assert.notOwnPropertyVal = function (obj, prop, value, msg) { + new Assertion(obj, msg, assert.notOwnPropertyVal, true) + .to.not.have.own.property(prop, value); + }; - if (Object.prototype.toString.call(handler) !== "[object Array]") { - response = [200, {}, handler]; - } + /** + * ### .deepOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a direct property named by `property` and a value + * equal to the provided `value`. Uses a deep equality check. Inherited + * properties aren't checked. + * + * assert.deepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' }); + * + * @name deepOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ - if (typeof response[2] !== "string") { - if (!supportsArrayBuffer) { - throw new TypeError( - `Fake server response body should be a string, but was ${typeof response[2]}` - ); - } else if (!(response[2] instanceof ArrayBuffer)) { - throw new TypeError( - `Fake server response body should be a string or ArrayBuffer, but was ${typeof response[2]}` - ); - } - } + assert.deepOwnPropertyVal = function (obj, prop, value, msg) { + new Assertion(obj, msg, assert.deepOwnPropertyVal, true) + .to.have.deep.own.property(prop, value); + }; - return response; - } + /** + * ### .notDeepOwnPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a direct property named by `property` + * with a value equal to the provided `value`. Uses a deep equality check. + * Inherited properties aren't checked. + * + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' }); + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' }); + * assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' }); + * assert.notDeepOwnPropertyVal({}, 'toString', Object.prototype.toString); + * + * @name notDeepOwnPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ - function getDefaultWindowLocation() { - var winloc = { - hostname: "localhost", - port: process.env.PORT || 80, - protocol: "http:" - }; - winloc.host = - winloc.hostname + - (String(winloc.port) === "80" ? "" : `:${winloc.port}`); - return winloc; - } + assert.notDeepOwnPropertyVal = function (obj, prop, value, msg) { + new Assertion(obj, msg, assert.notDeepOwnPropertyVal, true) + .to.not.have.deep.own.property(prop, value); + }; - function getWindowLocation() { - if (typeof window === "undefined") { - // Fallback - return getDefaultWindowLocation(); - } + /** + * ### .nestedProperty(object, property, [message]) + * + * Asserts that `object` has a direct or inherited property named by + * `property`, which can be a string using dot- and bracket-notation for + * nested reference. + * + * assert.nestedProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name nestedProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ - if (typeof window.location !== "undefined") { - // Browsers place location on window - return window.location; - } + assert.nestedProperty = function (obj, prop, msg) { + new Assertion(obj, msg, assert.nestedProperty, true) + .to.have.nested.property(prop); + }; - if ( - typeof window.window !== "undefined" && - typeof window.window.location !== "undefined" - ) { - // React Native on Android places location on window.window - return window.window.location; - } + /** + * ### .notNestedProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for nested reference. The + * property cannot exist on the object nor anywhere in its prototype chain. + * + * assert.notNestedProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notNestedProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @namespace Assert + * @api public + */ - return getDefaultWindowLocation(); - } + assert.notNestedProperty = function (obj, prop, msg) { + new Assertion(obj, msg, assert.notNestedProperty, true) + .to.not.have.nested.property(prop); + }; - function matchOne(response, reqMethod, reqUrl) { - var rmeth = response.method; - var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase(); - var url = response.url; - var matchUrl = - !url || - url === reqUrl || - (typeof url.test === "function" && url.test(reqUrl)) || - (typeof url === "function" && url(reqUrl) === true); + /** + * ### .nestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for nested + * reference. Uses a strict equality check (===). + * + * assert.nestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name nestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - return matchMethod && matchUrl; - } + assert.nestedPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.nestedPropertyVal, true) + .to.have.nested.property(prop, val); + }; - function match(response, request) { - var wloc = getWindowLocation(); + /** + * ### .notNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a property named by `property` with + * value given by `value`. `property` can use dot- and bracket-notation for + * nested reference. Uses a strict equality check (===). + * + * assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'coffee.green', 'matcha'); + * + * @name notNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - var rCurrLoc = new RegExp(`^${wloc.protocol}//${wloc.host}/`); + assert.notNestedPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.notNestedPropertyVal, true) + .to.not.have.nested.property(prop, val); + }; - var requestUrl = request.url; + /** + * ### .deepNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with a value given + * by `value`. `property` can use dot- and bracket-notation for nested + * reference. Uses a deep equality check. + * + * assert.deepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yum' }); + * + * @name deepNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) { - requestUrl = requestUrl.replace(rCurrLoc, "/"); - } + assert.deepNestedPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.deepNestedPropertyVal, true) + .to.have.deep.nested.property(prop, val); + }; - if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { - if (typeof response.response === "function") { - var ru = response.url; - var args = [request].concat( - ru && typeof ru.exec === "function" - ? ru.exec(requestUrl).slice(1) - : [] - ); - return response.response.apply(response, args); - } + /** + * ### .notDeepNestedPropertyVal(object, property, value, [message]) + * + * Asserts that `object` does _not_ have a property named by `property` with + * value given by `value`. `property` can use dot- and bracket-notation for + * nested reference. Uses a deep equality check. + * + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { oolong: 'yum' }); + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yuck' }); + * assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.black', { matcha: 'yum' }); + * + * @name notDeepNestedPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @namespace Assert + * @api public + */ - return true; - } + assert.notDeepNestedPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg, assert.notDeepNestedPropertyVal, true) + .to.not.have.deep.nested.property(prop, val); + }; - return false; - } + /** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` or `size` with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 6, 'string has length of 6'); + * assert.lengthOf(new Set([1,2,3]), 3, 'set has size of 3'); + * assert.lengthOf(new Map([['a',1],['b',2],['c',3]]), 3, 'map has size of 3'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @namespace Assert + * @api public + */ - function incrementRequestCount() { - var count = ++this.requestCount; + assert.lengthOf = function (exp, len, msg) { + new Assertion(exp, msg, assert.lengthOf, true).to.have.lengthOf(len); + }; - this.requested = true; + /** + * ### .hasAnyKeys(object, [keys], [message]) + * + * Asserts that `object` has at least one of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'iDontExist', 'baz']); + * assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, iDontExist: 99, baz: 1337}); + * assert.hasAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.hasAnyKeys(new Set([{foo: 'bar'}, 'anotherKey']), [{foo: 'bar'}, 'anotherKey']); + * + * @name hasAnyKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - this.requestedOnce = count === 1; - this.requestedTwice = count === 2; - this.requestedThrice = count === 3; + assert.hasAnyKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.hasAnyKeys, true).to.have.any.keys(keys); + }; - this.firstRequest = this.getRequest(0); - this.secondRequest = this.getRequest(1); - this.thirdRequest = this.getRequest(2); + /** + * ### .hasAllKeys(object, [keys], [message]) + * + * Asserts that `object` has all and only all of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']); + * assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337]); + * assert.hasAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.hasAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']); + * + * @name hasAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */ - this.lastRequest = this.getRequest(count - 1); - } + assert.hasAllKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.hasAllKeys, true).to.have.all.keys(keys); + }; - var fakeServer = { - create: function(config) { - var server = Object.create(this); - server.configure(config); - this.xhr = fakeXhr.useFakeXMLHttpRequest(); - server.requests = []; - server.requestCount = 0; - server.queue = []; - server.responses = []; + /** + * ### .containsAllKeys(object, [keys], [message]) + * + * Asserts that `object` has all of the `keys` provided but may have more keys not listed. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'baz']); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, baz: 1337}); + * assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337}); + * assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}]); + * assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']); + * assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}]); + * assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']); + * + * @name containsAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */ - this.xhr.onCreate = function(xhrObj) { - xhrObj.unsafeHeadersEnabled = function() { - return !(server.unsafeHeadersEnabled === false); - }; - server.addRequest(xhrObj); - }; + assert.containsAllKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.containsAllKeys, true) + .to.contain.all.keys(keys); + }; - return server; - }, + /** + * ### .doesNotHaveAnyKeys(object, [keys], [message]) + * + * Asserts that `object` has none of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']); + * assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'}); + * assert.doesNotHaveAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']); + * assert.doesNotHaveAnyKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']); + * + * @name doesNotHaveAnyKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */ - configure: function(config) { - var self = this; - var allowlist = { - autoRespond: true, - autoRespondAfter: true, - respondImmediately: true, - fakeHTTPMethods: true, - logger: true, - unsafeHeadersEnabled: true - }; + assert.doesNotHaveAnyKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.doesNotHaveAnyKeys, true) + .to.not.have.any.keys(keys); + }; - // eslint-disable-next-line no-param-reassign - config = config || {}; + /** + * ### .doesNotHaveAllKeys(object, [keys], [message]) + * + * Asserts that `object` does not have at least one of the `keys` provided. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']); + * assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'}); + * assert.doesNotHaveAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']); + * assert.doesNotHaveAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']); + * + * @name doesNotHaveAllKeys + * @param {Mixed} object + * @param {String[]} keys + * @param {String} message + * @namespace Assert + * @api public + */ - Object.keys(config).forEach(function(setting) { - if (setting in allowlist) { - self[setting] = config[setting]; - } - }); + assert.doesNotHaveAllKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.doesNotHaveAllKeys, true) + .to.not.have.all.keys(keys); + }; - self.logError = configureLogError(config); - }, + /** + * ### .hasAnyDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has at least one of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'}); + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'}); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {three: 'three'}]); + * assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name hasAnyDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - addRequest: function addRequest(xhrObj) { - var server = this; - push.call(this.requests, xhrObj); + assert.hasAnyDeepKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.hasAnyDeepKeys, true) + .to.have.any.deep.keys(keys); + }; - incrementRequestCount.call(this); + /** + * ### .hasAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has all and only all of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne']]), {one: 'one'}); + * assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.hasAllDeepKeys(new Set([{one: 'one'}]), {one: 'one'}); + * assert.hasAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name hasAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - xhrObj.onSend = function() { - server.handleRequest(this); + assert.hasAllDeepKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.hasAllDeepKeys, true) + .to.have.all.deep.keys(keys); + }; - if (server.respondImmediately) { - server.respond(); - } else if (server.autoRespond && !server.responding) { - setTimeout(function() { - server.responding = false; - server.respond(); - }, server.autoRespondAfter || 10); + /** + * ### .containsAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` contains all of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'}); + * assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]); + * assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'}); + * assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]); + * + * @name containsAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - server.responding = true; - } - }; - }, + assert.containsAllDeepKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.containsAllDeepKeys, true) + .to.contain.all.deep.keys(keys); + }; - getHTTPMethod: function getHTTPMethod(request) { - if (this.fakeHTTPMethods && /post/i.test(request.method)) { - var matches = (request.requestBody || "").match( - /_method=([^\b;]+)/ - ); - return matches ? matches[1] : request.method; - } + /** + * ### .doesNotHaveAnyDeepKeys(object, [keys], [message]) + * + * Asserts that `object` has none of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'}); + * assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {fifty: 'fifty'}]); + * assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'}); + * assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{twenty: 'twenty'}, {fifty: 'fifty'}]); + * + * @name doesNotHaveAnyDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - return request.method; - }, + assert.doesNotHaveAnyDeepKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.doesNotHaveAnyDeepKeys, true) + .to.not.have.any.deep.keys(keys); + }; - handleRequest: function handleRequest(xhr) { - if (xhr.async) { - push.call(this.queue, xhr); - } else { - this.processRequest(xhr); - } - }, + /** + * ### .doesNotHaveAllDeepKeys(object, [keys], [message]) + * + * Asserts that `object` does not have at least one of the `keys` provided. + * Since Sets and Maps can have objects as keys you can use this assertion to perform + * a deep comparison. + * You can also provide a single object instead of a `keys` array and its keys + * will be used as the expected set of keys. + * + * assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'}); + * assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {one: 'one'}]); + * assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'}); + * assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {fifty: 'fifty'}]); + * + * @name doesNotHaveAllDeepKeys + * @param {Mixed} object + * @param {Array|Object} keys + * @param {String} message + * @namespace Assert + * @api public + */ - logger: function() { - // no-op; override via configure() - }, + assert.doesNotHaveAllDeepKeys = function (obj, keys, msg) { + new Assertion(obj, msg, assert.doesNotHaveAllDeepKeys, true) + .to.not.have.all.deep.keys(keys); + }; - logError: configureLogError({}), + /** + * ### .throws(fn, [errorLike/string/regexp], [string/regexp], [message]) + * + * If `errorLike` is an `Error` constructor, asserts that `fn` will throw an error that is an + * instance of `errorLike`. + * If `errorLike` is an `Error` instance, asserts that the error thrown is the same + * instance as `errorLike`. + * If `errMsgMatcher` is provided, it also asserts that the error thrown will have a + * message matching `errMsgMatcher`. + * + * assert.throws(fn, 'Error thrown must have this msg'); + * assert.throws(fn, /Error thrown must have a msg that matches this/); + * assert.throws(fn, ReferenceError); + * assert.throws(fn, errorInstance); + * assert.throws(fn, ReferenceError, 'Error thrown must be a ReferenceError and have this msg'); + * assert.throws(fn, errorInstance, 'Error thrown must be the same errorInstance and have this msg'); + * assert.throws(fn, ReferenceError, /Error thrown must be a ReferenceError and match this/); + * assert.throws(fn, errorInstance, /Error thrown must be the same errorInstance and match this/); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} fn + * @param {ErrorConstructor|Error} errorLike + * @param {RegExp|String} errMsgMatcher + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */ - log: log, + assert.throws = function (fn, errorLike, errMsgMatcher, msg) { + if ('string' === typeof errorLike || errorLike instanceof RegExp) { + errMsgMatcher = errorLike; + errorLike = null; + } - respondWith: function respondWith(method, url, body) { - if (arguments.length === 1 && typeof method !== "function") { - this.response = responseArray(method); - return; - } + var assertErr = new Assertion(fn, msg, assert.throws, true) + .to.throw(errorLike, errMsgMatcher); + return flag(assertErr, 'object'); + }; - if (arguments.length === 1) { - // eslint-disable-next-line no-param-reassign - body = method; - // eslint-disable-next-line no-param-reassign - url = method = null; - } + /** + * ### .doesNotThrow(fn, [errorLike/string/regexp], [string/regexp], [message]) + * + * If `errorLike` is an `Error` constructor, asserts that `fn` will _not_ throw an error that is an + * instance of `errorLike`. + * If `errorLike` is an `Error` instance, asserts that the error thrown is _not_ the same + * instance as `errorLike`. + * If `errMsgMatcher` is provided, it also asserts that the error thrown will _not_ have a + * message matching `errMsgMatcher`. + * + * assert.doesNotThrow(fn, 'Any Error thrown must not have this message'); + * assert.doesNotThrow(fn, /Any Error thrown must not match this/); + * assert.doesNotThrow(fn, Error); + * assert.doesNotThrow(fn, errorInstance); + * assert.doesNotThrow(fn, Error, 'Error must not have this message'); + * assert.doesNotThrow(fn, errorInstance, 'Error must not have this message'); + * assert.doesNotThrow(fn, Error, /Error must not match this/); + * assert.doesNotThrow(fn, errorInstance, /Error must not match this/); + * + * @name doesNotThrow + * @param {Function} fn + * @param {ErrorConstructor} errorLike + * @param {RegExp|String} errMsgMatcher + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @namespace Assert + * @api public + */ - if (arguments.length === 2) { - // eslint-disable-next-line no-param-reassign - body = url; - // eslint-disable-next-line no-param-reassign - url = method; - // eslint-disable-next-line no-param-reassign - method = null; - } + assert.doesNotThrow = function (fn, errorLike, errMsgMatcher, msg) { + if ('string' === typeof errorLike || errorLike instanceof RegExp) { + errMsgMatcher = errorLike; + errorLike = null; + } - // Escape port number to prevent "named" parameters in 'path-to-regexp' module - if (typeof url === "string" && url !== "" && /:[0-9]+\//.test(url)) { - var m = url.match(/^(https?:\/\/.*?):([0-9]+\/.*)$/); - // eslint-disable-next-line no-param-reassign - url = `${m[1]}\\:${m[2]}`; - } + new Assertion(fn, msg, assert.doesNotThrow, true) + .to.not.throw(errorLike, errMsgMatcher); + }; - push.call(this.responses, { - method: method, - url: - typeof url === "string" && url !== "" ? pathToRegexp(url) : url, - response: typeof body === "function" ? body : responseArray(body) - }); - }, + /** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @namespace Assert + * @api public + */ - respond: function respond() { - if (arguments.length > 0) { - this.respondWith.apply(this, arguments); - } + assert.operator = function (val, operator, val2, msg) { + var ok; + switch(operator) { + case '==': + ok = val == val2; + break; + case '===': + ok = val === val2; + break; + case '>': + ok = val > val2; + break; + case '>=': + ok = val >= val2; + break; + case '<': + ok = val < val2; + break; + case '<=': + ok = val <= val2; + break; + case '!=': + ok = val != val2; + break; + case '!==': + ok = val !== val2; + break; + default: + msg = msg ? msg + ': ' : msg; + throw new chai.AssertionError( + msg + 'Invalid operator "' + operator + '"', + undefined, + assert.operator + ); + } + var test = new Assertion(ok, msg, assert.operator, true); + test.assert( + true === flag(test, 'object') + , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) + , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); + }; - var queue = this.queue || []; - var requests = queue.splice(0, queue.length); - var self = this; + /** + * ### .closeTo(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); + * + * @name closeTo + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @namespace Assert + * @api public + */ - requests.forEach(function(request) { - self.processRequest(request); - }); - }, + assert.closeTo = function (act, exp, delta, msg) { + new Assertion(act, msg, assert.closeTo, true).to.be.closeTo(exp, delta); + }; - respondAll: function respondAll() { - if (this.respondImmediately) { - return; - } + /** + * ### .approximately(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.approximately(1.5, 1, 0.5, 'numbers are close'); + * + * @name approximately + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @namespace Assert + * @api public + */ - this.queue = this.requests.slice(0); + assert.approximately = function (act, exp, delta, msg) { + new Assertion(act, msg, assert.approximately, true) + .to.be.approximately(exp, delta); + }; - var request; - while ((request = this.queue.shift())) { - this.processRequest(request); - } - }, + /** + * ### .sameMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members in any order. Uses a + * strict equality check (===). + * + * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); + * + * @name sameMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - processRequest: function processRequest(request) { - try { - if (request.aborted) { - return; - } + assert.sameMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.sameMembers, true) + .to.have.same.members(set2); + }; - var response = this.response || [404, {}, ""]; + /** + * ### .notSameMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` don't have the same members in any order. + * Uses a strict equality check (===). + * + * assert.notSameMembers([ 1, 2, 3 ], [ 5, 1, 3 ], 'not same members'); + * + * @name notSameMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - if (this.responses) { - for (var l = this.responses.length, i = l - 1; i >= 0; i--) { - if (match.call(this, this.responses[i], request)) { - response = this.responses[i].response; - break; - } - } - } + assert.notSameMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.notSameMembers, true) + .to.not.have.same.members(set2); + }; - if (request.readyState !== 4) { - this.log(response, request); + /** + * ### .sameDeepMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members in any order. Uses a + * deep equality check. + * + * assert.sameDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [{ b: 2 }, { a: 1 }, { c: 3 }], 'same deep members'); + * + * @name sameDeepMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - request.respond(response[0], response[1], response[2]); - } - } catch (e) { - this.logError("Fake server request processing", e); - } - }, + assert.sameDeepMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.sameDeepMembers, true) + .to.have.same.deep.members(set2); + }; - restore: function restore() { - return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments); - }, + /** + * ### .notSameDeepMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` don't have the same members in any order. + * Uses a deep equality check. + * + * assert.notSameDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [{ b: 2 }, { a: 1 }, { f: 5 }], 'not same deep members'); + * + * @name notSameDeepMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - getRequest: function getRequest(index) { - return this.requests[index] || null; - }, + assert.notSameDeepMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.notSameDeepMembers, true) + .to.not.have.same.deep.members(set2); + }; - reset: function reset() { - this.resetBehavior(); - this.resetHistory(); - }, + /** + * ### .sameOrderedMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members in the same order. + * Uses a strict equality check (===). + * + * assert.sameOrderedMembers([ 1, 2, 3 ], [ 1, 2, 3 ], 'same ordered members'); + * + * @name sameOrderedMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - resetBehavior: function resetBehavior() { - this.responses.length = this.queue.length = 0; - }, + assert.sameOrderedMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.sameOrderedMembers, true) + .to.have.same.ordered.members(set2); + }; - resetHistory: function resetHistory() { - this.requests.length = this.requestCount = 0; + /** + * ### .notSameOrderedMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` don't have the same members in the same + * order. Uses a strict equality check (===). + * + * assert.notSameOrderedMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'not same ordered members'); + * + * @name notSameOrderedMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - this.requestedOnce = this.requestedTwice = this.requestedThrice = this.requested = false; + assert.notSameOrderedMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.notSameOrderedMembers, true) + .to.not.have.same.ordered.members(set2); + }; - this.firstRequest = this.secondRequest = this.thirdRequest = this.lastRequest = null; - } - }; + /** + * ### .sameDeepOrderedMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members in the same order. + * Uses a deep equality check. + * + * assert.sameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 }, { c: 3 } ], 'same deep ordered members'); + * + * @name sameDeepOrderedMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - module.exports = fakeServer; + assert.sameDeepOrderedMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.sameDeepOrderedMembers, true) + .to.have.same.deep.ordered.members(set2); + }; - },{"../configure-logger":117,"../fake-xhr":127,"./log":125,"path-to-regexp":148}],125:[function(require,module,exports){ - var inspect = require("util").inspect; + /** + * ### .notSameDeepOrderedMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` don't have the same members in the same + * order. Uses a deep equality check. + * + * assert.notSameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 }, { z: 5 } ], 'not same deep ordered members'); + * assert.notSameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 }, { c: 3 } ], 'not same deep ordered members'); + * + * @name notSameDeepOrderedMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @namespace Assert + * @api public + */ - function log(response, request) { - var str; + assert.notSameDeepOrderedMembers = function (set1, set2, msg) { + new Assertion(set1, msg, assert.notSameDeepOrderedMembers, true) + .to.not.have.same.deep.ordered.members(set2); + }; - str = `Request:\n${inspect(request)}\n\n`; - str += `Response:\n${inspect(response)}\n\n`; + /** + * ### .includeMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset` in any order. Uses a + * strict equality check (===). Duplicates are ignored. + * + * assert.includeMembers([ 1, 2, 3 ], [ 2, 1, 2 ], 'include members'); + * + * @name includeMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - /* istanbul ignore else: when this.logger is not a function, it can't be called */ - if (typeof this.logger === "function") { - this.logger(str); - } - } + assert.includeMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.includeMembers, true) + .to.include.members(subset); + }; - module.exports = log; + /** + * ### .notIncludeMembers(superset, subset, [message]) + * + * Asserts that `subset` isn't included in `superset` in any order. Uses a + * strict equality check (===). Duplicates are ignored. + * + * assert.notIncludeMembers([ 1, 2, 3 ], [ 5, 1 ], 'not include members'); + * + * @name notIncludeMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - },{"util":113}],126:[function(require,module,exports){ + assert.notIncludeMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.notIncludeMembers, true) + .to.not.include.members(subset); + }; - exports.isSupported = (function() { - try { - return Boolean(new Blob()); - } catch (e) { - return false; - } - })(); + /** + * ### .includeDeepMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset` in any order. Uses a deep + * equality check. Duplicates are ignored. + * + * assert.includeDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 }, { b: 2 } ], 'include deep members'); + * + * @name includeDeepMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - },{}],127:[function(require,module,exports){ + assert.includeDeepMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.includeDeepMembers, true) + .to.include.deep.members(subset); + }; - var GlobalTextEncoder = - typeof TextEncoder !== "undefined" - ? TextEncoder - : require("@sinonjs/text-encoding").TextEncoder; - var globalObject = require("@sinonjs/commons").global; - var configureLogError = require("../configure-logger"); - var sinonEvent = require("../event"); - var extend = require("just-extend"); + /** + * ### .notIncludeDeepMembers(superset, subset, [message]) + * + * Asserts that `subset` isn't included in `superset` in any order. Uses a + * deep equality check. Duplicates are ignored. + * + * assert.notIncludeDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { f: 5 } ], 'not include deep members'); + * + * @name notIncludeDeepMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - var supportsProgress = typeof ProgressEvent !== "undefined"; - var supportsCustomEvent = typeof CustomEvent !== "undefined"; - var supportsFormData = typeof FormData !== "undefined"; - var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; - var supportsBlob = require("./blob").isSupported; + assert.notIncludeDeepMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.notIncludeDeepMembers, true) + .to.not.include.deep.members(subset); + }; - function getWorkingXHR(globalScope) { - var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined"; - if (supportsXHR) { - return globalScope.XMLHttpRequest; - } + /** + * ### .includeOrderedMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset` in the same order + * beginning with the first element in `superset`. Uses a strict equality + * check (===). + * + * assert.includeOrderedMembers([ 1, 2, 3 ], [ 1, 2 ], 'include ordered members'); + * + * @name includeOrderedMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined"; - if (supportsActiveX) { - return function() { - return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0"); - }; - } + assert.includeOrderedMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.includeOrderedMembers, true) + .to.include.ordered.members(subset); + }; - return false; - } + /** + * ### .notIncludeOrderedMembers(superset, subset, [message]) + * + * Asserts that `subset` isn't included in `superset` in the same order + * beginning with the first element in `superset`. Uses a strict equality + * check (===). + * + * assert.notIncludeOrderedMembers([ 1, 2, 3 ], [ 2, 1 ], 'not include ordered members'); + * assert.notIncludeOrderedMembers([ 1, 2, 3 ], [ 2, 3 ], 'not include ordered members'); + * + * @name notIncludeOrderedMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - // Ref: https://fetch.spec.whatwg.org/#forbidden-header-name - var unsafeHeaders = { - "Accept-Charset": true, - "Access-Control-Request-Headers": true, - "Access-Control-Request-Method": true, - "Accept-Encoding": true, - Connection: true, - "Content-Length": true, - Cookie: true, - Cookie2: true, - "Content-Transfer-Encoding": true, - Date: true, - DNT: true, - Expect: true, - Host: true, - "Keep-Alive": true, - Origin: true, - Referer: true, - TE: true, - Trailer: true, - "Transfer-Encoding": true, - Upgrade: true, - "User-Agent": true, - Via: true - }; + assert.notIncludeOrderedMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.notIncludeOrderedMembers, true) + .to.not.include.ordered.members(subset); + }; - function EventTargetHandler() { - var self = this; - var events = [ - "loadstart", - "progress", - "abort", - "error", - "load", - "timeout", - "loadend" - ]; + /** + * ### .includeDeepOrderedMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset` in the same order + * beginning with the first element in `superset`. Uses a deep equality + * check. + * + * assert.includeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 } ], 'include deep ordered members'); + * + * @name includeDeepOrderedMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - function addEventListener(eventName) { - self.addEventListener(eventName, function(event) { - var listener = self[`on${eventName}`]; + assert.includeDeepOrderedMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.includeDeepOrderedMembers, true) + .to.include.deep.ordered.members(subset); + }; - if (listener && typeof listener === "function") { - listener.call(this, event); - } - }); - } + /** + * ### .notIncludeDeepOrderedMembers(superset, subset, [message]) + * + * Asserts that `subset` isn't included in `superset` in the same order + * beginning with the first element in `superset`. Uses a deep equality + * check. + * + * assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { f: 5 } ], 'not include deep ordered members'); + * assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 } ], 'not include deep ordered members'); + * assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { c: 3 } ], 'not include deep ordered members'); + * + * @name notIncludeDeepOrderedMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @namespace Assert + * @api public + */ - events.forEach(addEventListener); - } + assert.notIncludeDeepOrderedMembers = function (superset, subset, msg) { + new Assertion(superset, msg, assert.notIncludeDeepOrderedMembers, true) + .to.not.include.deep.ordered.members(subset); + }; - EventTargetHandler.prototype = sinonEvent.EventTarget; + /** + * ### .oneOf(inList, list, [message]) + * + * Asserts that non-object, non-array value `inList` appears in the flat array `list`. + * + * assert.oneOf(1, [ 2, 1 ], 'Not found in list'); + * + * @name oneOf + * @param {*} inList + * @param {Array<*>} list + * @param {String} message + * @namespace Assert + * @api public + */ - function normalizeHeaderValue(value) { - // Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes - /*eslint no-control-regex: "off"*/ - return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g, ""); - } + assert.oneOf = function (inList, list, msg) { + new Assertion(inList, msg, assert.oneOf, true).to.be.oneOf(list); + }; - function getHeader(headers, header) { - var foundHeader = Object.keys(headers).filter(function(h) { - return h.toLowerCase() === header.toLowerCase(); - }); + /** + * ### .changes(function, object, property, [message]) + * + * Asserts that a function changes the value of a property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 22 }; + * assert.changes(fn, obj, 'val'); + * + * @name changes + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - return foundHeader[0] || null; - } + assert.changes = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } - function excludeSetCookie2Header(header) { - return !/^Set-Cookie2?$/i.test(header); - } + new Assertion(fn, msg, assert.changes, true).to.change(obj, prop); + }; - function verifyResponseBodyType(body, responseType) { - var error = null; - var isString = typeof body === "string"; + /** + * ### .changesBy(function, object, property, delta, [message]) + * + * Asserts that a function changes the value of a property by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 2 }; + * assert.changesBy(fn, obj, 'val', 2); + * + * @name changesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - if (responseType === "arraybuffer") { - if (!isString && !(body instanceof ArrayBuffer)) { - error = new Error( - `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string or ArrayBuffer.` - ); - error.name = "InvalidBodyException"; - } - } else if (responseType === "blob") { - if ( - !isString && - !(body instanceof ArrayBuffer) && - supportsBlob && - !(body instanceof Blob) - ) { - error = new Error( - `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string, ArrayBuffer, or Blob.` - ); - error.name = "InvalidBodyException"; - } - } else if (!isString) { - error = new Error( - `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string.` - ); - error.name = "InvalidBodyException"; + assert.changesBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; } - if (error) { - throw error; - } - } + new Assertion(fn, msg, assert.changesBy, true) + .to.change(obj, prop).by(delta); + }; - function convertToArrayBuffer(body, encoding) { - if (body instanceof ArrayBuffer) { - return body; + /** + * ### .doesNotChange(function, object, property, [message]) + * + * Asserts that a function does not change the value of a property. + * + * var obj = { val: 10 }; + * var fn = function() { console.log('foo'); }; + * assert.doesNotChange(fn, obj, 'val'); + * + * @name doesNotChange + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotChange = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; } - return new GlobalTextEncoder(encoding || "utf-8").encode(body).buffer; - } + return new Assertion(fn, msg, assert.doesNotChange, true) + .to.not.change(obj, prop); + }; - function isXmlContentType(contentType) { - return ( - !contentType || - /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType) - ); - } + /** + * ### .changesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not change the value of a property or of a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 10 }; + * assert.changesButNotBy(fn, obj, 'val', 5); + * + * @name changesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - function clearResponse(xhr) { - if (xhr.responseType === "" || xhr.responseType === "text") { - xhr.response = xhr.responseText = ""; - } else { - xhr.response = xhr.responseText = null; + assert.changesButNotBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; } - xhr.responseXML = null; - } - function fakeXMLHttpRequestFor(globalScope) { - var isReactNative = - globalScope.navigator && - globalScope.navigator.product === "ReactNative"; - var sinonXhr = { XMLHttpRequest: globalScope.XMLHttpRequest }; - sinonXhr.GlobalXMLHttpRequest = globalScope.XMLHttpRequest; - sinonXhr.GlobalActiveXObject = globalScope.ActiveXObject; - sinonXhr.supportsActiveX = - typeof sinonXhr.GlobalActiveXObject !== "undefined"; - sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined"; - sinonXhr.workingXHR = getWorkingXHR(globalScope); - sinonXhr.supportsTimeout = - sinonXhr.supportsXHR && - "timeout" in new sinonXhr.GlobalXMLHttpRequest(); - sinonXhr.supportsCORS = - isReactNative || - (sinonXhr.supportsXHR && - "withCredentials" in new sinonXhr.GlobalXMLHttpRequest()); + new Assertion(fn, msg, assert.changesButNotBy, true) + .to.change(obj, prop).but.not.by(delta); + }; + + /** + * ### .increases(function, object, property, [message]) + * + * Asserts that a function increases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 13 }; + * assert.increases(fn, obj, 'val'); + * + * @name increases + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - // Note that for FakeXMLHttpRequest to work pre ES5 - // we lose some of the alignment with the spec. - // To ensure as close a match as possible, - // set responseType before calling open, send or respond; - function FakeXMLHttpRequest(config) { - EventTargetHandler.call(this); - this.readyState = FakeXMLHttpRequest.UNSENT; - this.requestHeaders = {}; - this.requestBody = null; - this.status = 0; - this.statusText = ""; - this.upload = new EventTargetHandler(); - this.responseType = ""; - this.response = ""; - this.logError = configureLogError(config); + assert.increases = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } - if (sinonXhr.supportsTimeout) { - this.timeout = 0; - } + return new Assertion(fn, msg, assert.increases, true) + .to.increase(obj, prop); + }; - if (sinonXhr.supportsCORS) { - this.withCredentials = false; - } + /** + * ### .increasesBy(function, object, property, delta, [message]) + * + * Asserts that a function increases a numeric object property or a function's return value by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 10 }; + * assert.increasesBy(fn, obj, 'val', 10); + * + * @name increasesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - if (typeof FakeXMLHttpRequest.onCreate === "function") { - FakeXMLHttpRequest.onCreate(this); - } + assert.increasesBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; } - function verifyState(xhr) { - if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { - throw new Error("INVALID_STATE_ERR"); - } + new Assertion(fn, msg, assert.increasesBy, true) + .to.increase(obj, prop).by(delta); + }; - if (xhr.sendFlag) { - throw new Error("INVALID_STATE_ERR"); - } + /** + * ### .doesNotIncrease(function, object, property, [message]) + * + * Asserts that a function does not increase a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 8 }; + * assert.doesNotIncrease(fn, obj, 'val'); + * + * @name doesNotIncrease + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotIncrease = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; } - // largest arity in XHR is 5 - XHR#open - var apply = function(obj, method, args) { - switch (args.length) { - case 0: - return obj[method](); - case 1: - return obj[method](args[0]); - case 2: - return obj[method](args[0], args[1]); - case 3: - return obj[method](args[0], args[1], args[2]); - case 4: - return obj[method](args[0], args[1], args[2], args[3]); - case 5: - return obj[method](args[0], args[1], args[2], args[3], args[4]); - default: - throw new Error("Unhandled case"); - } - }; + return new Assertion(fn, msg, assert.doesNotIncrease, true) + .to.not.increase(obj, prop); + }; - FakeXMLHttpRequest.filters = []; - FakeXMLHttpRequest.addFilter = function addFilter(fn) { - this.filters.push(fn); - }; - FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) { - var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap + /** + * ### .increasesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not increase a numeric object property or function's return value by an amount (delta). + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.increasesButNotBy(fn, obj, 'val', 10); + * + * @name increasesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - [ - "open", - "setRequestHeader", - "abort", - "getResponseHeader", - "getAllResponseHeaders", - "addEventListener", - "overrideMimeType", - "removeEventListener" - ].forEach(function(method) { - fakeXhr[method] = function() { - return apply(xhr, method, arguments); - }; - }); + assert.increasesButNotBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; + } - fakeXhr.send = function() { - // Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute - if (xhr.responseType !== fakeXhr.responseType) { - xhr.responseType = fakeXhr.responseType; - } - return apply(xhr, "send", arguments); - }; + new Assertion(fn, msg, assert.increasesButNotBy, true) + .to.increase(obj, prop).but.not.by(delta); + }; - var copyAttrs = function(args) { - args.forEach(function(attr) { - fakeXhr[attr] = xhr[attr]; - }); - }; + /** + * ### .decreases(function, object, property, [message]) + * + * Asserts that a function decreases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreases(fn, obj, 'val'); + * + * @name decreases + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - var stateChangeStart = function() { - fakeXhr.readyState = xhr.readyState; - if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) { - copyAttrs(["status", "statusText"]); - } - if (xhr.readyState >= FakeXMLHttpRequest.LOADING) { - copyAttrs(["response"]); - if (xhr.responseType === "" || xhr.responseType === "text") { - copyAttrs(["responseText"]); - } - } - if ( - xhr.readyState === FakeXMLHttpRequest.DONE && - (xhr.responseType === "" || xhr.responseType === "document") - ) { - copyAttrs(["responseXML"]); - } - }; + assert.decreases = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } - var stateChangeEnd = function() { - if (fakeXhr.onreadystatechange) { - // eslint-disable-next-line no-useless-call - fakeXhr.onreadystatechange.call(fakeXhr, { - target: fakeXhr, - currentTarget: fakeXhr - }); - } - }; + return new Assertion(fn, msg, assert.decreases, true) + .to.decrease(obj, prop); + }; - var stateChange = function stateChange() { - stateChangeStart(); - stateChangeEnd(); - }; + /** + * ### .decreasesBy(function, object, property, delta, [message]) + * + * Asserts that a function decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val -= 5 }; + * assert.decreasesBy(fn, obj, 'val', 5); + * + * @name decreasesBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - if (xhr.addEventListener) { - xhr.addEventListener("readystatechange", stateChangeStart); + assert.decreasesBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; + } - Object.keys(fakeXhr.eventListeners).forEach(function(event) { - /*eslint-disable no-loop-func*/ - fakeXhr.eventListeners[event].forEach(function(handler) { - xhr.addEventListener(event, handler.listener, { - capture: handler.capture, - once: handler.once - }); - }); - /*eslint-enable no-loop-func*/ - }); + new Assertion(fn, msg, assert.decreasesBy, true) + .to.decrease(obj, prop).by(delta); + }; - xhr.addEventListener("readystatechange", stateChangeEnd); - } else { - xhr.onreadystatechange = stateChange; - } - apply(xhr, "open", xhrArgs); - }; - FakeXMLHttpRequest.useFilters = false; + /** + * ### .doesNotDecrease(function, object, property, [message]) + * + * Asserts that a function does not decreases a numeric object property. + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.doesNotDecrease(fn, obj, 'val'); + * + * @name doesNotDecrease + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - function verifyRequestOpened(xhr) { - if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { - const errorMessage = - xhr.readyState === FakeXMLHttpRequest.UNSENT - ? "INVALID_STATE_ERR - you might be trying to set the request state for a request that has already been aborted, it is recommended to check 'readyState' first..." - : `INVALID_STATE_ERR - ${xhr.readyState}`; - throw new Error(errorMessage); - } + assert.doesNotDecrease = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; } - function verifyRequestSent(xhr) { - if (xhr.readyState === FakeXMLHttpRequest.DONE) { - throw new Error("Request done"); - } + return new Assertion(fn, msg, assert.doesNotDecrease, true) + .to.not.decrease(obj, prop); + }; + + /** + * ### .doesNotDecreaseBy(function, object, property, delta, [message]) + * + * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.doesNotDecreaseBy(fn, obj, 'val', 1); + * + * @name doesNotDecreaseBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.doesNotDecreaseBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; } - function verifyHeadersReceived(xhr) { - if ( - xhr.async && - xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED - ) { - throw new Error("No headers received"); - } + return new Assertion(fn, msg, assert.doesNotDecreaseBy, true) + .to.not.decrease(obj, prop).by(delta); + }; + + /** + * ### .decreasesButNotBy(function, object, property, delta, [message]) + * + * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta) + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreasesButNotBy(fn, obj, 'val', 1); + * + * @name decreasesButNotBy + * @param {Function} modifier function + * @param {Object} object or getter function + * @param {String} property name _optional_ + * @param {Number} change amount (delta) + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.decreasesButNotBy = function (fn, obj, prop, delta, msg) { + if (arguments.length === 4 && typeof obj === 'function') { + var tmpMsg = delta; + delta = prop; + msg = tmpMsg; + } else if (arguments.length === 3) { + delta = prop; + prop = null; } - function convertResponseBody(responseType, contentType, body) { - if (responseType === "" || responseType === "text") { - return body; - } else if (supportsArrayBuffer && responseType === "arraybuffer") { - return convertToArrayBuffer(body); - } else if (responseType === "json") { - try { - return JSON.parse(body); - } catch (e) { - // Return parsing failure as null - return null; - } - } else if (supportsBlob && responseType === "blob") { - if (body instanceof Blob) { - return body; - } + new Assertion(fn, msg, assert.decreasesButNotBy, true) + .to.decrease(obj, prop).but.not.by(delta); + }; + + /*! + * ### .ifError(object) + * + * Asserts if value is not a false value, and throws if it is a true value. + * This is added to allow for chai to be a drop-in replacement for Node's + * assert class. + * + * var err = new Error('I am a custom error'); + * assert.ifError(err); // Rethrows err! + * + * @name ifError + * @param {Object} object + * @namespace Assert + * @api public + */ + + assert.ifError = function (val) { + if (val) { + throw(val); + } + }; + + /** + * ### .isExtensible(object) + * + * Asserts that `object` is extensible (can have new properties added to it). + * + * assert.isExtensible({}); + * + * @name isExtensible + * @alias extensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isExtensible = function (obj, msg) { + new Assertion(obj, msg, assert.isExtensible, true).to.be.extensible; + }; + + /** + * ### .isNotExtensible(object) + * + * Asserts that `object` is _not_ extensible. + * + * var nonExtensibleObject = Object.preventExtensions({}); + * var sealedObject = Object.seal({}); + * var frozenObject = Object.freeze({}); + * + * assert.isNotExtensible(nonExtensibleObject); + * assert.isNotExtensible(sealedObject); + * assert.isNotExtensible(frozenObject); + * + * @name isNotExtensible + * @alias notExtensible + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ + + assert.isNotExtensible = function (obj, msg) { + new Assertion(obj, msg, assert.isNotExtensible, true).to.not.be.extensible; + }; + + /** + * ### .isSealed(object) + * + * Asserts that `object` is sealed (cannot have new properties added to it + * and its existing properties cannot be removed). + * + * var sealedObject = Object.seal({}); + * var frozenObject = Object.seal({}); + * + * assert.isSealed(sealedObject); + * assert.isSealed(frozenObject); + * + * @name isSealed + * @alias sealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - var blobOptions = {}; - if (contentType) { - blobOptions.type = contentType; - } - return new Blob([convertToArrayBuffer(body)], blobOptions); - } else if (responseType === "document") { - if (isXmlContentType(contentType)) { - return FakeXMLHttpRequest.parseXML(body); - } - return null; - } - throw new Error(`Invalid responseType ${responseType}`); - } + assert.isSealed = function (obj, msg) { + new Assertion(obj, msg, assert.isSealed, true).to.be.sealed; + }; - /** - * Steps to follow when there is an error, according to: - * https://xhr.spec.whatwg.org/#request-error-steps - */ - function requestErrorSteps(xhr) { - clearResponse(xhr); - xhr.errorFlag = true; - xhr.requestHeaders = {}; - xhr.responseHeaders = {}; + /** + * ### .isNotSealed(object) + * + * Asserts that `object` is _not_ sealed. + * + * assert.isNotSealed({}); + * + * @name isNotSealed + * @alias notSealed + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - if ( - xhr.readyState !== FakeXMLHttpRequest.UNSENT && - xhr.sendFlag && - xhr.readyState !== FakeXMLHttpRequest.DONE - ) { - xhr.readyStateChange(FakeXMLHttpRequest.DONE); - xhr.sendFlag = false; - } - } + assert.isNotSealed = function (obj, msg) { + new Assertion(obj, msg, assert.isNotSealed, true).to.not.be.sealed; + }; - FakeXMLHttpRequest.parseXML = function parseXML(text) { - // Treat empty string as parsing failure - if (text !== "") { - try { - if (typeof DOMParser !== "undefined") { - var parser = new DOMParser(); - var parsererrorNS = ""; + /** + * ### .isFrozen(object) + * + * Asserts that `object` is frozen (cannot have new properties added to it + * and its existing properties cannot be modified). + * + * var frozenObject = Object.freeze({}); + * assert.frozen(frozenObject); + * + * @name isFrozen + * @alias frozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - try { - var parsererrors = parser - .parseFromString("INVALID", "text/xml") - .getElementsByTagName("parsererror"); - if (parsererrors.length) { - parsererrorNS = parsererrors[0].namespaceURI; - } - } catch (e) { - // passing invalid XML makes IE11 throw - // so no namespace needs to be determined - } + assert.isFrozen = function (obj, msg) { + new Assertion(obj, msg, assert.isFrozen, true).to.be.frozen; + }; - var result; - try { - result = parser.parseFromString(text, "text/xml"); - } catch (err) { - return null; - } + /** + * ### .isNotFrozen(object) + * + * Asserts that `object` is _not_ frozen. + * + * assert.isNotFrozen({}); + * + * @name isNotFrozen + * @alias notFrozen + * @param {Object} object + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - return result.getElementsByTagNameNS( - parsererrorNS, - "parsererror" - ).length - ? null - : result; - } - var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); - xmlDoc.async = "false"; - xmlDoc.loadXML(text); - return xmlDoc.parseError.errorCode !== 0 ? null : xmlDoc; - } catch (e) { - // Unable to parse XML - no biggie - } - } + assert.isNotFrozen = function (obj, msg) { + new Assertion(obj, msg, assert.isNotFrozen, true).to.not.be.frozen; + }; - return null; - }; + /** + * ### .isEmpty(target) + * + * Asserts that the target does not contain any values. + * For arrays and strings, it checks the `length` property. + * For `Map` and `Set` instances, it checks the `size` property. + * For non-function objects, it gets the count of own + * enumerable string keys. + * + * assert.isEmpty([]); + * assert.isEmpty(''); + * assert.isEmpty(new Map); + * assert.isEmpty({}); + * + * @name isEmpty + * @alias empty + * @param {Object|Array|String|Map|Set} target + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - FakeXMLHttpRequest.statusCodes = { - 100: "Continue", - 101: "Switching Protocols", - 200: "OK", - 201: "Created", - 202: "Accepted", - 203: "Non-Authoritative Information", - 204: "No Content", - 205: "Reset Content", - 206: "Partial Content", - 207: "Multi-Status", - 300: "Multiple Choice", - 301: "Moved Permanently", - 302: "Found", - 303: "See Other", - 304: "Not Modified", - 305: "Use Proxy", - 307: "Temporary Redirect", - 400: "Bad Request", - 401: "Unauthorized", - 402: "Payment Required", - 403: "Forbidden", - 404: "Not Found", - 405: "Method Not Allowed", - 406: "Not Acceptable", - 407: "Proxy Authentication Required", - 408: "Request Timeout", - 409: "Conflict", - 410: "Gone", - 411: "Length Required", - 412: "Precondition Failed", - 413: "Request Entity Too Large", - 414: "Request-URI Too Long", - 415: "Unsupported Media Type", - 416: "Requested Range Not Satisfiable", - 417: "Expectation Failed", - 422: "Unprocessable Entity", - 500: "Internal Server Error", - 501: "Not Implemented", - 502: "Bad Gateway", - 503: "Service Unavailable", - 504: "Gateway Timeout", - 505: "HTTP Version Not Supported" - }; + assert.isEmpty = function(val, msg) { + new Assertion(val, msg, assert.isEmpty, true).to.be.empty; + }; - extend(FakeXMLHttpRequest.prototype, sinonEvent.EventTarget, { - async: true, + /** + * ### .isNotEmpty(target) + * + * Asserts that the target contains values. + * For arrays and strings, it checks the `length` property. + * For `Map` and `Set` instances, it checks the `size` property. + * For non-function objects, it gets the count of own + * enumerable string keys. + * + * assert.isNotEmpty([1, 2]); + * assert.isNotEmpty('34'); + * assert.isNotEmpty(new Set([5, 6])); + * assert.isNotEmpty({ key: 7 }); + * + * @name isNotEmpty + * @alias notEmpty + * @param {Object|Array|String|Map|Set} target + * @param {String} message _optional_ + * @namespace Assert + * @api public + */ - open: function open(method, url, async, username, password) { - this.method = method; - this.url = url; - this.async = typeof async === "boolean" ? async : true; - this.username = username; - this.password = password; - clearResponse(this); - this.requestHeaders = {}; - this.sendFlag = false; + assert.isNotEmpty = function(val, msg) { + new Assertion(val, msg, assert.isNotEmpty, true).to.not.be.empty; + }; - if (FakeXMLHttpRequest.useFilters === true) { - var xhrArgs = arguments; - var defake = FakeXMLHttpRequest.filters.some(function(filter) { - return filter.apply(this, xhrArgs); - }); - if (defake) { - FakeXMLHttpRequest.defake(this, arguments); - return; - } - } - this.readyStateChange(FakeXMLHttpRequest.OPENED); - }, + /*! + * Aliases. + */ - readyStateChange: function readyStateChange(state) { - this.readyState = state; + (function alias(name, as){ + assert[as] = assert[name]; + return alias; + }) + ('isOk', 'ok') + ('isNotOk', 'notOk') + ('throws', 'throw') + ('throws', 'Throw') + ('isExtensible', 'extensible') + ('isNotExtensible', 'notExtensible') + ('isSealed', 'sealed') + ('isNotSealed', 'notSealed') + ('isFrozen', 'frozen') + ('isNotFrozen', 'notFrozen') + ('isEmpty', 'empty') + ('isNotEmpty', 'notEmpty'); + }; - var readyStateChangeEvent = new sinonEvent.Event( - "readystatechange", - false, - false, - this - ); - if (typeof this.onreadystatechange === "function") { - try { - this.onreadystatechange(readyStateChangeEvent); - } catch (e) { - this.logError("Fake XHR onreadystatechange handler", e); - } - } + /*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ - if (this.readyState !== FakeXMLHttpRequest.DONE) { - this.dispatchEvent(readyStateChangeEvent); - } else { - var event, progress; + var hasRequiredChai; - if (this.timedOut || this.aborted || this.status === 0) { - progress = { loaded: 0, total: 0 }; - event = - (this.timedOut && "timeout") || - (this.aborted && "abort") || - "error"; - } else { - progress = { loaded: 100, total: 100 }; - event = "load"; - } + function requireChai () { + if (hasRequiredChai) return chai$2; + hasRequiredChai = 1; + (function (exports) { + var used = []; - if (supportsProgress) { - this.upload.dispatchEvent( - new sinonEvent.ProgressEvent("progress", progress, this) - ); - this.upload.dispatchEvent( - new sinonEvent.ProgressEvent(event, progress, this) - ); - this.upload.dispatchEvent( - new sinonEvent.ProgressEvent("loadend", progress, this) - ); - } + /*! + * Chai version + */ - this.dispatchEvent( - new sinonEvent.ProgressEvent("progress", progress, this) - ); - this.dispatchEvent( - new sinonEvent.ProgressEvent(event, progress, this) - ); - this.dispatchEvent(readyStateChangeEvent); - this.dispatchEvent( - new sinonEvent.ProgressEvent("loadend", progress, this) - ); - } - }, + exports.version = '4.3.8'; - // Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method - setRequestHeader: function setRequestHeader(header, value) { - if (typeof value !== "string") { - throw new TypeError( - `By RFC7230, section 3.2.4, header values should be strings. Got ${typeof value}` - ); - } - verifyState(this); + /*! + * Assertion Error + */ - var checkUnsafeHeaders = true; - if (typeof this.unsafeHeadersEnabled === "function") { - checkUnsafeHeaders = this.unsafeHeadersEnabled(); - } + exports.AssertionError = assertionError; - if ( - checkUnsafeHeaders && - (getHeader(unsafeHeaders, header) !== null || - /^(Sec-|Proxy-)/i.test(header)) - ) { - throw new Error( - // eslint-disable-next-line quotes - `Refused to set unsafe header "${header}"` - ); - } + /*! + * Utils for plugins (not exported) + */ + + var util = requireUtils(); - // eslint-disable-next-line no-param-reassign - value = normalizeHeaderValue(value); + /** + * # .use(function) + * + * Provides a way to extend the internals of Chai. + * + * @param {Function} + * @returns {this} for chaining + * @api public + */ - var existingHeader = getHeader(this.requestHeaders, header); - if (existingHeader) { - this.requestHeaders[existingHeader] += `, ${value}`; - } else { - this.requestHeaders[header] = value; - } - }, + exports.use = function (fn) { + if (!~used.indexOf(fn)) { + fn(exports, util); + used.push(fn); + } - setStatus: function setStatus(status) { - var sanitizedStatus = typeof status === "number" ? status : 200; + return exports; + }; - verifyRequestOpened(this); - this.status = sanitizedStatus; - this.statusText = FakeXMLHttpRequest.statusCodes[sanitizedStatus]; - }, + /*! + * Utility Functions + */ - // Helps testing - setResponseHeaders: function setResponseHeaders(headers) { - verifyRequestOpened(this); + exports.util = util; - var responseHeaders = (this.responseHeaders = {}); + /*! + * Configuration + */ - Object.keys(headers).forEach(function(header) { - responseHeaders[header] = headers[header]; - }); + var config = config$5; + exports.config = config; - if (this.async) { - this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); - } else { - this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; - } - }, + /*! + * Primary `Assertion` prototype + */ - // Currently treats ALL data as a DOMString (i.e. no Document) - send: function send(data) { - verifyState(this); + var assertion$1 = assertion; + exports.use(assertion$1); - if (!/^(head)$/i.test(this.method)) { - var contentType = getHeader( - this.requestHeaders, - "Content-Type" - ); - if (this.requestHeaders[contentType]) { - var value = this.requestHeaders[contentType].split(";"); - this.requestHeaders[ - contentType - ] = `${value[0]};charset=utf-8`; - } else if (supportsFormData && !(data instanceof FormData)) { - this.requestHeaders["Content-Type"] = - "text/plain;charset=utf-8"; - } + /*! + * Core Assertions + */ - this.requestBody = data; + var core = assertions; + exports.use(core); + + /*! + * Expect interface + */ + + var expect = expect$1; + exports.use(expect); + + /*! + * Should interface + */ + + var should$1 = should; + exports.use(should$1); + + /*! + * Assert interface + */ + + var assert$1 = assert; + exports.use(assert$1); + } (chai$2)); + return chai$2; + } + + var chai = requireChai(); + + var chai$1 = /*@__PURE__*/getDefaultExportFromCjs(chai); + + const expect = chai$1.expect; + chai$1.version; + chai$1.Assertion; + chai$1.AssertionError; + chai$1.util; + chai$1.config; + chai$1.use; + chai$1.should; + chai$1.assert; + chai$1.core; + + // TODO: This file is no longer the server model because the web SDK payload + var MessageType = Types.MessageType; + var ApplicationTransitionType = Types.ApplicationTransitionType; + // TODO: Make this a pure function that returns a new object + function convertCustomFlags(event, dto) { + var valueArray = []; + dto.flags = {}; + for (var prop in event.CustomFlags) { + valueArray = []; + if (event.CustomFlags.hasOwnProperty(prop)) { + if (Array.isArray(event.CustomFlags[prop])) { + event.CustomFlags[prop].forEach(function (customFlagProperty) { + // TODO: Can we use our utility functions here? + if (typeof customFlagProperty === 'number' || typeof customFlagProperty === 'string' || typeof customFlagProperty === 'boolean') { + valueArray.push(customFlagProperty.toString()); + } + }); + } else if ( + // TODO: Can we use our utility functions here? + typeof event.CustomFlags[prop] === 'number' || typeof event.CustomFlags[prop] === 'string' || typeof event.CustomFlags[prop] === 'boolean') { + valueArray.push(event.CustomFlags[prop].toString()); + } + if (valueArray.length) { + dto.flags[prop] = valueArray; + } + } + } + } + function convertProductToV2DTO(product) { + return { + id: parseStringOrNumber(product.Sku), + nm: parseStringOrNumber(product.Name), + pr: parseNumber(product.Price), + qt: parseNumber(product.Quantity), + br: parseStringOrNumber(product.Brand), + va: parseStringOrNumber(product.Variant), + ca: parseStringOrNumber(product.Category), + ps: parseNumber(product.Position), + cc: parseStringOrNumber(product.CouponCode), + tpa: parseNumber(product.TotalAmount), + attrs: product.Attributes + }; + } + function convertProductListToV2DTO(productList) { + if (!productList) { + return []; + } + return productList.map(function (product) { + return convertProductToV2DTO(product); + }); + } + function ServerModel$1(mpInstance) { + var self = this; + // TODO: Can we refactor this to not mutate the event? + this.appendUserInfo = function (user, event) { + if (!event) { + return; + } + if (!user) { + event.MPID = null; + event.ConsentState = null; + event.UserAttributes = null; + event.UserIdentities = null; + return; + } + if (event.MPID && event.MPID === user.getMPID()) { + return; + } + event.MPID = user.getMPID(); + event.ConsentState = user.getConsentState(); + event.UserAttributes = user.getAllUserAttributes(); + var userIdentities = user.getUserIdentities().userIdentities; + var dtoUserIdentities = {}; + for (var identityKey in userIdentities) { + var identityType = Types.IdentityType.getIdentityType(identityKey); + if (identityType !== false) { + dtoUserIdentities[identityType] = userIdentities[identityKey]; + } + } + var validUserIdentities = []; + if (mpInstance._Helpers.isObject(dtoUserIdentities)) { + if (Object.keys(dtoUserIdentities).length) { + for (var key in dtoUserIdentities) { + var userIdentity = {}; + userIdentity.Identity = dtoUserIdentities[key]; + userIdentity.Type = mpInstance._Helpers.parseNumber(key); + validUserIdentities.push(userIdentity); + } + } + } + event.UserIdentities = validUserIdentities; + }; + this.convertToConsentStateV2DTO = function (state) { + if (!state) { + return null; + } + var jsonObject = {}; + var gdprConsentState = state.getGDPRConsentState(); + if (gdprConsentState) { + var gdpr = {}; + jsonObject.gdpr = gdpr; + for (var purpose in gdprConsentState) { + if (gdprConsentState.hasOwnProperty(purpose)) { + var gdprConsent = gdprConsentState[purpose]; + jsonObject.gdpr[purpose] = {}; + if (typeof gdprConsent.Consented === 'boolean') { + gdpr[purpose].c = gdprConsent.Consented; + } + if (typeof gdprConsent.Timestamp === 'number') { + gdpr[purpose].ts = gdprConsent.Timestamp; + } + if (typeof gdprConsent.ConsentDocument === 'string') { + gdpr[purpose].d = gdprConsent.ConsentDocument; + } + if (typeof gdprConsent.Location === 'string') { + gdpr[purpose].l = gdprConsent.Location; + } + if (typeof gdprConsent.HardwareId === 'string') { + gdpr[purpose].h = gdprConsent.HardwareId; + } + } + } + } + var ccpaConsentState = state.getCCPAConsentState(); + if (ccpaConsentState) { + jsonObject.ccpa = { + data_sale_opt_out: { + c: ccpaConsentState.Consented, + ts: ccpaConsentState.Timestamp, + d: ccpaConsentState.ConsentDocument, + l: ccpaConsentState.Location, + h: ccpaConsentState.HardwareId + } + }; + } + return jsonObject; + }; + this.createEventObject = function (event, user) { + var uploadObject = {}; + var eventObject = {}; + // The `optOut` variable is passed later in this method to the `uploadObject` + // so that it can be used to denote whether or not a user has "opted out" of being + // tracked. If this is an `optOut` Event, we set `optOut` to the inverse of the SDK's + // `isEnabled` boolean which is controlled via `MPInstanceManager.setOptOut`. + var optOut = event.messageType === Types.MessageType.OptOut ? !mpInstance._Store.isEnabled : null; + // TODO: Why is Webview Bridge Enabled or Opt Out necessary here? + if (mpInstance._Store.sessionId || event.messageType === Types.MessageType.OptOut || mpInstance._Store.webviewBridgeEnabled) { + if (event.hasOwnProperty('toEventAPIObject')) { + eventObject = event.toEventAPIObject(); + } else { + eventObject = { + // This is an artifact from v2 events where SessionStart/End and AST event + // names are numbers (1, 2, or 10), but going forward with v3, these lifecycle + // events do not have names, but are denoted by their `event_type` + EventName: event.name || event.messageType, + EventCategory: event.eventType, + EventAttributes: mpInstance._Helpers.sanitizeAttributes(event.data, event.name), + SourceMessageId: event.sourceMessageId || mpInstance._Helpers.generateUniqueId(), + EventDataType: event.messageType, + CustomFlags: event.customFlags || {}, + UserAttributeChanges: event.userAttributeChanges, + UserIdentityChanges: event.userIdentityChanges + }; + } + // TODO: Should we move this side effect outside of this method? + if (event.messageType !== Types.MessageType.SessionEnd) { + mpInstance._Store.dateLastEventSent = new Date(); + } + uploadObject = { + // FIXME: Deprecate when we get rid of V2 + Store: mpInstance._Store.serverSettings, + SDKVersion: Constants.sdkVersion, + SessionId: mpInstance._Store.sessionId, + SessionStartDate: mpInstance._Store.sessionStartDate ? mpInstance._Store.sessionStartDate.getTime() : 0, + Debug: mpInstance._Store.SDKConfig.isDevelopmentMode, + Location: mpInstance._Store.currentPosition, + OptOut: optOut, + ExpandedEventCount: 0, + AppVersion: mpInstance.getAppVersion(), + AppName: mpInstance.getAppName(), + Package: mpInstance._Store.SDKConfig["package"], + ClientGeneratedId: mpInstance._Store.clientId, + DeviceId: mpInstance._Store.deviceId, + IntegrationAttributes: mpInstance._Store.integrationAttributes, + CurrencyCode: mpInstance._Store.currencyCode, + DataPlan: mpInstance._Store.SDKConfig.dataPlan ? mpInstance._Store.SDKConfig.dataPlan : {} + }; + if (eventObject.EventDataType === MessageType.AppStateTransition) { + eventObject.IsFirstRun = mpInstance._Store.isFirstRun; + eventObject.LaunchReferral = window.location.href || null; + } + // FIXME: Remove duplicate occurence + eventObject.CurrencyCode = mpInstance._Store.currencyCode; + var currentUser = user || mpInstance.Identity.getCurrentUser(); + self.appendUserInfo(currentUser, eventObject); + if (event.messageType === Types.MessageType.SessionEnd) { + eventObject.SessionLength = mpInstance._Store.dateLastEventSent.getTime() - mpInstance._Store.sessionStartDate.getTime(); + eventObject.currentSessionMPIDs = mpInstance._Store.currentSessionMPIDs; + // Session attributes are assigned on a session level, but only uploaded + // when a session ends. As there is no way to attach event attributes to + // a `SessionEnd` event, we are uploading the session level attributes + // as event level attributes in a `SessionEnd` event. + eventObject.EventAttributes = mpInstance._Store.sessionAttributes; + // TODO: We should move this out of here to avoid side effects + mpInstance._Store.currentSessionMPIDs = []; + mpInstance._Store.sessionStartDate = null; + } + uploadObject.Timestamp = mpInstance._Store.dateLastEventSent.getTime(); + return mpInstance._Helpers.extend({}, eventObject, uploadObject); + } + return null; + }; + this.convertEventToV2DTO = function (event) { + var dto = { + n: event.EventName, + et: event.EventCategory, + ua: event.UserAttributes, + ui: event.UserIdentities, + ia: event.IntegrationAttributes, + str: event.Store, + attrs: event.EventAttributes, + sdk: event.SDKVersion, + sid: event.SessionId, + sl: event.SessionLength, + ssd: event.SessionStartDate, + dt: event.EventDataType, + dbg: event.Debug, + ct: event.Timestamp, + lc: event.Location, + o: event.OptOut, + eec: event.ExpandedEventCount, + av: event.AppVersion, + cgid: event.ClientGeneratedId, + das: event.DeviceId, + mpid: event.MPID, + smpids: event.currentSessionMPIDs + }; + if (event.DataPlan && event.DataPlan.PlanId) { + dto.dp_id = event.DataPlan.PlanId; + if (event.DataPlan.PlanVersion) { + dto.dp_v = event.DataPlan.PlanVersion; + } + } + var consent = self.convertToConsentStateV2DTO(event.ConsentState); + if (consent) { + dto.con = consent; + } + if (event.EventDataType === MessageType.AppStateTransition) { + dto.fr = event.IsFirstRun; + dto.iu = false; + dto.at = ApplicationTransitionType.AppInit; + dto.lr = event.LaunchReferral; + // Nullify Attributes in case AST Was logged manually or + // via logBaseEvent. AST should not have any attributes + dto.attrs = null; + } + if (event.CustomFlags) { + convertCustomFlags(event, dto); + } + if (event.EventDataType === MessageType.Commerce) { + dto.cu = event.CurrencyCode; + // TODO: If Cart is deprecated, we should deprecate this too + if (event.ShoppingCart) { + dto.sc = { + pl: convertProductListToV2DTO(event.ShoppingCart.ProductList) + }; + } + if (event.ProductAction) { + dto.pd = { + an: event.ProductAction.ProductActionType, + cs: mpInstance._Helpers.parseNumber(event.ProductAction.CheckoutStep), + co: event.ProductAction.CheckoutOptions, + pl: convertProductListToV2DTO(event.ProductAction.ProductList), + ti: event.ProductAction.TransactionId, + ta: event.ProductAction.Affiliation, + tcc: event.ProductAction.CouponCode, + tr: mpInstance._Helpers.parseNumber(event.ProductAction.TotalAmount), + ts: mpInstance._Helpers.parseNumber(event.ProductAction.ShippingAmount), + tt: mpInstance._Helpers.parseNumber(event.ProductAction.TaxAmount) + }; + } else if (event.PromotionAction) { + dto.pm = { + an: event.PromotionAction.PromotionActionType, + pl: event.PromotionAction.PromotionList.map(function (promotion) { + return { + id: promotion.Id, + nm: promotion.Name, + cr: promotion.Creative, + ps: promotion.Position ? promotion.Position : 0 + }; + }) + }; + } else if (event.ProductImpressions) { + dto.pi = event.ProductImpressions.map(function (impression) { + return { + pil: impression.ProductImpressionList, + pl: convertProductListToV2DTO(impression.ProductList) + }; + }); + } + } else if (event.EventDataType === MessageType.Profile) { + dto.pet = event.ProfileMessageType; + } + return dto; + }; + } + + // This file is used ONLY for the mParticle ESLint plugin. It should NOT be used otherwise! + var mockFunction = function mockFunction() { + return null; + }; + var _BatchValidator = /** @class */function () { + function _BatchValidator() {} + _BatchValidator.prototype.getMPInstance = function () { + return { + // Certain Helper, Store, and Identity properties need to be mocked to be used in the `returnBatch` method + _Helpers: { + sanitizeAttributes: window.mParticle.getInstance()._Helpers.sanitizeAttributes, + generateHash: function generateHash() { + return 'mockHash'; + }, + generateUniqueId: function generateUniqueId() { + return 'mockId'; + }, + extend: window.mParticle.getInstance()._Helpers.extend, + createServiceUrl: mockFunction, + parseNumber: mockFunction, + isObject: mockFunction, + returnConvertedBoolean: mockFunction, + Validators: null + }, + _resetForTests: mockFunction, + _APIClient: null, + MPSideloadedKit: null, + _Consent: null, + _Events: null, + _Forwarders: null, + _NativeSdkHelpers: null, + _Persistence: null, + _preInit: null, + Consent: null, + _ServerModel: null, + _SessionManager: null, + _Store: { + sessionId: 'mockSessionId', + sideloadedKits: [], + devToken: 'test_dev_token', + isFirstRun: true, + isEnabled: true, + sessionAttributes: {}, + currentSessionMPIDs: [], + consentState: null, + clientId: null, + deviceId: null, + serverSettings: {}, + dateLastEventSent: null, + sessionStartDate: null, + currentPosition: null, + isTracking: false, + watchPositionId: null, + cartProducts: [], + eventQueue: [], + currencyCode: null, + globalTimer: null, + context: null, + configurationLoaded: false, + identityCallInFlight: false, + nonCurrentUserMPIDs: {}, + identifyCalled: false, + isLoggedIn: false, + cookieSyncDates: {}, + integrationAttributes: {}, + requireDelay: true, + isLocalStorageAvailable: null, + integrationDelayTimeoutStart: null, + storageName: null, + prodStorageName: null, + activeForwarders: [], + kits: {}, + configuredForwarders: [], + pixelConfigurations: [], + wrapperSDKInfo: { + name: 'none', + version: null, + isInfoSet: false + }, + SDKConfig: { + isDevelopmentMode: false, + onCreateBatch: mockFunction + } + }, + config: null, + eCommerce: null, + Identity: { + getCurrentUser: mockFunction, + IdentityAPI: {}, + identify: mockFunction, + login: mockFunction, + logout: mockFunction, + modify: mockFunction + }, + Logger: { + verbose: mockFunction, + error: mockFunction, + warning: mockFunction + }, + ProductActionType: null, + ServerModel: null, + addForwarder: mockFunction, + generateHash: mockFunction, + getAppVersion: mockFunction, + getAppName: mockFunction, + getInstance: mockFunction, + getDeviceId: mockFunction, + init: mockFunction, + logBaseEvent: mockFunction, + logEvent: mockFunction, + logLevel: 'none', + setPosition: mockFunction, + upload: mockFunction + }; + }; + _BatchValidator.prototype.createSDKEventFunction = function (event) { + return new ServerModel$1(this.getMPInstance()).createEventObject(event); + }; + _BatchValidator.prototype.returnBatch = function (events) { + var _this = this; + var mpInstance = this.getMPInstance(); + var sdkEvents = Array.isArray(events) ? events.map(function (event) { + return _this.createSDKEventFunction(event); + }) : [this.createSDKEventFunction(events)]; + var batch = convertEvents('0', sdkEvents, mpInstance); + return batch; + }; + return _BatchValidator; + }(); + + function Logger(config) { + var self = this; + var logLevel = config.logLevel || 'warning'; + if (config.hasOwnProperty('logger')) { + this.logger = config.logger; + } else { + this.logger = new ConsoleLogger(); + } + this.verbose = function (msg) { + if (logLevel !== 'none') { + if (self.logger.verbose && logLevel === 'verbose') { + self.logger.verbose(msg); + } + } + }; + this.warning = function (msg) { + if (logLevel !== 'none') { + if (self.logger.warning && (logLevel === 'verbose' || logLevel === 'warning')) { + self.logger.warning(msg); + } + } + }; + this.error = function (msg) { + if (logLevel !== 'none') { + if (self.logger.error) { + self.logger.error(msg); + } + } + }; + this.setLogLevel = function (newLogLevel) { + logLevel = newLogLevel; + }; + } + function ConsoleLogger() { + this.verbose = function (msg) { + if (console && console.info) { + console.info(msg); + } + }; + this.error = function (msg) { + if (console && console.error) { + console.error(msg); + } + }; + this.warning = function (msg) { + if (console && console.warn) { + console.warn(msg); + } + }; + } + + var event0 = { + EventName: 'Test Event 0', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + var event1 = { + EventName: 'Test Event 1', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + var event2 = { + EventName: 'Test Event 2', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + var event3 = { + EventName: 'Test Event 3', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + var enableBatchingConfigFlags = { + eventBatchingIntervalMillis: 1000 + }; + describe('batch uploader', function () { + var mockServer; + var clock; + beforeEach(function () { + client.restore(); + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + mockServer.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + }); + afterEach(function () { + mockServer.reset(); + client.restore(); + window.localStorage.clear(); + }); + describe('Unit Tests', function () { + describe('#queueEvent', function () { + it('should add events to the Pending Events Queue', function () { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = new BatchUploader(mpInstance, 1000); + var event = { + EventName: 'Test Event', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + uploader.queueEvent(event); + expect(uploader.eventsQueuedForProcessing.length).to.eql(1); + }); + it('should reject batches without events', function () { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = new BatchUploader(mpInstance, 1000); + uploader.queueEvent(null); + uploader.queueEvent({}); + expect(uploader.eventsQueuedForProcessing).to.eql([]); + expect(uploader.batchesQueuedForProcessing).to.eql([]); + }); + it('should add events in the order they are received', function () { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = new BatchUploader(mpInstance, 1000); + uploader.queueEvent(event1); + uploader.queueEvent(event2); + uploader.queueEvent(event3); + expect(uploader.eventsQueuedForProcessing.length).to.eql(3); + expect(uploader.eventsQueuedForProcessing[0]).to.eql(event1); + expect(uploader.eventsQueuedForProcessing[1]).to.eql(event2); + expect(uploader.eventsQueuedForProcessing[2]).to.eql(event3); + }); + }); + describe('#uploadBatches', function () { + beforeEach(function () { + window.mParticle.config.flags = { + eventBatchingIntervalMillis: 1000 + }; + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + client.restore(); + }); + it('should reject batches without events', function () { + return __awaiter(void 0, void 0, void 0, function () { + var newLogger, mpInstance, uploader, batchValidator, baseEvent, actualBatch, eventlessBatch, actualBatchResult; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + client.post(urls.events, 200); + newLogger = new Logger(window.mParticle.config); + mpInstance = window.mParticle.getInstance(); + uploader = new BatchUploader(mpInstance, 1000); + batchValidator = new _BatchValidator(); + baseEvent = { + messageType: 4, + name: 'testEvent' + }; + actualBatch = batchValidator.returnBatch(baseEvent); + eventlessBatch = batchValidator.returnBatch({}); + // HACK: Directly access uploader to Force an upload + return [4 /*yield*/, uploader.uploadBatches(newLogger, [actualBatch, eventlessBatch], false)]; + case 1: + // HACK: Directly access uploader to Force an upload + _a.sent(); + expect(client.calls().length).to.equal(1); + actualBatchResult = JSON.parse(client.calls()[0][1].body); + expect(actualBatchResult.events.length).to.equal(1); + expect(actualBatchResult.events).to.eql(actualBatch.events); + return [2 /*return*/]; } + }); + }); + }); - this.errorFlag = false; - this.sendFlag = this.async; - clearResponse(this); + it('should return batches that fail to upload with 500 errors', function () { + return __awaiter(void 0, void 0, void 0, function () { + var newLogger, mpInstance, uploader, batchValidator, batch1, batch2, batch3, batchesNotUploaded; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + client.post(urls.events, 500); + newLogger = new Logger(window.mParticle.config); + mpInstance = window.mParticle.getInstance(); + uploader = new BatchUploader(mpInstance, 1000); + batchValidator = new _BatchValidator(); + batch1 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 1' + }); + batch2 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 2' + }); + batch3 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 3' + }); + return [4 /*yield*/, uploader.uploadBatches(newLogger, [batch1, batch2, batch3], false)]; + case 1: + batchesNotUploaded = _a.sent(); + expect(batchesNotUploaded.length, 'Should have 3 uploaded batches').to.equal(3); + expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1'); + expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2'); + expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3'); + return [2 /*return*/]; + } + }); + }); + }); - if (typeof this.onSend === "function") { - this.onSend(this); + it('should return batches that fail to upload with 429 errors', function () { + return __awaiter(void 0, void 0, void 0, function () { + var newLogger, mpInstance, uploader, batchValidator, batch1, batch2, batch3, batchesNotUploaded; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + client.post(urls.events, 429); + newLogger = new Logger(window.mParticle.config); + mpInstance = window.mParticle.getInstance(); + uploader = new BatchUploader(mpInstance, 1000); + batchValidator = new _BatchValidator(); + batch1 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 1' + }); + batch2 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 2' + }); + batch3 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 3' + }); + return [4 /*yield*/, uploader.uploadBatches(newLogger, [batch1, batch2, batch3], false)]; + case 1: + batchesNotUploaded = _a.sent(); + expect(batchesNotUploaded.length, 'Should have 3 uploaded batches').to.equal(3); + expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1'); + expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2'); + expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3'); + return [2 /*return*/]; } + }); + }); + }); - // Only listen if setInterval and Date are a stubbed. - if ( - sinonXhr.supportsTimeout && - typeof setInterval.clock === "object" && - typeof Date.clock === "object" - ) { - var initiatedTime = Date.now(); - var self = this; + it('should return null if batches fail to upload with 401 errors', function () { + return __awaiter(void 0, void 0, void 0, function () { + var newLogger, mpInstance, uploader, batchValidator, batch1, batch2, batch3, batchesNotUploaded; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + client.post(urls.events, 401); + newLogger = new Logger(window.mParticle.config); + mpInstance = window.mParticle.getInstance(); + uploader = new BatchUploader(mpInstance, 1000); + batchValidator = new _BatchValidator(); + batch1 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 1' + }); + batch2 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 2' + }); + batch3 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 3' + }); + return [4 /*yield*/, uploader.uploadBatches(newLogger, [batch1, batch2, batch3], false)]; + case 1: + batchesNotUploaded = _a.sent(); + expect(batchesNotUploaded === null).to.equal(true); + return [2 /*return*/]; + } + }); + }); + }); - // Listen to any possible tick by fake timers and check to see if timeout has - // been exceeded. It's important to note that timeout can be changed while a request - // is in flight, so we must check anytime the end user forces a clock tick to make - // sure timeout hasn't changed. - // https://xhr.spec.whatwg.org/#dfnReturnLink-2 - var clearIntervalId = setInterval(function() { - // Check if the readyState has been reset or is done. If this is the case, there - // should be no timeout. This will also prevent aborted requests and - // fakeServerWithClock from triggering unnecessary responses. - if ( - self.readyState === FakeXMLHttpRequest.UNSENT || - self.readyState === FakeXMLHttpRequest.DONE - ) { - clearInterval(clearIntervalId); - } else if ( - typeof self.timeout === "number" && - self.timeout > 0 - ) { - if (Date.now() >= initiatedTime + self.timeout) { - self.triggerTimeout(); - clearInterval(clearIntervalId); - } - } - }, 1); + it('should return batches that fail to unknown HTTP errors', function () { + return __awaiter(void 0, void 0, void 0, function () { + var newLogger, mpInstance, uploader, batchValidator, batch1, batch2, batch3, batchesNotUploaded; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + client.post(urls.events, 400); + newLogger = new Logger(window.mParticle.config); + mpInstance = window.mParticle.getInstance(); + uploader = new BatchUploader(mpInstance, 1000); + batchValidator = new _BatchValidator(); + batch1 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 1' + }); + batch2 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 2' + }); + batch3 = batchValidator.returnBatch({ + messageType: 4, + name: 'Test Event 3' + }); + return [4 /*yield*/, uploader.uploadBatches(newLogger, [batch1, batch2, batch3], false)]; + case 1: + batchesNotUploaded = _a.sent(); + expect(batchesNotUploaded).to.be.ok; + expect(batchesNotUploaded.length, 'Should have 3 uploaded batches').to.equal(3); + expect(batchesNotUploaded[0].events[0].data.event_name).to.equal('Test Event 1'); + expect(batchesNotUploaded[1].events[0].data.event_name).to.equal('Test Event 2'); + expect(batchesNotUploaded[2].events[0].data.event_name).to.equal('Test Event 3'); + return [2 /*return*/]; } + }); + }); + }); + }); + }); - this.dispatchEvent( - new sinonEvent.Event("loadstart", false, false, this) - ); + describe('Offline Storage Feature Flag', function () { + beforeEach(function () { + sinon$1.restore(); + client.restore(); + mockServer.reset(); + window.localStorage.clear(); + window.sessionStorage.clear(); + }); + afterEach(function () { + sinon$1.restore(); + client.restore(); + mockServer.reset(); + window.localStorage.clear(); + window.sessionStorage.clear(); + }); + it('should use local storage when enabled', function (done) { + window.mParticle.config.flags = { + offlineStorage: '100' + }; + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var getItemSpy = sinon$1.spy(Storage.prototype, 'getItem'); + var setItemSpy = sinon$1.spy(Storage.prototype, 'setItem'); + var mpInstance = window.mParticle.getInstance(); + var uploader = new BatchUploader(mpInstance, 1000); + var event = { + EventName: 'Test Event', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + var expectedEvent = [event]; + uploader.queueEvent(event); + expect(uploader.eventsQueuedForProcessing.length).to.eql(1); + expect(setItemSpy.called).to.eq(true); + expect(setItemSpy.getCall(0).lastArg).to.equal(JSON.stringify(expectedEvent)); + expect(getItemSpy.called).to.eq(true); + expect(getItemSpy.getCall(0).lastArg).to.equal('mprtcl-v4_abcdef-events'); + done(); + }); + it('should not use local storage when disabled', function () { + window.mParticle.config.flags = { + // offlineStorage: '0', // Defaults to 0, but test if not included, just in case + }; + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var getItemSpy = sinon$1.spy(Storage.prototype, 'getItem'); + var setItemSpy = sinon$1.spy(Storage.prototype, 'setItem'); + var mpInstance = window.mParticle.getInstance(); + var uploader = new BatchUploader(mpInstance, 1000); + var event = { + EventName: 'Test Event', + EventAttributes: null, + SourceMessageId: 'test-smid', + EventDataType: 4, + EventCategory: 1, + CustomFlags: {}, + IsFirstRun: false, + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + SDKVersion: 'X.XX.XX', + SessionId: 'test-session-id', + SessionStartDate: 0, + Debug: false, + DeviceId: 'test-device', + Timestamp: 0 + }; + uploader.queueEvent(event); + expect(uploader.eventsQueuedForProcessing.length).to.eql(1); + expect(uploader.eventsQueuedForProcessing[0]).to.eql(event); + expect(setItemSpy.called).to.eq(false); + expect(getItemSpy.called).to.eq(false); + expect(window.localStorage.getItem('mprtcl-v4_abcdef-events')).to.equal(null); + }); + }); + describe('Offline Storage Disabled', function () { + beforeEach(function () { + window.mParticle.config.flags = __assign({ + offlineStorage: '0' + }, enableBatchingConfigFlags); + clock = sinon$1.useFakeTimers({ + now: new Date().getTime() + }); + window.localStorage.clear(); + }); + afterEach(function () { + sinon$1.restore(); + window.localStorage.clear(); + client.restore(); + clock.restore(); + }); + it('should not save events or batches in local storage', function (done) { + var eventStorageKey = 'mprtcl-v4_abcdef-events'; + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + var eventQueue = uploader.eventsQueuedForProcessing; + expect(eventQueue.length).to.equal(3); + expect(window.localStorage.getItem(eventStorageKey), 'Local Storage Events should be empty').to.equal(null); + var batchQueue = uploader.batchesQueuedForProcessing; + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + expect(batchQueue.length).to.equal(2); + expect(window.localStorage.getItem(batchStorageKey), 'Local Storage Batches should be empty').to.equal(null); + done(); + }); + }); + describe('Offline Storage Enabled', function () { + beforeEach(function () { + window.mParticle.config.flags = __assign({ + offlineStorage: '100' + }, enableBatchingConfigFlags); + clock = sinon$1.useFakeTimers({ + now: new Date().getTime() + }); + client.restore(); + window.sessionStorage.clear(); + window.localStorage.clear(); + }); + afterEach(function () { + sinon$1.restore(); + client.restore(); + clock.restore(); + }); + it('should store events in Session Storage in order of creation', function (done) { + var eventStorageKey = 'mprtcl-v4_abcdef-events'; + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + var eventQueue = uploader.eventsQueuedForProcessing; + expect(eventQueue.length).to.equal(3); + var storedEvents = JSON.parse(window.sessionStorage.getItem(eventStorageKey)); + expect(storedEvents.length, 'Local Storage Events').to.equal(3); + expect(storedEvents[0], 'Local Storage: Session Start').to.eql(eventQueue[0]); + expect(storedEvents[1], 'Local Storage: AST').to.eql(eventQueue[1]); + expect(storedEvents[2], 'Local Storage: Test Event 0').to.eql(eventQueue[2]); + done(); + }); + it('should purge events from Session Storage upon Batch Creation', function (done) { + var eventStorageKey = 'mprtcl-v4_abcdef-events'; + client.post(urls.events, 200); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + expect(uploader.eventsQueuedForProcessing.length).to.equal(3); + expect(uploader.batchesQueuedForProcessing.length).to.equal(0); + expect(window.sessionStorage.getItem(eventStorageKey), 'Queued Events should appear in Session Storage').to.be.ok; + expect(JSON.parse(window.sessionStorage.getItem(eventStorageKey)).length).to.equal(3); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // If Session Storage is purged, it should return an empty string + expect(window.sessionStorage.getItem(eventStorageKey)).to.equal(''); + expect(uploader.eventsQueuedForProcessing.length).to.equal(0); + // Batch Queue should be empty because batch successfully uploaded + expect(uploader.batchesQueuedForProcessing.length).to.equal(0); + clock.restore(); + // Call a set timeout to catch the upload so that it does not + // collide with other tests. Unfortunately our setup/teardown + // does not catch async upload attempts + setTimeout(function () { + console.warn('test 2 end'); + done(); + }, 0); + }); + it('should save batches in sequence to Local Storage when an HTTP 500 error is encountered', function (done) { + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + client.post(urls.events, 500); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + clock.restore(); + setTimeout(function () { + expect(window.localStorage.getItem(batchStorageKey)).to.be.ok; + var storedBatches = JSON.parse(window.localStorage.getItem(batchStorageKey)); + // Note: Events are usually are groupd together into a single batch + // However, in this case, since we are mocking a custom event (event0) + // our batching logic is grouping event0 into a separate batch from + // the Session Start + AST event from init as they have a different + // SessionID + expect(storedBatches.length).to.equal(2); + expect(storedBatches[0].events[0].event_type, 'Batch 1: Session Start').to.equal('session_start'); + expect(storedBatches[0].events[1].event_type, 'Batch 1: AST').to.equal('application_state_transition'); + expect(storedBatches[1].events[0].event_type, 'Batch 2: Custom Event Type').to.equal('custom_event'); + expect(storedBatches[1].events[0].data.event_name, 'Batch 2: Custom Event Name').to.equal('Test Event 0'); + done(); + }, 0); + }); + it('should save batches in sequence to Local Storage when an HTTP 429 error is encountered', function (done) { + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + client.post(urls.events, 429); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + clock.restore(); + setTimeout(function () { + expect(window.localStorage.getItem(batchStorageKey)).to.be.ok; + var storedBatches = JSON.parse(window.localStorage.getItem(batchStorageKey)); + expect(storedBatches.length).to.equal(2); + expect(storedBatches[0].events[0].event_type, 'Batch 1: Session Start').to.equal('session_start'); + expect(storedBatches[0].events[1].event_type, 'Batch 1: AST').to.equal('application_state_transition'); + expect(storedBatches[1].events[0].event_type, 'Batch 2: Custom Event Type').to.equal('custom_event'); + expect(storedBatches[1].events[0].data.event_name, 'Batch 2: Custom Event Name').to.equal('Test Event 0'); + done(); + }, 0); + }); + it('should NOT save any batches to Local Storage when an HTTP 401 error is encountered', function (done) { + // When a 401 is encountered, we assume that the batch is bad so we clear those + // batches from the Upload Queue. Therefore, there should not be anything in + // Offline Storage afterwards + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + client.post(urls.events, 401); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + // Init will fire a Session Start and AST. We are adding event0 + // to show that manually queued events will also be grouped + // into a batch + uploader.queueEvent(event0); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + clock.restore(); + setTimeout(function () { + expect(window.localStorage.getItem(batchStorageKey)).to.equal(''); + done(); + }, 0); + }); + it('should save batches in sequence to Local Storage when upload is interrupted', function (done) { + // Interruption in this context means that the first upload is successful, but + // the next upload in sequence is not. For example, on a mobile device on the + // subway or if a connection is rate limited. In this case, we should save + // batches in the order they were created for a future upload attempt + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + // First upload is successful + client.post(urls.events, 200, { + overwriteRoutes: false, + repeat: 1 + }); + // Second upload is rate limited + client.post(urls.events, 429, { + overwriteRoutes: false + }); + // Set up SDK and Uploader + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + var batchValidator = new _BatchValidator(); + // Create sample batches for testing + var batch1 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 1' + }, { + messageType: 4, + name: 'Test Event 2' + }]); + var batch2 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 3' + }, { + messageType: 4, + name: 'Test Event 4' + }]); + var batch3 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 5' + }, { + messageType: 4, + name: 'Test Event 6' + }]); + // Init will generate a batch with Session Start and AST which normally comes first + // but for testing purposes the Session Start + AST batches will be the last batches + // as we are manually queueing additional batches to verify sequence + uploader.batchesQueuedForProcessing.push(batch1); + uploader.batchesQueuedForProcessing.push(batch2); + uploader.batchesQueuedForProcessing.push(batch3); + // Manually initiate the upload process + // This will also turn the SessionStart + AST events into a batch and add it to the end of the queue + window.mParticle.upload(); + clock.restore(); + setTimeout(function () { + expect(window.localStorage.getItem(batchStorageKey)).to.be.ok; + var storedBatches = JSON.parse(window.localStorage.getItem(batchStorageKey)); + // We tried to upload 4 batches (3 unique batches + Session Start/AST from init) + expect(storedBatches.length).to.equal(3); + // The following assertions should verify the sequence presented below + // - Batch 1: Test Event 1 and 2 - Should have been uploaded - No Longer in Offline Storage + // - Batch 2: Test Event 3 and 4 - Failed Upload - Saved to Offline Storage + // - Batch 3: Test Event 5 and 6 - Upload suspended - Saved to Offline Storage + // - Batch 4: Session Start and AST - Upload suspended - Saved to Offline Storage + // Because Batch 2 failed to upload, subsequent Batches should be suspended until Batch 2 succeeds + expect(storedBatches[0].events[0].event_type, 'Batch 2: Test Event 3 Event Type').to.equal('custom_event'); + expect(storedBatches[0].events[0].data.event_name, 'Batch 2: Test Event 3 Event Name').to.equal('Test Event 3'); + expect(storedBatches[0].events[1].event_type, 'Batch 2: Test Event 4 Event Type').to.equal('custom_event'); + expect(storedBatches[0].events[1].data.event_name, 'Batch 2: Test Event 4 Event Name').to.equal('Test Event 4'); + expect(storedBatches[1].events[0].event_type, 'Batch 3: Test Event 5 Event Type').to.equal('custom_event'); + expect(storedBatches[1].events[0].data.event_name, 'Batch 3: Test Event 5 Event Name').to.equal('Test Event 5'); + expect(storedBatches[1].events[1].event_type, 'Batch 3: Test Event 6 Event Type').to.equal('custom_event'); + expect(storedBatches[1].events[1].data.event_name, 'Batch 3: Test Event 6 Event Name').to.equal('Test Event 6'); + // These are the events that are generated by mParticle.init. Usually they + // come before any queued events, but we manually queued the previous + // batches increase the number of attempted uploads to verify that batches + // are retained in Offline Storage in order of creation + expect(storedBatches[2].events[0].event_type, 'Batch 4: Session Start').to.equal('session_start'); + expect(storedBatches[2].events[1].event_type, 'Batch 4: AST').to.equal('application_state_transition'); + done(); + }, 0); + }); + it('should attempt to upload batches from Offline Storage before new batches', function (done) { + // This test should verify that batches read from Offline Storage are prepended + // to the upload queue before newly created batches. + var batchStorageKey = 'mprtcl-v4_abcdef-batches'; + client.post(urls.events, 200); + // Set up SDK and Uploader + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + var uploader = mpInstance._APIClient.uploader; + var batchValidator = new _BatchValidator(); + // Create sample batches for testing + var batch1 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 1' + }, { + messageType: 4, + name: 'Test Event 2' + }]); + var batch2 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 3' + }, { + messageType: 4, + name: 'Test Event 4' + }]); + var batch3 = batchValidator.returnBatch([{ + messageType: 4, + name: 'Test Event 5' + }, { + messageType: 4, + name: 'Test Event 6' + }]); + // Write batches to Offline Storage before queuing new events or batches + window.localStorage.setItem(batchStorageKey, JSON.stringify([batch1, batch2, batch3])); + // Batch Queue should be empty before we upload + expect(uploader.batchesQueuedForProcessing.length).to.equal(0); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + clock.restore(); + setTimeout(function () { + expect(window.localStorage.getItem(batchStorageKey), 'Offline Batch Storage should be empty').to.equal(''); + // To verify the sequence, we should look at what has been uploaded + // as the upload queue and Offline Storage should be empty + expect(client.calls().length).to.equal(4); + var uploadedBatch1 = JSON.parse(client.calls()[0][1].body); + var uploadedBatch2 = JSON.parse(client.calls()[1][1].body); + var uploadedBatch3 = JSON.parse(client.calls()[2][1].body); + var uploadedBatch4 = JSON.parse(client.calls()[3][1].body); + // The following assertions should verify the sequence presented below + // - Batch 1: Test Event 1 and 2 - Read from Offline Storage + // - Batch 2: Test Event 3 and 4 - Read from Offline Storage + // - Batch 3: Test Event 5 and 6 - Read from Offline Storage + // - Batch 4: Session Start and AST - (new) Created by Init + expect(uploadedBatch1.events[0].data.event_name, 'Batch 1: Test Event 1 ').to.equal('Test Event 1'); + expect(uploadedBatch1.events[1].data.event_name, 'Batch 1: Test Event 2').to.equal('Test Event 2'); + expect(uploadedBatch2.events[0].data.event_name, 'Batch 2: Test Event 3 Event Name').to.equal('Test Event 3'); + expect(uploadedBatch2.events[1].data.event_name, 'Batch 2: Test Event 4 Event Name').to.equal('Test Event 4'); + expect(uploadedBatch3.events[0].data.event_name, 'Batch 2: Test Event 5 Event Name').to.equal('Test Event 5'); + expect(uploadedBatch3.events[1].data.event_name, 'Batch 2: Test Event 6 Event Name').to.equal('Test Event 6'); + // These are the events that are generated by mParticle.init. Usually they + // come before any queued events, but we manually queued the previous + // batches increase the number of attempted uploads to verify that batches + // are retained in Offline Storage in order of creation + expect(uploadedBatch4.events[0].event_type, 'Batch 4: Session Start').to.equal('session_start'); + expect(uploadedBatch4.events[1].event_type, 'Batch 4: AST').to.equal('application_state_transition'); + done(); + }, 0); + }); + }); + describe('Upload Workflow', function () { + beforeEach(function () { + clock = sinon$1.useFakeTimers({ + now: new Date().getTime() + }); + }); + afterEach(function () { + client.restore(); + clock.restore(); + }); + it('should organize events in the order they are processed and maintain that order when uploading', function (done) { + // Batches should be uploaded in the order they were created to prevent + // any potential corruption. + client.post(urls.events, 200); + client.config.overwriteRoutes = true; + window.mParticle.config.flags = __assign({}, enableBatchingConfigFlags); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event 0'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + expect(client.called(), 'FetchMock should have been called').to.equal(true); + var batch1 = JSON.parse(client._calls[0][1].body); + // Batch 1 should contain only session start, AST and a single event + // in this exact order + expect(batch1.events.length).to.equal(3); + expect(batch1.events[0].event_type).to.equal('session_start'); + expect(batch1.events[1].event_type).to.equal('application_state_transition'); + expect(batch1.events[2].data.event_name).to.equal('Test Event 0'); + // Log a second batch of events + window.mParticle.logEvent('Test Event 1'); + window.mParticle.logEvent('Test Event 2'); + window.mParticle.logEvent('Test Event 3'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + var batch2 = JSON.parse(client._calls[1][1].body); + // Batch 2 should contain three custom events + expect(batch2.events.length).to.equal(3); + expect(batch2.events[0].data.event_name).to.equal('Test Event 1'); + expect(batch2.events[1].data.event_name).to.equal('Test Event 2'); + expect(batch2.events[2].data.event_name).to.equal('Test Event 3'); + // Log a third batch of events + window.mParticle.logEvent('Test Event 4'); + window.mParticle.logEvent('Test Event 5'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + var batch3 = JSON.parse(client._calls[2][1].body); + // Batch 3 should contain two custom events + expect(batch3.events.length).to.equal(2); + expect(batch3.events[0].data.event_name).to.equal('Test Event 4'); + expect(batch3.events[1].data.event_name).to.equal('Test Event 5'); + done(); + }); + // TODO: Investigate workflow with unshift vs push + // https://go.mparticle.com/work/SQDSDKS-5165 + it.skip('should keep batches in sequence for future retries when an HTTP 500 error occurs', function (done) { + // If batches cannot upload, they should be added back to the Batch Queue + // in the order they were created so they can be retransmitted. + client.post(urls.events, 500); + window.mParticle.config.flags = __assign({}, enableBatchingConfigFlags); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + // Generates Batch 1 with Session Start + AST + // Adds a custom event to Batch 1 + window.mParticle.logEvent('Test Event 0'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + expect(client.called(), 'FetchMock should have been called').to.equal(true); + var batch1 = JSON.parse(client._calls[0][1].body); + // Batch 1 should contain only session start, AST and a single event + // in this exact order + expect(batch1.events.length).to.equal(3); + expect(batch1.events[0].event_type).to.equal('session_start'); + expect(batch1.events[1].event_type).to.equal('application_state_transition'); + expect(batch1.events[2].data.event_name).to.equal('Test Event 0'); + // Batch 2 + window.mParticle.logEvent('Test Event 1'); + window.mParticle.logEvent('Test Event 2'); + window.mParticle.logEvent('Test Event 3'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // Batch 3 + window.mParticle.logEvent('Test Event 4'); + window.mParticle.logEvent('Test Event 5'); + window.mParticle.logEvent('Test Event 6'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // Reset clock so that the setTimeout return immediately + clock.restore(); + setTimeout(function () { + var batchQueue = window.mParticle.getInstance()._APIClient.uploader.batchesQueuedForProcessing; + expect(batchQueue.length).to.equal(3); + expect(batchQueue[0].events[0].event_type).to.equal('session_start'); + expect(batchQueue[0].events[1].event_type).to.equal('application_state_transition'); + expect(batchQueue[0].events[2].data.event_name).to.equal('Test Event 0'); + expect(batchQueue[1].events[0].data.event_name).to.equal('Test Event 1'); + expect(batchQueue[1].events[1].data.event_name).to.equal('Test Event 2'); + expect(batchQueue[1].events[2].data.event_name).to.equal('Test Event 3'); + expect(batchQueue[2].events[0].data.event_name).to.equal('Test Event 4'); + expect(batchQueue[2].events[1].data.event_name).to.equal('Test Event 5'); + expect(batchQueue[2].events[2].data.event_name).to.equal('Test Event 6'); + done(); + }, 0); + }); + // TODO: Investigate workflow with unshift vs push + // https://go.mparticle.com/work/SQDSDKS-5165 + it.skip('should keep and retry batches in sequence if the transmission fails midway', function (done) { + // First request is successful, subsequent requests fail + client.post(urls.events, 200, { + overwriteRoutes: false, + repeat: 1 + }); + client.post(urls.events, 429, { + overwriteRoutes: false + }); + window.mParticle.config.flags = __assign({}, enableBatchingConfigFlags); + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + // Generates Batch 1 with Session Start + AST + // Adds a custom event to Batch 1 + window.mParticle.logEvent('Test Event 0'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // Batch 2 + window.mParticle.logEvent('Test Event 1'); + window.mParticle.logEvent('Test Event 2'); + window.mParticle.logEvent('Test Event 3'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // Batch 3 + window.mParticle.logEvent('Test Event 4'); + window.mParticle.logEvent('Test Event 5'); + window.mParticle.logEvent('Test Event 6'); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // Reset timer so the setTimeout can trigger + clock.restore(); + setTimeout(function () { + // Batch upload should be triggered 3 times, but only + // 2 should be waiting for retry + expect(client.calls().length).to.equal(3); + var batchQueue = window.mParticle.getInstance()._APIClient.uploader.batchesQueuedForProcessing; + expect(batchQueue.length).to.equal(2); + expect(batchQueue[0].events[0].data.event_name).to.equal('Test Event 1'); + expect(batchQueue[0].events[1].data.event_name).to.equal('Test Event 2'); + expect(batchQueue[0].events[2].data.event_name).to.equal('Test Event 3'); + expect(batchQueue[1].events[0].data.event_name).to.equal('Test Event 4'); + expect(batchQueue[1].events[1].data.event_name).to.equal('Test Event 5'); + expect(batchQueue[1].events[2].data.event_name).to.equal('Test Event 6'); + done(); + }, 0); + }); + }); + describe('batching via window.fetch', function () { + beforeEach(function () { + client.post(urls.events, 200); + client.config.overwriteRoutes = true; + clock = sinon$1.useFakeTimers({ + now: new Date().getTime() + }); + window.mParticle.config.flags = __assign({}, enableBatchingConfigFlags); + }); + afterEach(function () { + client.restore(); + sinon$1.restore(); + clock.restore(); + }); + it('should use custom v3 endpoint', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1); + // Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000); + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should have latitude/longitude for location when batching', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.setPosition(100, 100); + window.mParticle.logEvent('Test Event'); + clock.tick(1000); + // Tick forward 1000 ms to hit upload interval and force an upload + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + batch.events[2].data.location.should.have.property('latitude', 100); + batch.events[2].data.location.should.have.property('longitude', 100); + done(); + }); + it('should force uploads when using public `upload`', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1); + // no calls made to fetch yet + (client.lastCall() === undefined).should.equal(true); + // force upload, triggering window.fetch + window.mParticle.upload(); + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should force uploads when a commerce event is called', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1); + var product1 = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart, product1); + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + batch.events[3].event_type.should.equal('commerce_event'); + batch.events[3].data.product_action.action.should.equal('add_to_cart'); + done(); + }); + it('should return pending uploads if a 500 is returned', function (done) { + window.mParticle._resetForTests(MPConfig); + // var clock = sinon.useFakeTimers(); + client.post(urls.events, 500); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + var pendingEvents = window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing; + pendingEvents.length.should.equal(3); + pendingEvents[0].EventName.should.equal(1); + pendingEvents[1].EventName.should.equal(10); + pendingEvents[2].EventName.should.equal('Test Event'); + client.post(urls.events, 200); + (client.lastCall() === undefined).should.equal(true); + clock.tick(1000); + var nowPendingEvents = window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing; + nowPendingEvents.length.should.equal(0); + var batch = JSON.parse(client.lastCall()[1].body); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should send source_message_id with events to v3 endpoint', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000); + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + batch.events[0].data.should.have.property('source_message_id'); + done(); + }); + it('should send user-defined SourceMessageId events to v3 endpoint', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logBaseEvent({ + messageType: 4, + name: 'Test Event', + data: { + key: 'value' }, - - abort: function abort() { - this.aborted = true; - requestErrorSteps(this); - this.readyState = FakeXMLHttpRequest.UNSENT; + eventType: 3, + customFlags: { + flagKey: 'flagValue' }, + sourceMessageId: 'abcdefg' + }); + // Identity call is via XHR request + // Session start, AST, and `Test Event` are queued. + mockServer.requests.length.should.equal(1); + // Tick forward 1000 ms to hit upload interval and force an upload + clock.tick(1000); + var lastCall = client.lastCall(); + var endpoint = lastCall[0]; + var batch = JSON.parse(client.lastCall()[1].body); + endpoint.should.equal(urls.events); + // event batch includes session start, ast, then last event is Test Event + batch.events[batch.events.length - 1].data.should.have.property('source_message_id', 'abcdefg'); + done(); + }); + it('should call the identity callback after a session ends if user is returning to the page after a long period of time', function (done) { + // Background of bug that this test fixes: + // User navigates away from page and returns after some time + // and the session should end. There is a UAC firing inside of + // config.identityCallback, which would send to our servers with + // the previous session ID because the identity call back fired + // before the session logic that determines if a new session should + // start. + window.mParticle._resetForTests(MPConfig); + window.mParticle.config.identityCallback = function (result) { + var currentUser = result.getUser(); + if (currentUser) { + // TODO: Investigate if we should update definitely typed typings for + // setUserAttribute which only allows strings right now + // more context at https://go.mparticle.com/work/SQDSDKS-4576 + currentUser.setUserAttribute("number", "".concat(Math.floor(Math.random() * 1000 + 1))); + } + }; + var endSessionFunction = window.mParticle.getInstance()._SessionManager.endSession; + window.mParticle.init(apiKey, window.mParticle.config); + // Mock end session so that the SDK doesn't actually send it. We do this + // to mimic a return to page behavior, below: + window.mParticle.getInstance()._SessionManager.endSession = function () {}; + // Force 35 minutes to pass, so that when we return to the page, when + // the SDK initializes it will know to end the session. + clock.tick(35 * 60000); + // Undo mock of end session so that when we initializes, it will end + // the session for real. + window.mParticle.getInstance()._SessionManager.endSession = endSessionFunction; + // Initialize imitates returning to the page + window.mParticle.init(apiKey, window.mParticle.config); + // Manually initiate the upload process - turn event into batches and upload the batch + window.mParticle.upload(); + // We have to restore the clock in order to use setTimeout below + clock.restore(); + setTimeout(function () { + var batch1 = JSON.parse(client._calls[0][1].body); + var batch2 = JSON.parse(client._calls[1][1].body); + var batch3 = JSON.parse(client._calls[2][1].body); + var batch4 = JSON.parse(client._calls[3][1].body); + var batch5 = JSON.parse(client._calls[4][1].body); + // UAC event + expect(batch1.events.length, 'Batch 1: UAC event').to.equal(1); + // session start, AST + expect(batch2.events.length, 'Batch 2: Session Start, AST').to.equal(2); + // session end + expect(batch3.events.length, 'Batch 3: Session End').to.equal(1); + // UAC event + expect(batch4.events.length, 'Batch 5: Session Start, AST').to.equal(2); + // session start, AST + expect(batch5.events.length, 'Batch 4: UAC event').to.equal(1); + var batch1UAC = TestsCore.findEventFromBatch(batch1, 'user_attribute_change'); + batch1UAC.should.be.ok(); + var batch2SessionStart = TestsCore.findEventFromBatch(batch2, 'session_start'); + var batch2AST = TestsCore.findEventFromBatch(batch2, 'application_state_transition'); + batch2SessionStart.should.be.ok(); + batch2AST.should.be.ok(); + var batch3SessionEnd = TestsCore.findEventFromBatch(batch3, 'session_end'); + batch3SessionEnd.should.be.ok(); + var batch4SessionStart = TestsCore.findEventFromBatch(batch4, 'session_start'); + var batch4AST = TestsCore.findEventFromBatch(batch4, 'application_state_transition'); + batch4SessionStart.should.be.ok(); + batch4AST.should.be.ok(); + var batch5UAC = TestsCore.findEventFromBatch(batch5, 'user_attribute_change'); + batch5UAC.should.be.ok(); + _typeof(batch1.source_request_id).should.equal('string'); + _typeof(batch2.source_request_id).should.equal('string'); + _typeof(batch3.source_request_id).should.equal('string'); + _typeof(batch4.source_request_id).should.equal('string'); + _typeof(batch5.source_request_id).should.equal('string'); + batch1.source_request_id.should.not.equal(batch2.source_request_id); + batch1.source_request_id.should.not.equal(batch3.source_request_id); + batch1.source_request_id.should.not.equal(batch4.source_request_id); + batch1.source_request_id.should.not.equal(batch5.source_request_id); + batch2.source_request_id.should.not.equal(batch3.source_request_id); + batch2.source_request_id.should.not.equal(batch4.source_request_id); + batch2.source_request_id.should.not.equal(batch5.source_request_id); + batch3.source_request_id.should.not.equal(batch4.source_request_id); + batch3.source_request_id.should.not.equal(batch5.source_request_id); + batch4.source_request_id.should.not.equal(batch5.source_request_id); + batch1UAC.data.session_uuid.should.equal(batch2AST.data.session_uuid); + batch1UAC.data.session_uuid.should.equal(batch2SessionStart.data.session_uuid); + batch1UAC.data.session_uuid.should.not.equal(batch5UAC.data.session_uuid); + batch1UAC.data.session_uuid.should.not.equal(batch4SessionStart.data.session_uuid); + batch1UAC.data.session_uuid.should.not.equal(batch4AST.data.session_uuid); + batch1UAC.data.session_start_unixtime_ms.should.equal(batch2AST.data.session_start_unixtime_ms); + batch1UAC.data.session_start_unixtime_ms.should.equal(batch2SessionStart.data.session_start_unixtime_ms); + batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch5UAC.data.session_start_unixtime_ms); + batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch4SessionStart.data.session_start_unixtime_ms); + batch1UAC.data.session_start_unixtime_ms.should.not.equal(batch4AST.data.session_start_unixtime_ms); + batch2SessionStart.data.session_uuid.should.equal(batch2AST.data.session_uuid); + batch2SessionStart.data.session_uuid.should.equal(batch3SessionEnd.data.session_uuid); + batch2AST.data.session_uuid.should.equal(batch3SessionEnd.data.session_uuid); + batch2SessionStart.data.session_start_unixtime_ms.should.equal(batch2AST.data.session_start_unixtime_ms); + batch2SessionStart.data.session_start_unixtime_ms.should.equal(batch3SessionEnd.data.session_start_unixtime_ms); + batch2AST.data.session_start_unixtime_ms.should.equal(batch3SessionEnd.data.session_start_unixtime_ms); + batch4AST.data.session_uuid.should.equal(batch5UAC.data.session_uuid); + batch4SessionStart.data.session_uuid.should.equal(batch5UAC.data.session_uuid); + batch4SessionStart.data.session_uuid.should.equal(batch4AST.data.session_uuid); + batch4AST.data.session_start_unixtime_ms.should.equal(batch5UAC.data.session_start_unixtime_ms); + batch4SessionStart.data.session_start_unixtime_ms.should.equal(batch5UAC.data.session_start_unixtime_ms); + batch4SessionStart.data.session_start_unixtime_ms.should.equal(batch4AST.data.session_start_unixtime_ms); + done(); + // wait for more than 1000 milliseconds to force the final upload + }, 1200); + }); + }); + describe('batching via XHR for older browsers without window.fetch', function () { + var fetch = window.fetch; + beforeEach(function () { + delete window.fetch; + window.mParticle.config.flags = { + eventBatchingIntervalMillis: 1000 + }; + mockServer.respondWith(urls.events, [200, {}, JSON.stringify({ + mpid: testMPID, + Store: {} + })]); + clock = sinon$1.useFakeTimers(); + }); + afterEach(function () { + window.mParticle._resetForTests(MPConfig); + window.fetch = fetch; + sinon$1.restore(); + clock.restore(); + }); + it('should use custom v3 endpoint', function (done) { + window.mParticle._resetForTests(MPConfig); + mockServer.requests = []; + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1); + // Upload interval hit, now will send requests + clock.tick(1000); + // 1st request is /Identity call, 2nd request is /Event call + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should force uploads when using public `upload`', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1); + // Upload interval hit, now will send requests + clock.tick(1000); + window.mParticle.upload(); + // 1st request is /Identity call, 2nd request is /Event call + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should trigger an upload of batch when a commerce event is called', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + // The only request to the server should be the identify call + // Session start, AST, and Test Event are queued. + mockServer.requests.length.should.equal(1); + var product1 = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart, product1); + // 1st request is /Identity call, 2nd request is /Event call + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + batch.events[3].event_type.should.equal('commerce_event'); + batch.events[3].data.product_action.action.should.equal('add_to_cart'); + done(); + }); + it('should trigger an upload of batch when a UIC occurs', function (done) { + window.mParticle._resetForTests(MPConfig); + // include an identify request so that it creates a UIC + window.mParticle.config.identifyRequest = { + userIdentities: { + customerid: 'foo-customer-id' + } + }; + window.mParticle.init(apiKey, window.mParticle.config); + // Requests sent should be identify call, then UIC event + // Session start, AST, and Test Event are queued, and don't appear + // in the mockServer.requests + mockServer.requests.length.should.equal(2); + // 1st request is /Identity call, 2nd request is UIC call + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('user_identity_change'); + // force upload of other events + window.mParticle.upload(); + var batch2 = JSON.parse(mockServer.thirdRequest.requestBody); + batch2.events[0].event_type.should.equal('session_start'); + batch2.events[1].event_type.should.equal('application_state_transition'); + done(); + }); + it('should trigger an upload of batch when a UAC occurs', function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); + // Set a user attribute to trigger a UAC event + window.mParticle.Identity.getCurrentUser().setUserAttribute('age', 25); + // Requests sent should be identify call, then + // a request for session start, AST, and UAC + mockServer.requests.length.should.equal(2); + // 1st request is /Identity call, 2nd request is UIC call + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('user_attribute_change'); + done(); + }); + it('should return pending uploads if a 500 is returned', function (done) { + window.mParticle._resetForTests(MPConfig); + // var clock = sinon.useFakeTimers(); + mockServer.respondWith(urls.events, [500, {}, JSON.stringify({ + mpid: testMPID, + Store: {} + })]); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + var pendingEvents = window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing; + pendingEvents.length.should.equal(3); + pendingEvents[0].EventName.should.equal(1); + pendingEvents[1].EventName.should.equal(10); + pendingEvents[2].EventName.should.equal('Test Event'); + clock.tick(1000); + var nowPendingEvents = window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing; + nowPendingEvents.length.should.equal(0); + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Test Event'); + done(); + }); + it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', function (done) { + window.mParticle._resetForTests(MPConfig); + // var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch = function (batch) { + return batch; + }; + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + clock.tick(1000); + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.modified.should.equal(true); + done(); + }); + it('should respect rules for the batch modification', function (done) { + window.mParticle._resetForTests(MPConfig); + // var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch = function (batch) { + batch.events.map(function (event) { + if (event.event_type === "custom_event") { + event.data.event_name = 'Modified!'; + } + }); + return batch; + }; + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + clock.tick(1000); + var batch = JSON.parse(mockServer.secondRequest.requestBody); + batch.events.length.should.equal(3); + batch.events[0].event_type.should.equal('session_start'); + batch.events[1].event_type.should.equal('application_state_transition'); + batch.events[2].event_type.should.equal('custom_event'); + batch.events[2].data.event_name.should.equal('Modified!'); + done(); + }); + it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', function (done) { + window.mParticle._resetForTests(MPConfig); + // var clock = sinon.useFakeTimers(); + window.mParticle.config.onCreateBatch = function (batch) { + return undefined; + }; + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + clock.tick(1000); + (mockServer.secondRequest === null).should.equal(true); + done(); + }); + }); + }); - error: function() { - clearResponse(this); - this.errorFlag = true; - this.requestHeaders = {}; - this.responseHeaders = {}; + describe('Beacon Upload', function () { + var mockServer; + before(function () { + client.restore(); + sinon$1.restore(); + }); + beforeEach(function () { + client.restore(); + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + mockServer.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + window.mParticle.config.flags = { + eventBatchingIntervalMillis: 1000 + }; + }); + afterEach(function () { + sinon$1.restore(); + mockServer.reset(); + client.restore(); + }); + it('should trigger beacon on page visibilitychange events', function (done) { + window.mParticle._resetForTests(MPConfig); + var bond = sinon$1.spy(navigator, 'sendBeacon'); + window.mParticle.init(apiKey, window.mParticle.config); + // visibility change is a document property, not window + document.dispatchEvent(new Event('visibilitychange')); + bond.called.should.eql(true); + bond.lastCall.args[0].should.eql(urls.events); + done(); + }); + it('should trigger beacon on page beforeunload events', function (done) { + window.mParticle._resetForTests(MPConfig); + var bond = sinon$1.spy(navigator, 'sendBeacon'); + window.mParticle.init(apiKey, window.mParticle.config); + // karma fails if onbeforeunload is not set to null + window.onbeforeunload = null; + window.dispatchEvent(new Event('beforeunload')); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql(urls.events); + done(); + }); + it('should trigger beacon on pagehide events', function (done) { + window.mParticle._resetForTests(MPConfig); + var bond = sinon$1.spy(navigator, 'sendBeacon'); + window.mParticle.init(apiKey, window.mParticle.config); + window.dispatchEvent(new Event('pagehide')); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql(urls.events); + _typeof(bond.getCalls()[0].args[1]).should.eql('object'); + done(); + }); + }); - this.readyStateChange(FakeXMLHttpRequest.DONE); - }, + var dtpn = { + blok: { + ev: true, + ea: true, + ua: true, + id: true + }, + vers: { + version: 1, + data_plan_id: "robs_plan", + last_modified_on: "2020-10-27T19:12:42.397Z", + version_document: { + data_points: [ + { + description: "", + match: { + type: "product_impression", + criteria: { + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + additionalProperties: true, + properties: { + custom_flags: { + additionalProperties: false, + description: "", + properties: { + NotSoCustomFlag: { + description: "", + type: "boolean" + } + }, + required: [ + ], + type: "object" + }, + custom_attributes: { + additionalProperties: false, + description: "", + properties: { + thing1: { + description: "", + type: "string" + } + }, + required: [ + "thing1" + ], + type: "object" + }, + product_impressions: { + description: "", + items: { + additionalProperties: false, + description: "", + properties: { + product_impression_list: { + description: "", + type: "string" + }, + products: { + description: "", + items: { + additionalProperties: true, + description: "", + properties: { + custom_attributes: { + additionalProperties: false, + description: "", + properties: { + allowedAttr2: { + description: "", + type: "string" + }, + allowedAttr1: { + description: "", + type: "string" + } + }, + required: [ + ], + type: "object" + } + }, + required: [ + ], + type: "object" + }, + type: "array" + } + }, + required: [ + ], + type: "object" + }, + type: "array" + } + }, + required: [ + "custom_attributes" + ], + type: "object" + } + } + } + } + }, + { + description: "", + match: { + type: "screen_view", + criteria: { + screen_name: "another new screenview event" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + additionalProperties: false, + properties: { + activity_type: { + description: "", + pattern: "[a-z]", + type: "string" + } + }, + required: [ + ], + type: "object" + } + } + } + }, + active_transformation_ids: null + }, + { + match: { + type: "custom_event", + criteria: { + event_name: "Search Event", + custom_event_type: "search" + } + }, + validator: { + type: "json_schema", + definition: { + } + } + }, + { + match: { + type: "custom_event", + criteria: { + event_name: "locationEvent", + custom_event_type: "location" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + foo: { + }, + "foo foo": { + }, + "foo number": { + } + } + } + } + } + } + } + } + }, + { + match: { + type: "product_action", + criteria: { + action: "add_to_cart" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + attributeBoolean: { + }, + attributeEmail: { + }, + attributeNumEnum: { + }, + attributeNumMinMax: { + }, + attributeStringAlpha: { + } + } + } + } + } + } + } + } + }, + { + match: { + type: "promotion_action", + criteria: { + action: "view" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + "not required": { + }, + required: { + } + } + } + } + } + } + } + } + }, + { + match: { + type: "custom_event", + criteria: { + event_name: "TestEvent", + custom_event_type: "navigation" + } + }, + validator: { + type: "json_schema", + definition: { + } + } + }, + { + match: { + type: "screen_view", + criteria: { + screen_name: "A New ScreenViewEvent" + } + }, + validator: { + type: "json_schema", + definition: { + } + } + }, + { + match: { + type: "screen_view", + criteria: { + screen_name: "my screeeen" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + test1key: { + }, + test2key: { + } + } + } + } + } + } + } + } + }, + { + match: { + type: "custom_event", + criteria: { + event_name: "something something something", + custom_event_type: "navigation" + } + }, + validator: { + type: "json_schema", + definition: { + } + } + }, + { + match: { + type: "user_attributes" + }, + validator: { + type: "json_schema", + definition: { + additionalProperties: false, + properties: { + "a third attribute": { + }, + "my attribute": { + }, + "my other attribute": { + } + } + } + } + }, + { + match: { + type: "custom_event", + criteria: { + event_name: "SocialEvent", + custom_event_type: "social" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + } + } + } + } + } + } + } + }, + { + match: { + type: "product_action", + criteria: { + action: "purchase" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + eventAttribute1: { + }, + eventAttribute2: { + } + } + }, + product_action: { + properties: { + products: { + items: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + plannedAttr1: { + }, + plannedAttr2: { + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + { + match: { + type: "promotion_action", + criteria: { + action: "click" + } + }, + validator: { + type: "json_schema", + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + eventAttribute1: { + }, + eventAttribute2: { + } + } + } + } + } + } + } + } + }, + { + description: "User Identities", + match: { + type: "user_identities", + criteria: { + } + }, + validator: { + type: "json_schema", + definition: { + additionalProperties: true, + properties: { + customerid: { + description: "", + type: "string" + }, + amp_id: { + description: "", + type: "string" + }, + email: { + description: "", + type: "string" + } + }, + required: [ + "email" + ], + type: "object" + } + } + } + ] + } + } + }; + var dataPlan = { + dtpn: dtpn + }; - triggerTimeout: function triggerTimeout() { - if (sinonXhr.supportsTimeout) { - this.timedOut = true; - requestErrorSteps(this); - } - }, + var dataPlan$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + dtpn: dtpn, + 'default': dataPlan + }); - getResponseHeader: function getResponseHeader(header) { - if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { - return null; + /* + TODO: Including this as a workaround because attempting to import it from + @mparticle/data-planning-models directly creates a build error. + */ + var DataPlanMatchType = { + ScreenView: "screen_view", + CustomEvent: "custom_event", + Commerce: "commerce", + UserAttributes: "user_attributes", + UserIdentities: "user_identities", + ProductAction: "product_action", + PromotionAction: "promotion_action", + ProductImpression: "product_impression" + }; + /* + inspiration from https://github.com/mParticle/data-planning-node/blob/master/src/data_planning/data_plan_event_validator.ts + but modified to only include commerce events, custom events, screen views, and removes validation + + The purpose of the KitBlocker class is to parse a data plan and determine what events, event/user/product attributes, and user identities should be blocked from downstream forwarders. + + KitBlocker is instantiated with a data plan on mParticle initialization. KitBlocker.kitBlockingEnabled is false if no data plan is passed. + It parses the data plan by creating a `dataPlanMatchLookups` object in the following manner: + 1. For all events and user attributes/identities, it generates a `matchKey` in the shape of `typeOfEvent:eventType:nameOfEvent` + a. The matchKeys' value will return `true` if additionalProperties for the custom attributes/identities is `true`, otherwise it will return an object of planned attribute/identities + 2. For commerce events, after step 1 and 1a, a second `matchKey` is included that appends `Products`. This is used to determine productAttributes blocked + + When an event is logged in mParticle, it is sent to our server and then calls `KitBlocker.createBlockedEvent` before passing the event to each forwarder. + If the event is blocked, it will not send to the forwarder. If the event is not blocked, event/user/product attributes and user identities will be removed from the returned event if blocked. + */ + var KitBlocker = /** @class */function () { + function KitBlocker(dataPlan, mpInstance) { + var _this = this; + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; + this.dataPlanMatchLookups = {}; + this.blockEvents = false; + this.blockEventAttributes = false; + this.blockUserAttributes = false; + this.blockUserIdentities = false; + this.kitBlockingEnabled = false; + // if data plan is not requested, the data plan is {document: null} + if (dataPlan && !dataPlan.document) { + this.kitBlockingEnabled = false; + return; + } + this.kitBlockingEnabled = true; + this.mpInstance = mpInstance; + this.blockEvents = (_c = (_b = (_a = dataPlan === null || dataPlan === void 0 ? void 0 : dataPlan.document) === null || _a === void 0 ? void 0 : _a.dtpn) === null || _b === void 0 ? void 0 : _b.blok) === null || _c === void 0 ? void 0 : _c.ev; + this.blockEventAttributes = (_f = (_e = (_d = dataPlan === null || dataPlan === void 0 ? void 0 : dataPlan.document) === null || _d === void 0 ? void 0 : _d.dtpn) === null || _e === void 0 ? void 0 : _e.blok) === null || _f === void 0 ? void 0 : _f.ea; + this.blockUserAttributes = (_j = (_h = (_g = dataPlan === null || dataPlan === void 0 ? void 0 : dataPlan.document) === null || _g === void 0 ? void 0 : _g.dtpn) === null || _h === void 0 ? void 0 : _h.blok) === null || _j === void 0 ? void 0 : _j.ua; + this.blockUserIdentities = (_m = (_l = (_k = dataPlan === null || dataPlan === void 0 ? void 0 : dataPlan.document) === null || _k === void 0 ? void 0 : _k.dtpn) === null || _l === void 0 ? void 0 : _l.blok) === null || _m === void 0 ? void 0 : _m.id; + var versionDocument = (_q = (_p = (_o = dataPlan === null || dataPlan === void 0 ? void 0 : dataPlan.document) === null || _o === void 0 ? void 0 : _o.dtpn) === null || _p === void 0 ? void 0 : _p.vers) === null || _q === void 0 ? void 0 : _q.version_document; + var dataPoints = versionDocument === null || versionDocument === void 0 ? void 0 : versionDocument.data_points; + if (versionDocument) { + try { + if ((dataPoints === null || dataPoints === void 0 ? void 0 : dataPoints.length) > 0) { + dataPoints.forEach(function (point) { + return _this.addToMatchLookups(point); + }); + } + } catch (e) { + this.mpInstance.Logger.error('There was an issue with the data plan: ' + e); + } + } + } + KitBlocker.prototype.addToMatchLookups = function (point) { + var _a, _b, _c; + if (!point.match || !point.validator) { + this.mpInstance.Logger.warning("Data Plan Point is not valid' + ".concat(point)); + return; + } + // match keys for non product custom attribute related data points + var matchKey = this.generateMatchKey(point.match); + var properties = this.getPlannedProperties(point.match.type, point.validator); + this.dataPlanMatchLookups[matchKey] = properties; + // match keys for product custom attribute related data points + if (((_a = point === null || point === void 0 ? void 0 : point.match) === null || _a === void 0 ? void 0 : _a.type) === DataPlanMatchType.ProductImpression || ((_b = point === null || point === void 0 ? void 0 : point.match) === null || _b === void 0 ? void 0 : _b.type) === DataPlanMatchType.ProductAction || ((_c = point === null || point === void 0 ? void 0 : point.match) === null || _c === void 0 ? void 0 : _c.type) === DataPlanMatchType.PromotionAction) { + matchKey = this.generateProductAttributeMatchKey(point.match); + properties = this.getProductProperties(point.match.type, point.validator); + this.dataPlanMatchLookups[matchKey] = properties; + } + }; + KitBlocker.prototype.generateMatchKey = function (match) { + var criteria = match.criteria || ''; + switch (match.type) { + case DataPlanMatchType.CustomEvent: + var customEventCriteria = criteria; + return [DataPlanMatchType.CustomEvent, customEventCriteria.custom_event_type, customEventCriteria.event_name].join(':'); + case DataPlanMatchType.ScreenView: + var screenViewCriteria = criteria; + return [DataPlanMatchType.ScreenView, '', screenViewCriteria.screen_name].join(':'); + case DataPlanMatchType.ProductAction: + var productActionMatch = criteria; + return [match.type, productActionMatch.action].join(':'); + case DataPlanMatchType.PromotionAction: + var promoActionMatch = criteria; + return [match.type, promoActionMatch.action].join(':'); + case DataPlanMatchType.ProductImpression: + var productImpressionActionMatch = criteria; + return [match.type, productImpressionActionMatch.action].join(':'); + case DataPlanMatchType.UserIdentities: + case DataPlanMatchType.UserAttributes: + return [match.type].join(':'); + default: + return null; + } + }; + KitBlocker.prototype.generateProductAttributeMatchKey = function (match) { + var criteria = match.criteria || ''; + switch (match.type) { + case DataPlanMatchType.ProductAction: + var productActionMatch = criteria; + return [match.type, productActionMatch.action, 'ProductAttributes'].join(':'); + case DataPlanMatchType.PromotionAction: + var promoActionMatch = criteria; + return [match.type, promoActionMatch.action, 'ProductAttributes'].join(':'); + case DataPlanMatchType.ProductImpression: + return [match.type, 'ProductAttributes'].join(':'); + default: + return null; + } + }; + KitBlocker.prototype.getPlannedProperties = function (type, validator) { + var _a, _b, _c, _d, _e, _f, _g, _h; + var customAttributes; + var userAdditionalProperties; + switch (type) { + case DataPlanMatchType.CustomEvent: + case DataPlanMatchType.ScreenView: + case DataPlanMatchType.ProductAction: + case DataPlanMatchType.PromotionAction: + case DataPlanMatchType.ProductImpression: + customAttributes = (_d = (_c = (_b = (_a = validator === null || validator === void 0 ? void 0 : validator.definition) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.properties) === null || _d === void 0 ? void 0 : _d.custom_attributes; + if (customAttributes) { + if (customAttributes.additionalProperties === true || customAttributes.additionalProperties === undefined) { + return true; + } else { + var properties = {}; + for (var _i = 0, _j = Object.keys(customAttributes.properties); _i < _j.length; _i++) { + var property = _j[_i]; + properties[property] = true; } - - if (/^Set-Cookie2?$/i.test(header)) { - return null; + return properties; + } + } else { + if (((_g = (_f = (_e = validator === null || validator === void 0 ? void 0 : validator.definition) === null || _e === void 0 ? void 0 : _e.properties) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.additionalProperties) === false) { + return {}; + } else { + return true; + } + } + case DataPlanMatchType.UserAttributes: + case DataPlanMatchType.UserIdentities: + userAdditionalProperties = (_h = validator === null || validator === void 0 ? void 0 : validator.definition) === null || _h === void 0 ? void 0 : _h.additionalProperties; + if (userAdditionalProperties === true || userAdditionalProperties === undefined) { + return true; + } else { + var properties = {}; + var userProperties = validator.definition.properties; + for (var _k = 0, _l = Object.keys(userProperties); _k < _l.length; _k++) { + var property = _l[_k]; + properties[property] = true; + } + return properties; + } + default: + return null; + } + }; + KitBlocker.prototype.getProductProperties = function (type, validator) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u; + var productCustomAttributes; + switch (type) { + case DataPlanMatchType.ProductImpression: + productCustomAttributes = (_k = (_j = (_h = (_g = (_f = (_e = (_d = (_c = (_b = (_a = validator === null || validator === void 0 ? void 0 : validator.definition) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.properties) === null || _d === void 0 ? void 0 : _d.product_impressions) === null || _e === void 0 ? void 0 : _e.items) === null || _f === void 0 ? void 0 : _f.properties) === null || _g === void 0 ? void 0 : _g.products) === null || _h === void 0 ? void 0 : _h.items) === null || _j === void 0 ? void 0 : _j.properties) === null || _k === void 0 ? void 0 : _k.custom_attributes; + //product item attributes + if ((productCustomAttributes === null || productCustomAttributes === void 0 ? void 0 : productCustomAttributes.additionalProperties) === false) { + var properties = {}; + for (var _i = 0, _v = Object.keys(productCustomAttributes === null || productCustomAttributes === void 0 ? void 0 : productCustomAttributes.properties); _i < _v.length; _i++) { + var property = _v[_i]; + properties[property] = true; + } + return properties; + } + return true; + case DataPlanMatchType.ProductAction: + case DataPlanMatchType.PromotionAction: + productCustomAttributes = (_u = (_t = (_s = (_r = (_q = (_p = (_o = (_m = (_l = validator === null || validator === void 0 ? void 0 : validator.definition) === null || _l === void 0 ? void 0 : _l.properties) === null || _m === void 0 ? void 0 : _m.data) === null || _o === void 0 ? void 0 : _o.properties) === null || _p === void 0 ? void 0 : _p.product_action) === null || _q === void 0 ? void 0 : _q.properties) === null || _r === void 0 ? void 0 : _r.products) === null || _s === void 0 ? void 0 : _s.items) === null || _t === void 0 ? void 0 : _t.properties) === null || _u === void 0 ? void 0 : _u.custom_attributes; + //product item attributes + if (productCustomAttributes) { + if (productCustomAttributes.additionalProperties === false) { + var properties = {}; + for (var _w = 0, _x = Object.keys(productCustomAttributes === null || productCustomAttributes === void 0 ? void 0 : productCustomAttributes.properties); _w < _x.length; _w++) { + var property = _x[_w]; + properties[property] = true; } - - // eslint-disable-next-line no-param-reassign - header = getHeader(this.responseHeaders, header); - - return this.responseHeaders[header] || null; + return properties; + } + } + return true; + default: + return null; + } + }; + KitBlocker.prototype.getMatchKey = function (eventToMatch) { + switch (eventToMatch.event_type) { + case dist.EventTypeEnum.screenView: + var screenViewEvent = eventToMatch; + if (screenViewEvent.data) { + return ['screen_view', '', screenViewEvent.data.screen_name].join(':'); + } + return null; + case dist.EventTypeEnum.commerceEvent: + var commerceEvent = eventToMatch; + var matchKey = []; + if (commerceEvent && commerceEvent.data) { + var _a = commerceEvent.data, + product_action = _a.product_action, + product_impressions = _a.product_impressions, + promotion_action = _a.promotion_action; + if (product_action) { + matchKey.push(DataPlanMatchType.ProductAction); + matchKey.push(product_action.action); + } else if (promotion_action) { + matchKey.push(DataPlanMatchType.PromotionAction); + matchKey.push(promotion_action.action); + } else if (product_impressions) { + matchKey.push(DataPlanMatchType.ProductImpression); + } + } + return matchKey.join(':'); + case dist.EventTypeEnum.customEvent: + var customEvent = eventToMatch; + if (customEvent.data) { + return ['custom_event', customEvent.data.custom_event_type, customEvent.data.event_name].join(':'); + } + return null; + default: + return null; + } + }; + KitBlocker.prototype.getProductAttributeMatchKey = function (eventToMatch) { + switch (eventToMatch.event_type) { + case dist.EventTypeEnum.commerceEvent: + var commerceEvent = eventToMatch; + var matchKey = []; + var _a = commerceEvent.data, + product_action = _a.product_action, + product_impressions = _a.product_impressions, + promotion_action = _a.promotion_action; + if (product_action) { + matchKey.push(DataPlanMatchType.ProductAction); + matchKey.push(product_action.action); + matchKey.push('ProductAttributes'); + } else if (promotion_action) { + matchKey.push(DataPlanMatchType.PromotionAction); + matchKey.push(promotion_action.action); + matchKey.push('ProductAttributes'); + } else if (product_impressions) { + matchKey.push(DataPlanMatchType.ProductImpression); + matchKey.push('ProductAttributes'); + } + return matchKey.join(':'); + default: + return null; + } + }; + KitBlocker.prototype.createBlockedEvent = function (event) { + /* + return a transformed event based on event/event attributes, + then product attributes if applicable, then user attributes, + then the user identities + */ + try { + if (event) { + event = this.transformEventAndEventAttributes(event); + } + if (event && event.EventDataType === Types.MessageType.Commerce) { + event = this.transformProductAttributes(event); + } + if (event) { + event = this.transformUserAttributes(event); + event = this.transformUserIdentities(event); + } + return event; + } catch (e) { + return event; + } + }; + KitBlocker.prototype.transformEventAndEventAttributes = function (event) { + var clonedEvent = __assign({}, event); + var baseEvent = convertEvent(clonedEvent); + var matchKey = this.getMatchKey(baseEvent); + var matchedEvent = this.dataPlanMatchLookups[matchKey]; + if (this.blockEvents) { + /* + If the event is not planned, it doesn't exist in dataPlanMatchLookups + and should be blocked (return null to not send anything to forwarders) + */ + if (!matchedEvent) { + return null; + } + } + if (this.blockEventAttributes) { + /* + matchedEvent is set to `true` if additionalProperties is `true` + otherwise, delete attributes that exist on event.EventAttributes + that aren't on + */ + if (matchedEvent === true) { + return clonedEvent; + } + if (matchedEvent) { + for (var _i = 0, _a = Object.keys(clonedEvent.EventAttributes); _i < _a.length; _i++) { + var key = _a[_i]; + if (!matchedEvent[key]) { + delete clonedEvent.EventAttributes[key]; + } + } + return clonedEvent; + } else { + return clonedEvent; + } + } + return clonedEvent; + }; + KitBlocker.prototype.transformProductAttributes = function (event) { + var _a; + var clonedEvent = __assign({}, event); + var baseEvent = convertEvent(clonedEvent); + var matchKey = this.getProductAttributeMatchKey(baseEvent); + var matchedEvent = this.dataPlanMatchLookups[matchKey]; + function removeAttribute(matchedEvent, productList) { + productList.forEach(function (product) { + for (var _i = 0, _a = Object.keys(product.Attributes); _i < _a.length; _i++) { + var productKey = _a[_i]; + if (!matchedEvent[productKey]) { + delete product.Attributes[productKey]; + } + } + }); + } + if (this.blockEvents) { + /* + If the event is not planned, it doesn't exist in dataPlanMatchLookups + and should be blocked (return null to not send anything to forwarders) + */ + if (!matchedEvent) { + return null; + } + } + if (this.blockEventAttributes) { + /* + matchedEvent is set to `true` if additionalProperties is `true` + otherwise, delete attributes that exist on event.EventAttributes + that aren't on + */ + if (matchedEvent === true) { + return clonedEvent; + } + if (matchedEvent) { + switch (event.EventCategory) { + case Types.CommerceEventType.ProductImpression: + clonedEvent.ProductImpressions.forEach(function (impression) { + removeAttribute(matchedEvent, impression === null || impression === void 0 ? void 0 : impression.ProductList); + }); + break; + case Types.CommerceEventType.ProductPurchase: + removeAttribute(matchedEvent, (_a = clonedEvent.ProductAction) === null || _a === void 0 ? void 0 : _a.ProductList); + break; + default: + this.mpInstance.Logger.warning('Product Not Supported '); + } + return clonedEvent; + } else { + return clonedEvent; + } + } + return clonedEvent; + }; + KitBlocker.prototype.transformUserAttributes = function (event) { + var clonedEvent = __assign({}, event); + if (this.blockUserAttributes) { + /* + If the user attribute is not found in the matchedAttributes + then remove it from event.UserAttributes as it is blocked + */ + var matchedAttributes = this.dataPlanMatchLookups['user_attributes']; + if (this.mpInstance._Helpers.isObject(matchedAttributes)) { + for (var _i = 0, _a = Object.keys(clonedEvent.UserAttributes); _i < _a.length; _i++) { + var ua = _a[_i]; + if (!matchedAttributes[ua]) { + delete clonedEvent.UserAttributes[ua]; + } + } + } + } + return clonedEvent; + }; + KitBlocker.prototype.isAttributeKeyBlocked = function (key) { + /* used when an attribute is added to the user */ + if (!this.blockUserAttributes) { + return false; + } + if (this.blockUserAttributes) { + var matchedAttributes = this.dataPlanMatchLookups['user_attributes']; + if (matchedAttributes === true) { + return false; + } + if (!matchedAttributes[key]) { + return true; + } + } + return false; + }; + KitBlocker.prototype.isIdentityBlocked = function (key) { + /* used when an attribute is added to the user */ + if (!this.blockUserIdentities) { + return false; + } + if (this.blockUserIdentities) { + var matchedIdentities = this.dataPlanMatchLookups['user_identities']; + if (matchedIdentities === true) { + return false; + } + if (!matchedIdentities[key]) { + return true; + } + } else { + return false; + } + return false; + }; + KitBlocker.prototype.transformUserIdentities = function (event) { + var _this = this; + var _a; + /* + If the user identity is not found in matchedIdentities + then remove it from event.UserIdentities as it is blocked. + event.UserIdentities is of type [{Identity: 'id1', Type: 7}, ...] + and so to compare properly in matchedIdentities, each Type needs + to be converted to an identityName + */ + var clonedEvent = __assign({}, event); + if (this.blockUserIdentities) { + var matchedIdentities_1 = this.dataPlanMatchLookups['user_identities']; + if (this.mpInstance._Helpers.isObject(matchedIdentities_1)) { + if ((_a = clonedEvent === null || clonedEvent === void 0 ? void 0 : clonedEvent.UserIdentities) === null || _a === void 0 ? void 0 : _a.length) { + clonedEvent.UserIdentities.forEach(function (uiByType, i) { + var identityName = Types.IdentityType.getIdentityName(_this.mpInstance._Helpers.parseNumber(uiByType.Type)); + if (!matchedIdentities_1[identityName]) { + clonedEvent.UserIdentities.splice(i, 1); + } + }); + } + } + } + return clonedEvent; + }; + return KitBlocker; + }(); + + // import sinon from 'sinon'; + var forwarderDefaultConfiguration$4 = TestsCore.forwarderDefaultConfiguration, + MockForwarder$6 = TestsCore.MockForwarder; + describe('kit blocking', function () { + var mockServer; + var kitBlockerDataPlan = { + document: dataPlan$1 + }; + beforeEach(function () { + mockServer = sinon$2.createFakeServer(); + mockServer.respondImmediately = true; + window.mParticle.config.dataPlan = { + document: dataPlan$1 + }; + window.mParticle.config.kitConfigs = []; + }); + afterEach(function () { + mockServer.reset(); + sinon$2.restore(); + }); + describe('kitBlocker', function () { + it('kitBlocker should parse data plan into dataPlanMatchLookups properly', function (done) { + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var dataPlanMatchLookups = kitBlocker.dataPlanMatchLookups; + dataPlanMatchLookups.should.have.property('custom_event:search:Search Event', true); + dataPlanMatchLookups.should.have.property('screen_view::another new screenview event', {}); + dataPlanMatchLookups.should.have.property('custom_event:location:locationEvent', { + foo: true, + 'foo foo': true, + 'foo number': true + }); + dataPlanMatchLookups.should.have.property('product_action:add_to_cart', { + attributeNumMinMax: true, + attributeEmail: true, + attributeNumEnum: true, + attributeStringAlpha: true, + attributeBoolean: true + }); + dataPlanMatchLookups.should.have.property('product_action:add_to_cart:ProductAttributes', true); + dataPlanMatchLookups.should.have.property('promotion_action:view', { + 'not required': true, + 'required': true + }); + dataPlanMatchLookups.should.have.property('promotion_action:view:ProductAttributes', true); + dataPlanMatchLookups.should.have.property('custom_event:navigation:TestEvent', true); + dataPlanMatchLookups.should.have.property('product_impression:ProductAttributes', { + allowedAttr1: true, + allowedAttr2: true + }); + dataPlanMatchLookups.should.have.property('screen_view::A New ScreenViewEvent', true); + dataPlanMatchLookups.should.have.property('screen_view::my screeeen', { + test2key: true, + test1key: true + }); + dataPlanMatchLookups.should.have.property('custom_event:navigation:something something something', true); + dataPlanMatchLookups.should.have.property('user_attributes', { + 'my attribute': true, + 'my other attribute': true, + 'a third attribute': true + }); + dataPlanMatchLookups.should.have.property('user_identities', true); + dataPlanMatchLookups.should.have.property('custom_event:social:SocialEvent', {}); + dataPlanMatchLookups.should.have.property('product_action:purchase', { + eventAttribute1: true, + eventAttribute2: true + }); + dataPlanMatchLookups.should.have.property('product_action:purchase:ProductAttributes', { + plannedAttr1: true, + plannedAttr2: true + }); + dataPlanMatchLookups.should.have.property('promotion_action:click', { + eventAttribute1: true, + eventAttribute2: true + }); + dataPlanMatchLookups.should.have.property('promotion_action:click:ProductAttributes', true); + done(); + }); + }); + describe('kitblocking - events and event attributes', function () { + var kitBlocker; + var event; + beforeEach(function () { + kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + event = { + DeviceId: 'test', + IsFirstRun: true, + EventName: null, + EventCategory: null, + MPID: testMPID, + EventAttributes: null, + SDKVersion: '1.0.0', + SourceMessageId: 'testSMID', + SessionId: 'sessionId', + SessionStartDate: 1, + Timestamp: 1, + EventDataType: null, + Debug: true, + CurrencyCode: 'usd' + }; + }); + it('should transform an unplanned event to null if blok.ev = true', function (done) { + event.EventName = 'unplanned event'; + event.EventCategory = Types.EventType.Search; + event.EventAttributes = { + keyword2: 'test' + }; + event.EventDataType = Types.MessageType.PageEvent; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + (transformedEvent === null).should.equal(true); + done(); + }); + it('should transform EventAttributes if an event attribute is not planned and blok.ea = true', function (done) { + event.EventName = 'locationEvent'; + event.EventCategory = Types.EventType.Location; + event.EventAttributes = { + unplannedAttr: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + transformedEvent.EventAttributes.should.not.have.property('unplannedAttr'); + transformedEvent.EventAttributes.should.have.property('foo', 'hi'); + done(); + }); + it('should transform EventAttributes if there are no custom attributes and additionalProperties === false', function (done) { + event.EventName = 'another new screenview event'; + event.EventCategory = Types.EventType.Location; + event.EventAttributes = { + unplannedAttr: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageView; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + transformedEvent.EventAttributes.should.not.have.property('unplannedAttr'); + transformedEvent.EventAttributes.should.not.have.property('foo'); + done(); + }); + it('should include unplanned event attributes if additionalProperties = true and blok.ea = true', function (done) { + event.EventName = 'something something something'; + event.EventCategory = Types.EventType.Navigation; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + transformedEvent.EventAttributes.should.have.property('foo', 'hi'); + transformedEvent.EventAttributes.should.have.property('keyword2', 'test'); + done(); + }); + it('should block any unplanned event attributes if custom attributes is empty, additionalProperties = false, and block.ea = true.', function (done) { + event.EventName = 'SocialEvent'; + event.EventCategory = Types.EventType.Social; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + Object.keys(transformedEvent.EventAttributes).length.should.equal(0); + done(); + }); + it('should not block any unplanned event attributes if custom attributes is empty, additionalProperties = true, and block.ea = true.', function (done) { + // modify this test so that the above + var socialDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + var _a, _b; + return ((_b = (_a = dataPoint === null || dataPoint === void 0 ? void 0 : dataPoint.match) === null || _a === void 0 ? void 0 : _a.criteria) === null || _b === void 0 ? void 0 : _b.event_name) === 'SocialEvent'; + }); + socialDataPoint.validator.definition.properties.data.properties.custom_attributes.additionalProperties = true; + kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + event.EventName = 'SocialEvent'; + event.EventCategory = Types.EventType.Social; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + var transformedEvent = kitBlocker.transformEventAndEventAttributes(event); + Object.keys(transformedEvent.EventAttributes).length.should.equal(2); + transformedEvent.EventAttributes.should.have.property('foo', 'hi'); + transformedEvent.EventAttributes.should.have.property('keyword2', 'test'); + socialDataPoint.validator.definition.properties.data.properties.custom_attributes.additionalProperties = false; + done(); + }); + }); + describe('kit blocking - user attributes/identities', function () { + var event; + beforeEach(function () { + new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + event = { + DeviceId: 'test', + IsFirstRun: true, + EventName: null, + EventCategory: null, + MPID: testMPID, + EventAttributes: null, + SDKVersion: '1.0.0', + SourceMessageId: 'testSMID', + SessionId: 'sessionId', + SessionStartDate: 1, + Timestamp: 1, + EventDataType: null, + Debug: true, + CurrencyCode: 'usd' + }; + }); + it('should block any unplanned user attributes when blok.ua = true and additionalPropertes = false', function (done) { + event.EventName = 'something something something'; + event.EventCategory = Types.EventType.Navigation; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + event.UserAttributes = { + 'my attribute': 'test1', + 'my other attribute': 'test2', + 'a third attribute': 'test3', + 'unplanned attribute': 'test4' + }; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformUserAttributes(event); + transformedEvent.UserAttributes.should.have.property('my attribute', 'test1'); + transformedEvent.UserAttributes.should.have.property('my other attribute', 'test2'); + transformedEvent.UserAttributes.should.have.property('a third attribute', 'test3'); + transformedEvent.UserAttributes.should.not.have.property('unplanned attribute'); + done(); + }); + it('should not block any unplanned user attributes if blok.ua = false', function (done) { + //TODO - what if this additional properties is false? shoudl we validate that? + window.mParticle.config.dataPlan.document.dtpn.blok.ua = false; + event.EventName = 'something something something', event.EventCategory = Types.EventType.Navigation, event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }, event.EventDataType = Types.MessageType.PageEvent, event.UserAttributes = { + 'my attribute': 'test1', + 'my other attribute': 'test2', + 'a third attribute': 'test3', + 'unplanned attribute': 'test4' + }; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformUserAttributes(event); + transformedEvent.UserAttributes.should.have.property('my attribute', 'test1'); + transformedEvent.UserAttributes.should.have.property('my other attribute', 'test2'); + transformedEvent.UserAttributes.should.have.property('a third attribute', 'test3'); + transformedEvent.UserAttributes.should.have.property('unplanned attribute', 'test4'); + //reset + window.mParticle.config.dataPlan.document.dtpn.blok.ua = true; + done(); + }); + it('isAttributeKeyBlocked should return false for attributes that are blocked and true for properties that are not', function (done) { + // this key is blocked because the default data plan has user_attributes>additional_properties = false + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var isBlocked = kitBlocker.isAttributeKeyBlocked('blocked'); + isBlocked.should.equal(true); + var userAttributeDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_attributes'; + }); + userAttributeDataPoint.validator.definition.additionalProperties = true; + var kitBlocker2 = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + isBlocked = kitBlocker2.isAttributeKeyBlocked('my attribute'); + isBlocked.should.equal(false); + // reset to original data plan + userAttributeDataPoint.validator.definition.additionalProperties = false; + done(); + }); + it('should not block any unplanned user identities when blok.id = true and additionalProperties = true', function (done) { + event.EventName = 'something something something'; + event.EventCategory = Types.EventType.Navigation; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + event.UserIdentities = [{ + Type: 7, + Identity: 'email@gmail.com' + }, { + Type: 1, + Identity: 'customerid1' + }, { + Type: 4, + Identity: 'GoogleId' + }]; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformUserIdentities(event); + transformedEvent.UserIdentities.filter(function (UI) { + return UI.Type === 1; + })[0].should.have.property('Identity', 'customerid1'); + transformedEvent.UserIdentities.filter(function (UI) { + return UI.Type === 7; + })[0].should.have.property('Identity', 'email@gmail.com'); + transformedEvent.UserIdentities.filter(function (UI) { + return UI.Type === 4; + })[0].should.have.property('Identity', 'GoogleId'); + done(); + }); + it('should block user identities when additional properties = false and blok.id = true', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + event.EventName = 'something something something'; + event.EventCategory = Types.EventType.Navigation; + event.EventAttributes = { + keyword2: 'test', + foo: 'hi' + }; + event.EventDataType = Types.MessageType.PageEvent; + event.UserIdentities = [{ + Type: 7, + Identity: 'email@gmail.com' + }, { + Type: 1, + Identity: 'customerid1' + }, { + Type: 4, + Identity: 'GoogleId' + }]; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformUserIdentities(event); + transformedEvent.UserIdentities.find(function (UI) { + return UI.Type === 1; + }).should.have.property('Identity', 'customerid1'); + transformedEvent.UserIdentities.find(function (UI) { + return UI.Type === 7; + }).should.have.property('Identity', 'email@gmail.com'); + (transformedEvent.UserIdentities.find(function (UI) { + return UI.Type === 4; + }) === undefined).should.equal(true); + // reset + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + it('isIdentityBlocked should return false for identities that are blocked and true for properties that are not', function (done) { + // this identity is not blocked because the default data plan has user_identities>additional_properties = false + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var isBlocked = kitBlocker.isIdentityBlocked('random identity'); + isBlocked.should.equal(false); + // for next test, change additionalProperties to false + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + var kitBlocker2 = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + isBlocked = kitBlocker2.isIdentityBlocked('facebook'); + isBlocked.should.equal(true); + // reset to original data plan + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + }); + describe('kit blocking - product attributes', function () { + var event; + var products; + beforeEach(function () { + new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + products = [{ + Attributes: { + 'plannedAttr1': 'val1', + 'plannedAttr2': 'val2', + 'unplannedAttr1': 'val3', + 'allowedAttr1': 'val4', + 'allowedAttr2': 'val5' }, - - getAllResponseHeaders: function getAllResponseHeaders() { - if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { - return ""; - } - - var responseHeaders = this.responseHeaders; - var headers = Object.keys(responseHeaders) - .filter(excludeSetCookie2Header) - .reduce(function(prev, header) { - var value = responseHeaders[header]; - - return `${prev}${header}: ${value}\r\n`; - }, ""); - - return headers; + Name: 'iPhone', + Category: 'category', + CouponCode: 'coupon', + Position: 1, + Price: 999, + Quantity: 1, + Sku: 'iphoneSKU', + TotalAmount: 999, + Variant: '128' + }, { + Attributes: { + 'plannedAttr1': 'val1', + 'plannedAttr2': 'val2', + 'unplannedAttr1': 'val3', + 'allowedAttr1': 'val4', + 'allowedAttr2': 'val5' }, - - setResponseBody: function setResponseBody(body) { - verifyRequestSent(this); - verifyHeadersReceived(this); - verifyResponseBodyType(body, this.responseType); - var contentType = - this.overriddenMimeType || - this.getResponseHeader("Content-Type"); - - var isTextResponse = - this.responseType === "" || this.responseType === "text"; - clearResponse(this); - if (this.async) { - var chunkSize = this.chunkSize || 10; - var index = 0; - - do { - this.readyStateChange(FakeXMLHttpRequest.LOADING); - - if (isTextResponse) { - this.responseText = this.response += body.substring( - index, - index + chunkSize - ); + Name: 'S10', + Category: 'category', + CouponCode: 'coupon', + Position: 2, + Price: 500, + Quantity: 1, + Sku: 'galaxySKU', + TotalAmount: 500, + Variant: '256' + }]; + event = { + DeviceId: 'test', + IsFirstRun: true, + EventName: null, + EventCategory: null, + MPID: testMPID, + EventAttributes: null, + SDKVersion: '1.0.0', + SourceMessageId: 'testSMID', + SessionId: 'sessionId', + SessionStartDate: 1, + Timestamp: 1, + EventDataType: null, + Debug: true, + CurrencyCode: 'usd' + }; + }); + it('should transform productAttributes if an product attribute is not planned, additionalProperties = false, and blok.ea = true', function (done) { + event.EventName = 'eCommerce - Purchase'; + event.EventCategory = Types.CommerceEventType.ProductPurchase; + event.EventDataType = Types.MessageType.Commerce; + event.ProductAction = { + ProductActionType: SDKProductActionType.Purchase, + ProductList: products + }; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformProductAttributes(event); + transformedEvent.ProductAction.ProductList[0].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr1'); + transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr2'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr1'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr2'); + done(); + }); + it('should not transform productAttributes if a product attribute is not planned, additionalProperties = false, and blok.ea = true', function (done) { + event.EventName = 'eCommerce - AddToCart'; + event.EventCategory = Types.CommerceEventType.AddToCart; + event.EventDataType = Types.MessageType.Commerce; + event.ProductAction = { + ProductActionType: SDKProductActionType.AddToCart, + ProductList: products + }; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformProductAttributes(event); + transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('unplannedAttr1'); + transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr1'); + transformedEvent.ProductAction.ProductList[0].Attributes.should.have.property('plannedAttr2'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('unplannedAttr1'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr1'); + transformedEvent.ProductAction.ProductList[1].Attributes.should.have.property('plannedAttr2'); + done(); + }); + it('should transform productAttributes in product impressions if an product attribute is not planned, additionalProperties = false, and blok.ea = true', function (done) { + event.EventName = 'eCommerce - Impression'; + event.ProductImpressions = [{ + ProductImpressionList: 'imp1', + ProductList: products + }, { + ProductImpressionList: 'imp2', + ProductList: products + }]; + event.EventCategory = Types.CommerceEventType.ProductImpression; + event.EventDataType = Types.MessageType.Commerce; + var kitBlocker = new KitBlocker(kitBlockerDataPlan, window.mParticle.getInstance()); + var transformedEvent = kitBlocker.transformProductAttributes(event); + transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.have.property('allowedAttr1', 'val4'); + transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.have.property('allowedAttr2', 'val5'); + transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductImpressions[0].ProductList[0].Attributes.should.not.have.property('unplannedAttr2'); + transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.have.property('allowedAttr1', 'val4'); + transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.have.property('allowedAttr2', 'val5'); + transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductImpressions[0].ProductList[1].Attributes.should.not.have.property('unplannedAttr2'); + transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.have.property('allowedAttr1', 'val4'); + transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.have.property('allowedAttr2', 'val5'); + transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductImpressions[1].ProductList[0].Attributes.should.not.have.property('unplannedAttr2'); + transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.have.property('allowedAttr1', 'val4'); + transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.have.property('allowedAttr2', 'val5'); + transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.not.have.property('unplannedAttr1'); + transformedEvent.ProductImpressions[1].ProductList[1].Attributes.should.not.have.property('unplannedAttr2'); + done(); + }); + }); + describe('kit blocking - integration tests', function () { + beforeEach(function () { + mockServer.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + }); + it('integration test - should log an error if the data plan has an error on it', function (done) { + var errorMessage = 'This is an error'; + window.mParticle.config.dataPlan = { + document: { + error_message: errorMessage + } + }; + var errorMessages = []; + window.mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.logger = { + error: function error(err) { + errorMessages.push(err); + } + }; + window.mParticle.init(apiKey, window.mParticle.config); + errorMessages[0].should.equal(errorMessage); + window.mParticle.config.requestConfig = false; + done(); + }); + it('integration test - should block a custom event from reaching the forwarder if event is unplanned and block.ev=true', function (done) { + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Blocked event'); + var event = window.MockForwarder1.instance.receivedEvent; + (event === null).should.equal(true); + done(); + }); + it('integration test - should allow unplanned custom events through to forwarder if blok.ev=false', function (done) { + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.config.dataPlan.document.dtpn.blok.ev = false; + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Unplanned Event'); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('EventName', 'Unplanned Event'); + // reset + window.mParticle.config.dataPlan.document.dtpn.blok.ev = true; + done(); + }); + it('integration test - should block an unplanned attribute from being set on the forwarder if additionalProperties = false and blok.ua = true', function (done) { + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserAttribute('unplannedAttr', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', false); + done(); + }); + it('integration test - should allow an unplanned attribute to be set on forwarder if additionalProperties = true and blok.ua = true', function (done) { + var userAttributeDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_attributes'; + }); + userAttributeDataPoint.validator.definition.additionalProperties = true; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserAttribute('unplanned but unblocked', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + userAttributeDataPoint.validator.definition.additionalProperties = false; + done(); + }); + it('integration test - should allow an unplanned user attribute to be set on the forwarder if blok=false', function (done) { + window.mParticle.config.dataPlan.document.dtpn.blok.ua = false; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserAttribute('unplanned but not blocked', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + window.mParticle.config.dataPlan.document.dtpn.blok.ua = true; + done(); + }); + it('integration test - should block an unplanned attribute set via setUserTag from being set on the forwarder if additionalProperties = false and blok.ua = true', function (done) { + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserTag('unplannedAttr', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', false); + done(); + }); + it('integration test - should allow an unplanned attribute set via setUserTag to be set on forwarder if additionalProperties = true and blok.ua = true', function (done) { + var userAttributeDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_attributes'; + }); + userAttributeDataPoint.validator.definition.additionalProperties = true; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserTag('unplanned but unblocked', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + userAttributeDataPoint.validator.definition.additionalProperties = false; + done(); + }); + it('integration test - should allow an unplanned user attribute set via setUserTag to be set on the forwarder if blok=false', function (done) { + window.mParticle.config.dataPlan.document.dtpn.blok.ua = false; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.getCurrentUser().setUserTag('unplanned but not blocked', true); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + window.mParticle.config.dataPlan.document.dtpn.blok.ua = true; + done(); + }); + describe('integration tests - user identity related', function () { + var userIdentityRequest; + beforeEach(function () { + ['login', 'logout', 'modify'].forEach(function (identityMethod) { + mockServer.respondWith(urls[identityMethod], [200, {}, JSON.stringify({ + mpid: 'testMPID', + is_logged_in: true + })]); + }); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + userIdentityRequest = { + userIdentities: { + google: 'test', + customerid: 'id1', + other: 'id2', + yahoo: 'yahoo1', + email: 'email@gmail.com' + } + }; + }); + it('integration test - should not block any unplanned user identities to the forwarder when blok.id = true and additionalProperties = true', function (done) { + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.login({ + userIdentities: { + customerid: 'customerid1', + email: 'email@gmail.com', + 'google': 'GoogleId' + } + }); + window.mParticle.logEvent('something something something', Types.EventType.Navigation); + var event = window.MockForwarder1.instance.receivedEvent; + event.UserIdentities.find(function (UI) { + return UI.Type === 1; + }).should.have.property('Identity', 'customerid1'); + event.UserIdentities.find(function (UI) { + return UI.Type === 7; + }).should.have.property('Identity', 'email@gmail.com'); + event.UserIdentities.find(function (UI) { + return UI.Type === 4; + }).should.have.property('Identity', 'GoogleId'); + done(); + }); + it('integration test - should block user identities to the forwarder when additional properties = false and blok.id = true', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.login({ + userIdentities: { + customerid: 'customerid1', + email: 'email@gmail.com', + 'google': 'GoogleId' + } + }); + window.mParticle.logEvent('something something something', Types.EventType.Navigation); + var event = window.MockForwarder1.instance.receivedEvent; + event.UserIdentities.find(function (UI) { + return UI.Type === 1; + }).should.have.property('Identity', 'customerid1'); + event.UserIdentities.find(function (UI) { + return UI.Type === 7; + }).should.have.property('Identity', 'email@gmail.com'); + (event.UserIdentities.find(function (UI) { + return UI.Type === 4; + }) === undefined).should.not.have.property('Identity', 'GoogleId'); + // reset + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + it('integration test - should not block identities from being passed to onUserIdentified/onLogoutComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)', function (done) { + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.logout(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.have.property('yahoo', 'yahoo1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + var onLogoutCompleteUserIdentities = window.MockForwarder1.instance.onLogoutCompleteUser.getUserIdentities().userIdentities; + onLogoutCompleteUserIdentities.should.not.have.property('google'); + onLogoutCompleteUserIdentities.should.have.property('customerid', 'id1'); + onLogoutCompleteUserIdentities.should.have.property('other', 'id2'); + onLogoutCompleteUserIdentities.should.have.property('yahoo', 'yahoo1'); + onLogoutCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + done(); + }); + it('integration test - should block identities from being passed to onUserIdentified/onLogoutComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.logout(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.not.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.not.have.property('yahoo'); + var onLogoutCompleteUserIdentities = window.MockForwarder1.instance.onLogoutCompleteUser.getUserIdentities().userIdentities; + onLogoutCompleteUserIdentities.should.have.property('customerid', 'id1'); + onLogoutCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + onLogoutCompleteUserIdentities.should.not.have.property('google'); + onLogoutCompleteUserIdentities.should.not.have.property('other', 'id2'); + onLogoutCompleteUserIdentities.should.not.have.property('yahoo'); + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + it('integration test - should not block identities from being passed to onUserIdentified/onModifyComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)', function (done) { + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.modify(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.have.property('yahoo', 'yahoo1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + var onModifyCompleteUserIdentities = window.MockForwarder1.instance.onModifyCompleteUser.getUserIdentities().userIdentities; + onModifyCompleteUserIdentities.should.not.have.property('google'); + onModifyCompleteUserIdentities.should.have.property('customerid', 'id1'); + onModifyCompleteUserIdentities.should.have.property('other', 'id2'); + onModifyCompleteUserIdentities.should.have.property('yahoo', 'yahoo1'); + onModifyCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + done(); + }); + it('integration test - should block identities from being passed to onUserIdentified/onModifyComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.modify(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.not.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.not.have.property('yahoo'); + var onModifyCompleteUserIdentities = window.MockForwarder1.instance.onModifyCompleteUser.getUserIdentities().userIdentities; + onModifyCompleteUserIdentities.should.have.property('customerid', 'id1'); + onModifyCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + onModifyCompleteUserIdentities.should.not.have.property('google'); + onModifyCompleteUserIdentities.should.not.have.property('other', 'id2'); + onModifyCompleteUserIdentities.should.not.have.property('yahoo'); + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + it('integration test - should not block identities from being passed to onUserIdentified/onIdentifyComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)', function (done) { + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.identifyRequest = userIdentityRequest; + window.mParticle.init(apiKey, window.mParticle.config); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.have.property('yahoo', 'yahoo1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + var onIdentifyCompleteUserIdentities = window.MockForwarder1.instance.onIdentifyCompleteUser.getUserIdentities().userIdentities; + onIdentifyCompleteUserIdentities.should.not.have.property('google'); + onIdentifyCompleteUserIdentities.should.have.property('customerid', 'id1'); + onIdentifyCompleteUserIdentities.should.have.property('other', 'id2'); + onIdentifyCompleteUserIdentities.should.have.property('yahoo', 'yahoo1'); + onIdentifyCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + done(); + }); + it('integration test - should block identities from being passed to onUserIdentified/onIdentifyComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.identify(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.not.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.not.have.property('yahoo'); + var onIdentifyCompleteUserIdentities = window.MockForwarder1.instance.onIdentifyCompleteUser.getUserIdentities().userIdentities; + onIdentifyCompleteUserIdentities.should.have.property('customerid', 'id1'); + onIdentifyCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + onIdentifyCompleteUserIdentities.should.not.have.property('google'); + onIdentifyCompleteUserIdentities.should.not.have.property('other', 'id2'); + onIdentifyCompleteUserIdentities.should.not.have.property('yahoo'); + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + it('integration test - should not block identities from being passed to onUserIdentified/onLoginComplete if blok.id = true and additionalProperties = true (in addition to having a filtered user identity list)', function (done) { + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.login(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.have.property('yahoo', 'yahoo1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + var onLoginCompleteUserIdentities = window.MockForwarder1.instance.onLoginCompleteUser.getUserIdentities().userIdentities; + onLoginCompleteUserIdentities.should.not.have.property('google'); + onLoginCompleteUserIdentities.should.have.property('customerid', 'id1'); + onLoginCompleteUserIdentities.should.have.property('other', 'id2'); + onLoginCompleteUserIdentities.should.have.property('yahoo', 'yahoo1'); + onLoginCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + done(); + }); + it('integration test - should block identities from being passed to onUserIdentified/onLoginComplete if blok.id = true and additionalProperties = false (in addition to having a filtered user identity list)', function (done) { + var userIdentityDataPoint = dtpn.vers.version_document.data_points.find(function (dataPoint) { + return dataPoint.match.type === 'user_identities'; + }); + userIdentityDataPoint.validator.definition.additionalProperties = false; + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + var config1 = forwarderDefaultConfiguration$4('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.Identity.login(userIdentityRequest); + var onUserIdentifiedUserIdentities = window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities; + onUserIdentifiedUserIdentities.should.have.property('customerid', 'id1'); + onUserIdentifiedUserIdentities.should.have.property('email', 'email@gmail.com'); + onUserIdentifiedUserIdentities.should.not.have.property('google'); + onUserIdentifiedUserIdentities.should.not.have.property('other', 'id2'); + onUserIdentifiedUserIdentities.should.not.have.property('yahoo'); + var onLoginCompleteUserIdentities = window.MockForwarder1.instance.onLoginCompleteUser.getUserIdentities().userIdentities; + onLoginCompleteUserIdentities.should.have.property('customerid', 'id1'); + onLoginCompleteUserIdentities.should.have.property('email', 'email@gmail.com'); + onLoginCompleteUserIdentities.should.not.have.property('google'); + onLoginCompleteUserIdentities.should.not.have.property('other', 'id2'); + onLoginCompleteUserIdentities.should.not.have.property('yahoo'); + userIdentityDataPoint.validator.definition.additionalProperties = true; + done(); + }); + }); + describe('integration tests - product attribute related', function () { + var prodattr1, prodattr2, product1, product2, transactionAttributes, customAttributes, customFlags; + beforeEach(function () { + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + prodattr1 = { + 'plannedAttr1': 'val1', + 'plannedAttr2': 'val2', + 'unplannedAttr1': 'val3' + }; + prodattr2 = { + 'plannedAttr1': 'val1', + 'plannedAttr2': 'val2', + 'unplannedAttr1': 'val3' + }; + product1 = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999, 1, 'variant', 'category', 'brand', 1, 'coupon', prodattr1); + product2 = window.mParticle.eCommerce.createProduct('galaxy', 'galaxySKU', 799, 1, 'variant', 'category', 'brand', 1, 'coupon', prodattr2); + transactionAttributes = { + Id: 'foo-transaction-id', + Revenue: 430.00, + Tax: 30 + }; + customAttributes = { + sale: true + }; + customFlags = { + 'Google.Category': 'travel' + }; + }); + it('integration test - should block any unplanned product attributes from reaching the forwarder if additionalProperties = false and block.ea=true', function (done) { + window.mParticle.eCommerce.logProductAction(window.mParticle.ProductActionType['Purchase'], [product1, product2], customAttributes, customFlags, transactionAttributes); + var event = window.MockForwarder1.instance.receivedEvent; + var products = event.ProductAction.ProductList; + products[0].Attributes.should.have.property('plannedAttr1', 'val1'); + products[0].Attributes.should.have.property('plannedAttr2', 'val2'); + products[0].Attributes.should.not.have.property('unplannedAttr1'); + products[1].Attributes.should.have.property('plannedAttr1', 'val1'); + products[1].Attributes.should.have.property('plannedAttr2', 'val2'); + products[1].Attributes.should.not.have.property('unplannedAttr1'); + done(); + }); + it('integration test - should not block unplanned product attributes from reaching the forwarder if additionalProperties = true and block.ea=true', function (done) { + window.mParticle.eCommerce.logProductAction(window.mParticle.ProductActionType['AddToCart'], [product1, product2], customAttributes, customFlags, transactionAttributes); + var event = window.MockForwarder1.instance.receivedEvent; + var products = event.ProductAction.ProductList; + products[0].Attributes.should.have.property('plannedAttr1', 'val1'); + products[0].Attributes.should.have.property('plannedAttr2', 'val2'); + products[0].Attributes.should.have.property('unplannedAttr1'); + products[1].Attributes.should.have.property('plannedAttr1', 'val1'); + products[1].Attributes.should.have.property('plannedAttr2', 'val2'); + products[1].Attributes.should.have.property('unplannedAttr1'); + done(); + }); + }); + describe('integration tests - client passed in data plan', function () { + var clientProvidedDataPlan = { + version_document: { + data_points: [{ + match: { + // @ts-ignore (fix this after DataPlanMatchType importing works) + type: 'custom_event', + criteria: { + event_name: 'locationEvent123', + custom_event_type: 'location' + } + }, + validator: { + // @ts-ignore (fix this after DataPlanMatchType importing works) + type: 'json_schema', + definition: { + properties: { + data: { + properties: { + custom_attributes: { + additionalProperties: false, + properties: { + foo: {}, + 'foo foo': {}, + 'foo number': {} + } + } } - index += chunkSize; - } while (index < body.length); - } - - this.response = convertResponseBody( - this.responseType, - contentType, - body - ); - if (isTextResponse) { - this.responseText = this.response; + } + } + } } + }] + } + }; + it('integration test - should log an error if the client passes a data plan without the proper keys', function (done) { + // @ts-ignore - purposely leaving out blockUserIdentities as a key below + window.mParticle.config.dataPlanOptions = { + dataPlanVersion: clientProvidedDataPlan, + blockUserAttributes: true, + blockEventAttributes: true, + blockEvents: true + }; + var errorMessages = []; + window.mParticle._resetForTests(MPConfig); + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.logger = { + error: function error(err) { + errorMessages.push(err); + } + }; + window.mParticle.init(apiKey, window.mParticle.config); + errorMessages[0].should.equal('Ensure your config.dataPlanOptions object has the following keys: a "dataPlanVersion" object, and "blockUserAttributes", "blockEventAttributes", "blockEvents", "blockUserIdentities" booleans'); + done(); + }); + it('integration test - should prioritize data plan from config.dataPlanOptions over server provided data plan', function (done) { + window.mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.config.dataPlanOptions = { + dataPlanVersion: clientProvidedDataPlan, + blockUserAttributes: true, + blockEventAttributes: true, + blockEvents: true, + blockUserIdentities: true + }; + var logs = []; + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.logger = { + verbose: function verbose(msg) { + logs.push(msg); + } + }; + window.mParticle.init(apiKey, window.mParticle.config); + logs.includes('Customer provided data plan found').should.equal(true); + logs.includes('Data plan found from mParticle.js').should.equal(false); + logs.includes('Data plan found from /config').should.equal(false); + // this event is part of the server provided data plan (dataPlan.json) which is being ignored, so the event doesn't go through; + window.mParticle.logEvent('something something something', Types.EventType.Navigation); + var event = window.MockForwarder1.instance.receivedEvent; + (event === null).should.equal(true); + // this event is part of the clientGeneratedDataPlan + window.mParticle.logEvent('locationEvent123', Types.EventType.Location, { + unplannedAttr: 'test', + foo: 'hi' + }); + event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('EventName', 'locationEvent123'); + event.EventAttributes.should.have.property('foo', 'hi'); + event.EventAttributes.should.not.have.property('unplannedAttr'); + done(); + }); + it('integration test - should block or unblock planned events', function (done) { + window.mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + delete window.mParticle.config.dataPlan; + window.mParticle.config.dataPlanOptions = { + dataPlanVersion: clientProvidedDataPlan, + blockUserAttributes: true, + blockEventAttributes: true, + blockEvents: true, + blockUserIdentities: true + }; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Blocked event'); + var event = window.MockForwarder1.instance.receivedEvent; + (event === null).should.equal(true); + window.mParticle.logEvent('locationEvent123', Types.EventType.Location, { + unplannedAttr: 'test', + foo: 'hi' + }); + event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('EventName', 'locationEvent123'); + event.EventAttributes.should.have.property('foo', 'hi'); + event.EventAttributes.should.not.have.property('unplannedAttr'); + done(); + }); + }); + describe('integration tests - self hosting set up', function () { + it('should create a proper kitblocker on a self hosted set up', function (done) { + mockServer.respondWith("".concat(urls.config, "&plan_id=robs_plan&plan_version=1"), [200, {}, JSON.stringify({ + dataPlanResult: dataPlan$1 + })]); + window.mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + //requestConfig = true indicates self hosted + window.mParticle.config.requestConfig = true; + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.dataPlan = { + planId: 'robs_plan', + planVersion: 1 + }; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Blocked event'); + var event = window.MockForwarder1.instance.receivedEvent; + (event === null).should.equal(true); + window.mParticle.config.requestConfig = false; + done(); + }); + it('should log an error if the data plan has an error on it', function (done) { + var errorMessage = 'This is an error'; + mockServer.respondWith("".concat(urls.config, "&plan_id=robs_plan&plan_version=1"), [200, {}, JSON.stringify({ + dataPlanResult: { + error_message: errorMessage + } + })]); + var errorMessages = []; + window.mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$6(); + window.mParticle.addForwarder(mockForwarder); + //requestConfig = true indicates self hosted + window.mParticle.config.requestConfig = true; + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.dataPlan = { + planId: 'robs_plan', + planVersion: 1 + }; + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$4('MockForwarder')); + window.mParticle.config.logLevel = 'verbose'; + window.mParticle.config.logger = { + error: function error(err) { + errorMessages.push(err); + } + }; + window.mParticle.init(apiKey, window.mParticle.config); + errorMessages[0].should.equal(errorMessage); + window.mParticle.config.requestConfig = false; + done(); + }); + }); + }); + }); - if (this.responseType === "document") { - this.responseXML = this.response; - } else if ( - this.responseType === "" && - isXmlContentType(contentType) - ) { - this.responseXML = FakeXMLHttpRequest.parseXML( - this.responseText - ); - } - this.readyStateChange(FakeXMLHttpRequest.DONE); + var findCookie$1 = TestsCore.findCookie, + getLocalStorage$4 = TestsCore.getLocalStorage, + getLocalStorageProducts$2 = TestsCore.getLocalStorageProducts, + setCookie$1 = TestsCore.setCookie, + setLocalStorage$3 = TestsCore.setLocalStorage, + findBatch$5 = TestsCore.findBatch; + var mockServer$c; + describe('migrations and persistence-related', function () { + beforeEach(function () { + client.post(urls.events, 200); + mockServer$c = sinon$1.createFakeServer(); + mockServer$c.respondImmediately = true; + mockServer$c.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle$5.init(apiKey, mParticle$5.config); + }); + afterEach(function () { + mockServer$c.restore(); + client.restore(); + }); + it('should move new schema from cookies to localStorage with useCookieStorage = false', function (done) { + mParticle$5._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'sid', + les: new Date().getTime() + }, + testMPID: { + ui: { + 1: '123' + } + }, + cu: testMPID + }); + setCookie$1(workspaceCookieName, cookies); + var beforeInitCookieData = findCookie$1(workspaceCookieName); + mParticle$5.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + var localStorageData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + var afterInitCookieData = findCookie$1(); + beforeInitCookieData[testMPID].ui.should.have.property('1', '123'); + localStorageData[testMPID].ua.should.have.property('gender', 'male'); + localStorageData[testMPID].ui.should.have.property('1', '123'); + expect(afterInitCookieData).to.not.be.ok; + done(); + }); + it('should migrate localStorage to cookies with useCookieStorage = true', function (done) { + mParticle$5._resetForTests(MPConfig); + setLocalStorage$3(); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + var localStorageData = localStorage.getItem('mprtcl-api'); + var cookieData = findCookie$1(); + expect(localStorageData).to.not.be.ok; + cookieData[testMPID].ua.should.have.property('gender', 'male'); + cookieData[testMPID].ui.should.have.property('1', 'testuser@mparticle.com'); + done(); + }); + it('localStorage - should key cookies on mpid on first run', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + var cookies1 = mParticle$5.getInstance()._Persistence.getLocalStorage(); + var props1 = ['ie', 'sa', 'ua', 'ui', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'csd', 'mpid', 'cp', 'sid', 'c']; + props1.forEach(function (prop) { + cookies1.should.not.have.property(prop); + }); + cookies1.should.have.property('cu', testMPID, 'gs'); + cookies1.should.have.property(testMPID); + var props2 = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + var cookies2 = mParticle$5.getInstance()._Persistence.getLocalStorage(); + cookies2.should.have.property('cu', 'otherMPID', 'gs'); + props2.forEach(function (prop) { + cookies1[testMPID].should.not.have.property(prop); + cookies2[testMPID].should.not.have.property(prop); + cookies2['otherMPID'].should.not.have.property(prop); + }); + done(); + }); + it('cookies - should key cookies on mpid when there are no cookies yet', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var cookies1 = findCookie$1(); + var props1 = ['ie', 'sa', 'ua', 'ui', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'csd', 'mpid', 'cp', 'sid', 'c']; + cookies1.should.have.property('cu', testMPID, 'gs'); + props1.forEach(function (prop) { + cookies1.should.not.have.property(prop); + }); + var props2 = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + var cookies2 = findCookie$1(); + cookies2.should.have.property('cu', 'otherMPID', testMPID); + props2.forEach(function (prop) { + cookies1[testMPID].should.not.have.property(prop); + cookies2[testMPID].should.not.have.property(prop); + cookies2['otherMPID'].should.not.have.property(prop); + }); + done(); + }); + it('puts data into cookies when init-ing with useCookieStorage = true', function (done) { + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var cookieData = findCookie$1(); + var localStorageData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + cookieData.should.have.properties(['gs', 'cu', testMPID]); + var props = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props.forEach(function (prop) { + cookieData[testMPID].should.not.have.property(prop); + }); + expect(localStorageData).to.not.be.ok; + done(); + }); + it('puts data into localStorage when running initializeStorage with useCookieStorage = false', function (done) { + mParticle$5.init(apiKey, mParticle$5.config); + var cookieData = mParticle$5.getInstance()._Persistence.getCookie(); + var localStorageData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + expect(localStorageData).to.include.keys(['gs', 'cu', testMPID]); + var props = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props.forEach(function (prop) { + expect(localStorageData[testMPID]).to.not.have.property(prop); + }); + expect(cookieData).to.not.be.ok; + done(); + }); + it('puts data into cookies when updating persistence with useCookieStorage = true', function (done) { + var cookieData; + var localStorageData; + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + cookieData = findCookie$1(); + expect(cookieData).to.include.keys('gs', 'cu', testMPID); + localStorageData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + var props = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props.forEach(function (prop) { + cookieData[testMPID].should.not.have.property(prop); + }); + expect(localStorageData).to.not.be.ok; + done(); + }); + it('puts data into localStorage when updating persistence with useCookieStorage = false', function (done) { + var cookieData; + var localStorageData; + // Flush out anything in expire before updating in order to silo testing persistence.update() + // mParticle.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + localStorageData = getLocalStorage$4(); + cookieData = findCookie$1(); + expect(localStorageData).to.have.include.keys('gs', 'cu', testMPID); + var props = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props.forEach(function (prop) { + localStorageData[testMPID].should.not.have.property(prop); + }); + expect(cookieData).to.not.be.ok; + done(); + }); + it('should revert to cookie storage if localStorage is not available and useCookieStorage is set to false', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.getInstance()._Persistence.determineLocalStorageAvailability = function () { + return false; + }; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + var cookieData = findCookie$1(); + cookieData[testMPID].ua.should.have.property('gender', 'male'); + mParticle$5.getInstance()._Persistence.determineLocalStorageAvailability = function () { + return true; + }; + done(); + }); + it('should set certain attributes onto global localStorage, while setting user specific to the MPID', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.setIntegrationAttribute(128, { + MCID: 'abcedfg' + }); + var data = getLocalStorage$4(); + data.cu.should.equal(testMPID); + data.gs.should.have.properties(['sid', 'ie', 'dt', 'cgid', 'das', 'les', 'ia']); + data.testMPID.ua.should.have.property('gender', 'male'); + done(); + }); + it('should save integration attributes properly on a page refresh', function (done) { + mParticle$5.setIntegrationAttribute(128, { + MCID: 'abcedfg' + }); + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.logEvent('Test Event'); + var testEvent = findBatch$5(client._calls, 'Test Event'); + testEvent.integration_attributes.should.have.property('128'); + testEvent.integration_attributes['128'].should.have.property('MCID', 'abcedfg'); + done(); + }); + it('should set certain attributes onto global cookies, while setting user specific to the MPID', function (done) { + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + var data = findCookie$1(); + data.cu.should.equal(testMPID); + data.gs.should.have.properties(['sid', 'ie', 'dt', 'cgid', 'das', 'les']); + data.testMPID.ua.should.have.property('gender', 'male'); + done(); + }); + it('should add new MPID to cookies when returned MPID does not match anything in cookies, and have empty UI and UA', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + var user1 = { + userIdentities: { + customerid: 'customerid1' + } + }; + mParticle$5.Identity.login(user1); + var user1Result = mParticle$5.getInstance().Identity.getCurrentUser().getUserIdentities(); + user1Result.userIdentities.customerid.should.equal('customerid1'); + mockServer$c.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle$5.Identity.logout(); + var user2Result = mParticle$5.getInstance().Identity.getCurrentUser(); + Object.keys(user2Result.getUserIdentities().userIdentities).length.should.equal(0); + var localStorageData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + localStorageData.cu.should.equal('mpid2'); + localStorageData.testMPID.should.not.have.property('ui'); + localStorageData.mpid1.ui[1].should.equal('customerid1'); + localStorageData.mpid2.should.not.have.property('ui'); + done(); + }); + it('should have the same currentUserMPID as the last browser session when a reload occurs and no identityRequest is provided', function (done) { + mParticle$5._resetForTests(MPConfig); + var user1 = { + userIdentities: { + customerid: '1' + } + }; + var user2 = { + userIdentities: { + customerid: '2' + } + }; + var user3 = { + userIdentities: { + customerid: '3' + } + }; + mParticle$5.init(apiKey, mParticle$5.config); + var data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + data.cu.should.equal(testMPID); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mParticle$5.Identity.login(user1); + var user1Data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user1Data.cu.should.equal('mpid1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle$5.Identity.login(user2); + var user2Data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user2Data.cu.should.equal('mpid2'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid3', + is_logged_in: false + })]); + mParticle$5.Identity.login(user3); + var user3data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user3data.cu.should.equal('mpid3'); + mParticle$5.init(apiKey, mParticle$5.config); + var data3 = mParticle$5.getInstance()._Persistence.getLocalStorage(); + data3.cu.should.equal('mpid3'); + done(); + }); + it('should transfer user attributes and revert to user identities properly', function (done) { + mParticle$5._resetForTests(MPConfig); + var user1 = { + userIdentities: { + customerid: 'customerid1' + } + }; + var user2 = { + userIdentities: { + customerid: 'customerid2' + } + }; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test1', 'test1'); + var data = getLocalStorage$4(); + data.cu.should.equal(testMPID); + data.testMPID.ua.should.have.property('test1', 'test1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mockServer$c.respondWith('https://identity.mparticle.com/v1/mpid1/modify', [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mParticle$5.Identity.login(user1); + mParticle$5.Identity.modify({ + userIdentities: { + email: 'email@test.com' + } + }); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test2', 'test2'); + var user1Data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user1Data.cu.should.equal('mpid1'); + user1Data.mpid1.ua.should.have.property('test2', 'test2'); + user1Data.mpid1.ui.should.have.property('7', 'email@test.com'); + user1Data.mpid1.ui.should.have.property('1', 'customerid1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle$5.Identity.login(user2); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('test3', 'test3'); + var user2Data = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user2Data.cu.should.equal('mpid2'); + user2Data.mpid2.ui.should.have.property('1', 'customerid2'); + user2Data.mpid2.ua.should.have.property('test3', 'test3'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mParticle$5.Identity.login(user1); + var user1RelogInData = mParticle$5.getInstance()._Persistence.getLocalStorage(); + user1RelogInData.cu.should.equal('mpid1'); + user1RelogInData.mpid1.ui.should.have.property('1', 'customerid1'); + user1RelogInData.mpid1.ui.should.have.property('7', 'email@test.com'); + Object.keys(user1RelogInData.mpid1.ui).length.should.equal(2); + user1RelogInData.mpid1.ua.should.have.property('test2', 'test2'); + done(); + }); + it('should remove MPID as keys if the cookie size is beyond the setting', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.maxCookieSize = 700; + var cookies = { + gs: { + csm: ['mpid1', 'mpid2', 'mpid3'], + sid: 'abcd', + ie: true, + dt: apiKey, + cgid: 'cgid1', + das: 'das1' + }, + cu: 'mpid3', + l: false, + mpid1: { + ua: { + gender: 'female', + age: 29, + height: '65', + color: 'blue', + id: 'abcdefghijklmnopqrstuvwxyz' }, - - respond: function respond(status, headers, body) { - this.responseURL = this.url; - - this.setStatus(status); - this.setResponseHeaders(headers || {}); - this.setResponseBody(body || ""); + ui: { + 1: 'customerid123', + 2: 'facebookid123' + } + }, + mpid2: { + ua: { + gender: 'male', + age: 20, + height: '68', + color: 'red' }, - - uploadProgress: function uploadProgress(progressEventRaw) { - if (supportsProgress) { - this.upload.dispatchEvent( - new sinonEvent.ProgressEvent( - "progress", - progressEventRaw, - this.upload - ) - ); - } + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz' + } + }, + mpid3: { + ua: { + gender: 'male', + age: 20, + height: '68', + color: 'red' }, - - downloadProgress: function downloadProgress(progressEventRaw) { - if (supportsProgress) { - this.dispatchEvent( - new sinonEvent.ProgressEvent( - "progress", - progressEventRaw, - this - ) - ); - } + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz' + } + } + }; + var expires = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000).toUTCString(); + var cookiesWithExpiration = mParticle$5.getInstance()._Persistence.reduceAndEncodePersistence(cookies, expires, 'testDomain', mParticle$5.config.maxCookieSize); + var cookiesWithoutExpiration = cookiesWithExpiration.slice(0, cookiesWithExpiration.indexOf(';expires')); + var cookiesResult = JSON.parse(mParticle$5.getInstance() + // TODO: Refactor or rename this to highlight that it is + // a string function + ._Persistence.decodePersistence(cookiesWithoutExpiration)); + expect(cookiesResult['mpid1']).to.not.be.ok; + expect(cookiesResult['mpid2']).be.ok; + expect(cookiesResult['mpid3']).be.ok; + cookiesResult.gs.csm.length.should.equal(3); + cookiesResult.gs.csm[0].should.equal('mpid1'); + cookiesResult.gs.csm[1].should.equal('mpid2'); + cookiesResult.gs.csm[2].should.equal('mpid3'); + done(); + }); + it('integration test - will change the order of the CSM when a previous MPID logs in again', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = true; + mParticle$5.config.maxCookieSize = 1000; + mParticle$5.init(apiKey, mParticle$5.config); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + var cookieData = findCookie$1(); + cookieData.gs.csm[0].should.be.equal('testMPID'); + cookieData.gs.csm[1].should.be.equal('MPID1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + cookieData = findCookie$1(); + cookieData.gs.csm[0].should.be.equal('testMPID'); + cookieData.gs.csm[1].should.be.equal('MPID1'); + cookieData.gs.csm[2].should.be.equal('MPID2'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'testMPID', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + cookieData = findCookie$1(); + cookieData.gs.csm[0].should.be.equal('MPID1'); + cookieData.gs.csm[1].should.be.equal('MPID2'); + cookieData.gs.csm[2].should.be.equal('testMPID'); + done(); + }); + it('integration test - should remove a previous MPID as a key from cookies if new user attribute added and exceeds the size of the max cookie size', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = true; + mParticle$5.config.maxCookieSize = 650; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '68'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '60'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id2'); + var cookieData = findCookie$1(); + cookieData.gs.csm[0].should.equal('testMPID'); + cookieData.gs.csm[1].should.equal('MPID1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 45); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '80'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + //this last one puts us over the maxcookiesize threshold and removes 'testMPID' from cookie + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id3'); + cookieData = findCookie$1(); + expect(cookieData['testMPID']).to.not.be.ok; + cookieData['MPID1'].ua.should.have.property('id', 'id2'); + cookieData['MPID1'].ua.should.have.property('gender', 'male'); + cookieData['MPID1'].ua.should.have.property('age', 30); + cookieData['MPID1'].ua.should.have.property('height', '60'); + cookieData['MPID1'].ua.should.have.property('color', 'green'); + cookieData['MPID2'].ua.should.have.property('id', 'id3'); + cookieData['MPID2'].ua.should.have.property('gender', 'female'); + cookieData['MPID2'].ua.should.have.property('age', 45); + cookieData['MPID2'].ua.should.have.property('height', '80'); + cookieData['MPID2'].ua.should.have.property('color', 'green'); + done(); + }); + it('should remove a random MPID from storage if there is a new session and there are no other MPIDs in currentSessionMPIDs except for the currentUser mpid', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.maxCookieSize = 400; + var cookies = { + gs: { + csm: ['mpid3'], + sid: 'abcd', + ie: true, + dt: apiKey, + cgid: 'cgid1', + das: 'das1' + }, + cu: 'mpid3', + l: false, + mpid1: { + ua: { + gender: 'female', + age: 29, + height: '65', + color: 'blue', + id: 'abcdefghijklmnopqrstuvwxyz' }, - - uploadError: function uploadError(error) { - if (supportsCustomEvent) { - this.upload.dispatchEvent( - new sinonEvent.CustomEvent("error", { detail: error }) - ); - } + ui: { + 1: 'customerid123', + 2: 'facebookid123' + } + }, + mpid2: { + ua: { + gender: 'male', + age: 20, + height: '68', + color: 'red' }, - - overrideMimeType: function overrideMimeType(type) { - if (this.readyState >= FakeXMLHttpRequest.LOADING) { - throw new Error("INVALID_STATE_ERR"); - } - this.overriddenMimeType = type; + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz' + } + }, + mpid3: { + ua: { + gender: 'male', + age: 20, + height: '68', + color: 'red' + }, + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz' } + } + }; + var expires = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000).toString(); + var cookiesWithExpiration = mParticle$5.getInstance()._Persistence.reduceAndEncodePersistence(cookies, expires, 'testDomain', mParticle$5.config.maxCookieSize); + var cookiesWithoutExpiration = cookiesWithExpiration.slice(0, cookiesWithExpiration.indexOf(';expires')); + var cookiesResult = JSON.parse(mParticle$5.getInstance()._Persistence.decodePersistence(cookiesWithoutExpiration)); + expect(cookiesResult['mpid1']).to.not.be.ok; + expect(cookiesResult['mpid2']).to.not.be.ok; + expect(cookiesResult['mpid3']).be.ok; + cookiesResult.gs.csm[0].should.equal('mpid3'); + cookiesResult.should.have.property('mpid3'); + // TODO: Refactor tests to include this in setup/teardown + mParticle$5.config.maxCookieSize = 3000; + done(); + }); + it('integration test - should remove a random MPID from storage if there is a new session and there are no MPIDs in currentSessionMPIDs', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = true; + mParticle$5.config.maxCookieSize = 600; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '68'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '60'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id2'); + var cookieData = findCookie$1(); + cookieData.gs.csm[0].should.equal('testMPID'); + cookieData.gs.csm[1].should.equal('MPID1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.endSession(); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 45); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '80'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id3'); + cookieData = findCookie$1(); + expect(cookieData['testMPID']).to.not.be.ok; + cookieData['MPID1'].ua.should.have.property('id', 'id2'); + cookieData['MPID1'].ua.should.have.property('gender', 'male'); + cookieData['MPID1'].ua.should.have.property('age', 30); + cookieData['MPID1'].ua.should.have.property('height', '60'); + cookieData['MPID1'].ua.should.have.property('color', 'green'); + cookieData['MPID2'].ua.should.have.property('id', 'id3'); + cookieData['MPID2'].ua.should.have.property('gender', 'female'); + cookieData['MPID2'].ua.should.have.property('age', 45); + cookieData['MPID2'].ua.should.have.property('height', '80'); + cookieData['MPID2'].ua.should.have.property('color', 'green'); + done(); + }); + it('integration test - migrates a large localStorage cookie to cookies and properly remove MPIDs', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = false; + mParticle$5.config.maxCookieSize = 700; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '68'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '60'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id2'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 45); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '80'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id3'); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var cookieData = findCookie$1(); + expect(cookieData['testMPID']).to.not.be.ok; + cookieData['MPID1'].ua.should.have.property('id', 'id2'); + cookieData['MPID2'].ua.should.have.property('id'); + done(); + }); + it('integration test - migrates all cookie MPIDs to localStorage', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '68'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '60'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id2'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 45); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '80'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id3'); + mParticle$5.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + var lsData = getLocalStorage$4(v4LSKey); + lsData.should.have.properties(['gs', 'cu', 'testMPID', 'MPID1', 'MPID2']); + lsData['testMPID'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + lsData['MPID1'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + lsData['MPID2'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + done(); + }); + it('integration test - migrates all LS MPIDs to cookies', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.useCookieStorage = false; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '68'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id1'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 30); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '60'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id2'); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('age', 45); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('height', '80'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('color', 'green'); + mParticle$5.getInstance().Identity.getCurrentUser().setUserAttribute('id', 'id3'); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var cookieData = findCookie$1(); + cookieData.should.have.properties(['gs', 'cu', 'testMPID', 'MPID1', 'MPID2']); + cookieData['testMPID'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + cookieData['MPID1'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + cookieData['MPID2'].ua.should.have.properties(['gender', 'age', 'height', 'color', 'id']); + done(); + }); + it('get/set consent state for single user', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + var consentState = mParticle$5.getInstance().Identity.getCurrentUser().getConsentState(); + expect(consentState).to.equal(null); + consentState = mParticle$5.Consent.createConsentState(); + consentState.addGDPRConsentState('foo purpose', mParticle$5.Consent.createGDPRConsent(true, 10)); + mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState); + var storedConsentState = mParticle$5.getInstance().Identity.getCurrentUser().getConsentState(); + storedConsentState.should.be.ok(); + storedConsentState.getGDPRConsentState().should.have.property('foo purpose'); + storedConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Consented', true); + storedConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Timestamp', 10); + done(); + }); + it('get/set consent state for multiple users', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + var user1StoredConsentState = mParticle$5.getInstance().Identity.getCurrentUser().getConsentState(); + expect(user1StoredConsentState).to.equal(null); + var consentState = mParticle$5.Consent.createConsentState(); + consentState.addGDPRConsentState('foo purpose', mParticle$5.Consent.createGDPRConsent(true, 10)); + mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState); + mParticle$5._resetForTests(MPConfig, true); + mParticle$5.init(apiKey, mParticle$5.config); + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle$5.Identity.login(); + var user2StoredConsentState = mParticle$5.getInstance().Identity.getCurrentUser().getConsentState(); + expect(user2StoredConsentState).to.equal(null); + consentState.removeGDPRConsentState('foo purpose'); + consentState.addGDPRConsentState('foo purpose 2', mParticle$5.Consent.createGDPRConsent(false, 11)); + mParticle$5.getInstance().Identity.getCurrentUser().setConsentState(consentState); + user1StoredConsentState = mParticle$5.getInstance()._Persistence.getConsentState('MPID1'); + user2StoredConsentState = mParticle$5.getInstance()._Persistence.getConsentState('MPID2'); + user1StoredConsentState.getGDPRConsentState().should.have.property('foo purpose'); + user1StoredConsentState.getGDPRConsentState().should.not.have.property('foo purpose 2'); + user1StoredConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Consented', true); + user1StoredConsentState.getGDPRConsentState()['foo purpose'].should.have.property('Timestamp', 10); + user2StoredConsentState.getGDPRConsentState().should.have.property('foo purpose 2'); + user1StoredConsentState.getGDPRConsentState().should.not.have.property('foo purpose 1'); + user2StoredConsentState.getGDPRConsentState()['foo purpose 2'].should.have.property('Consented', false); + user2StoredConsentState.getGDPRConsentState()['foo purpose 2'].should.have.property('Timestamp', 11); + done(); + }); + it('integration test - clears and creates new LS on reload if LS is corrupt', function (done) { + var les = new Date().getTime(); + mParticle$5._resetForTests(MPConfig); + //an extra apostrophe is added to ua here to force a corrupt cookie. On init, cookies will clear and there will be a new cgid, sid, and das to exist + var LS = "{'sid':'1992BDBB-AD74-49DB-9B20-5EC8037E72DE'|'ie':1|'ua':'eyJ0ZXN'0Ijoiwq7igJkifQ=='|'ui':'eyIzIjoiwq7igJkifQ=='|'ss':'eyJ1aWQiOnsiRXhwaXJlcyI6IjIwMjgtMDktMTRUMjI6MjI6MTAuMjU0MDcyOVoiLCJWYWx1ZSI6Imc9NjhjMmJhMzktYzg2OS00MTZhLWE4MmMtODc4OWNhZjVmMWU3JnU9NDE3NjQyNTYyMTQ0MTEwODk2OCZjcj00NTgxOTgyIn19'|'dt':'e207c24e36a7a8478ba0fcb3707a616b'|'les':" + les + "|'ssd':1537222930186|'cgid':'4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'|'das':'68c2ba39-c869-416a-a82c-8789caf5f1e7'|'mpid':'4176425621441108968'}"; + setLocalStorage$3(v4LSKey, LS, true); + mParticle$5.init(apiKey, mParticle$5.config); + var sessionId = mParticle$5.sessionManager.getSession(); + var das = mParticle$5.getDeviceId(); + var cgid = mParticle$5.getInstance()._Persistence.getLocalStorage().gs.cgid; + sessionId.should.not.equal('1992BDBB-AD74-49DB-9B20-5EC8037E72DE'); + das.should.not.equal('68c2ba39-c869-416a-a82c-8789caf5f1e7'); + cgid.should.not.equal('4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'); + done(); + }); + it('integration test - clears and creates new cookies on reload if cookies is corrupt', function (done) { + var les = new Date().getTime(); + mParticle$5._resetForTests(MPConfig); + //an extra apostrophe is added to ua here to force a corrupt cookie. On init, cookies will clear and there will be a new cgid, sid, and das to exist + var cookies = "{'sid':'1992BDBB-AD74-49DB-9B20-5EC8037E72DE'|'ie':1|'ua':'eyJ0ZXN'0Ijoiwq7igJkifQ=='|'ui':'eyIzIjoiwq7igJkifQ=='|'ss':'eyJ1aWQiOnsiRXhwaXJlcyI6IjIwMjgtMDktMTRUMjI6MjI6MTAuMjU0MDcyOVoiLCJWYWx1ZSI6Imc9NjhjMmJhMzktYzg2OS00MTZhLWE4MmMtODc4OWNhZjVmMWU3JnU9NDE3NjQyNTYyMTQ0MTEwODk2OCZjcj00NTgxOTgyIn19'|'dt':'e207c24e36a7a8478ba0fcb3707a616b'|'les':" + les + "|'ssd':1537222930186|'cgid':'4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'|'das':'68c2ba39-c869-416a-a82c-8789caf5f1e7'|'mpid':'4176425621441108968'}"; + setCookie$1(workspaceCookieName, cookies, true); + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var sessionId = mParticle$5.sessionManager.getSession(); + var das = mParticle$5.getDeviceId(); + var cgid = mParticle$5.getInstance()._Persistence.getCookie().gs.cgid; + sessionId.should.not.equal('1992BDBB-AD74-49DB-9B20-5EC8037E72DE'); + das.should.not.equal('68c2ba39-c869-416a-a82c-8789caf5f1e7'); + cgid.should.not.equal('4ebad5b4-8ed1-4275-8455-838a2e3aa5c0'); + done(); + }); + it('integration test - clears LS products on reload if LS products are corrupt', function (done) { + mParticle$5._resetForTests(MPConfig); + // randomly added gibberish to a Base64 encoded cart product array to force a corrupt product array + var products = 'eyItOTE4MjY2NTAzNTA1ODg1NjAwMyI6eyasdjfiojasdifojfsdfJjcCI6W3siTmFtZSI6ImFuZHJvaWQiLCJTa3UiOiI1MTg3MDkiLCJQcmljZSI6MjM0LCJRdWFudGl0eSI6MSwiQnJhbmQiOm51bGwsIlZhcmlhbnQiOm51bGwsIkNhdGVnb3J5IjpudWxsLCJQb3NpdGlvbiI6bnVsbCwiQ291cG9uQ29kZSI6bnVsbCwiVG90YWxBbW91bnQiOjIzNCwiQXR0cmlidXRlcyI6eyJwcm9kYXR0cjEiOiJoaSJ9fSx7Ik5hbWUiOiJ3aW5kb3dzIiwiU2t1IjoiODMzODYwIiwiUHJpY2UiOjM0NSwiUXVhbnRpdHkiOjEsIlRvdGFsQW1vdW50IjozNDUsIkF0dHJpYnV0ZXMiOm51bGx9XX19'; + localStorage.setItem(localStorageProductsV4, products); + mParticle$5.init(apiKey, mParticle$5.config); + var productsAfterInit = getLocalStorageProducts$2().testMPID; + expect(productsAfterInit.length).to.not.be.ok; + done(); + }); + it('should save products to persistence correctly when adding and removing products', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + var iphone = mParticle$5.eCommerce.createProduct('iphone', 'iphonesku', 599, 1, 'iphone variant', 'iphonecategory', 'iphonebrand', null, 'iphonecoupon', { + iphoneattr1: 'value1', + iphoneattr2: 'value2' + }); + mParticle$5.eCommerce.Cart.add(iphone, true); + var ls = localStorage.getItem(LocalStorageProductsV4WithWorkSpaceName); + var parsedProducts = JSON.parse(atob(ls)); + // parsedProducts should just have key of testMPID with value of cp with a single product + Object.keys(parsedProducts).length.should.equal(1); + parsedProducts['testMPID'].should.have.property('cp'); + parsedProducts['testMPID'].cp.length.should.equal(1); + mParticle$5.eCommerce.Cart.remove(iphone, true); + ls = localStorage.getItem(LocalStorageProductsV4WithWorkSpaceName); + var parsedProductsAfter = JSON.parse(atob(ls)); + // parsedProducts should just have key of testMPID with value of cp with no products + Object.keys(parsedProductsAfter).length.should.equal(1); + parsedProductsAfter['testMPID'].should.have.property('cp'); + parsedProductsAfter['testMPID'].cp.length.should.equal(0); + done(); + }); + it('should only set setFirstSeenTime() once', function (done) { + mParticle$5._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + previous: {}, + previous_set: { + fst: 100 + }, + cu: 'current' + }); + setCookie$1(workspaceCookieName, cookies); + // TODO: Refactor this into setup/teardown + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('current', 10000); + var currentFirstSeenTime = mParticle$5.getInstance()._Persistence.getFirstSeenTime('current'); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('current', 2); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('current').should.equal(currentFirstSeenTime); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous', 10); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous').should.equal(10); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous', 20); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous').should.equal(10); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous_set').should.equal(100); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('previous_set', 200); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous_set').should.equal(100); + done(); + }); + it('should properly set setLastSeenTime()', function (done) { + mParticle$5._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'lst Test', + les: new Date().getTime() + }, + previous: {}, + previous_set: { + lst: 10 + }, + cu: 'current' + }); + setCookie$1(workspaceCookieName, cookies, true); + // TODO: https://go.mparticle.com/work/SQDSDKS-5339 + // @ts-ignore + mParticle$5.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var clock = sinon$1.useFakeTimers(); + clock.tick(100); + var persistence = mParticle$5.getInstance()._Persistence; + persistence.setLastSeenTime('previous', 1); + expect(persistence.getLastSeenTime('previous')).to.equal(1); + persistence.setLastSeenTime('previous', 2); + expect(persistence.getLastSeenTime('previous')).to.equal(2); + expect(persistence.getLastSeenTime('previous_set')).to.equal(10); + persistence.setLastSeenTime('previous_set', 20); + expect(persistence.getLastSeenTime('previous_set')).to.equal(20); + expect(persistence.getLastSeenTime('current')).to.equal(100); + persistence.setLastSeenTime('current', 200); + //lastSeenTime for the current user should always reflect the current time, + //even if was set + expect(persistence.getLastSeenTime('current')).to.equal(100); + clock.tick(50); + expect(persistence.getLastSeenTime('current')).to.equal(150); + clock.restore(); + done(); + }); + it("should set firstSeenTime() for a user that doesn't have storage yet", function (done) { + mParticle$5._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'lst Test', + les: new Date().getTime() + }, + cu: 'test' + }); + setCookie$1(workspaceCookieName, cookies, true); + // FIXME: Should this be in configs or global? + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance()._Persistence.setFirstSeenTime('1', 1); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('1').should.equal(1); + //firstSeenTime should ignore subsiquent calls after it has been set + mParticle$5.getInstance()._Persistence.setFirstSeenTime('2', 2); + mParticle$5.getInstance()._Persistence.getFirstSeenTime('1').should.equal(1); + done(); + }); + it('fst should be set when the user does not change, after an identify request', function (done) { + mParticle$5._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'lst Test', + les: new Date().getTime() + }, + current: {}, + cu: 'current' + }); + mockServer$c.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'current', + is_logged_in: false + })]); + setCookie$1(workspaceCookieName, cookies, true); + // FIXME: Should this be in configs or global? + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('current')).to.equal(null); + mParticle$5.Identity.identify(); + expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('current')).to.not.equal(null); + done(); + }); + it('lastSeenTime should be null for users in storage without an lst value', function (done) { + var cookies = JSON.stringify({ + gs: { + sid: 'lst Test', + les: new Date().getTime() + }, + previous: {}, + cu: 'current' + }); + setCookie$1(workspaceCookieName, cookies, true); + // FIXME: config or global? + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + expect(mParticle$5.getInstance()._Persistence.getFirstSeenTime('previous')).to.equal(null); + done(); + }); + it('should save to persistence a device id set with setDeviceId', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.setDeviceId('foo-guid'); + mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das.should.equal('foo-guid'); + done(); + }); + it('should save to persistence a device id set via mParticle.config', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.config.deviceId = 'foo-guid'; + mParticle$5.init(apiKey, mParticle$5.config); + mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das.should.equal('foo-guid'); + done(); + }); + it('should prioritize device id set via mParticle.config instead of local storage', function (done) { + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + var initialDeviceId = mParticle$5.getInstance().getDeviceId(); + expect(initialDeviceId).to.not.be["null"]; + var expectedDeviceId = 'guid-via-config'; + mParticle$5.config.deviceId = expectedDeviceId; + mParticle$5.init(apiKey, mParticle$5.config); + expect(mParticle$5.getInstance().getDeviceId(), 'Device ID should match guid passed in via config').to.equal(expectedDeviceId); + expect(initialDeviceId, 'New Device ID should not match Old Device Id').to.not.equal(expectedDeviceId); + expect(mParticle$5.getInstance()._Persistence.getLocalStorage().gs.das, 'Device ID stored in Local Storage should be the new Device ID').to.equal(expectedDeviceId); + done(); + }); + // this test confirms a bug has been fixed where setting a user attribute, then user attribute list + // with a special character in it results in a cookie decode error, which only happened + // when config.useCookieStorage was true + it('should save special characters to persistence when on cookies or local storage', function (done) { + mockServer$c.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + // first test local storage + mParticle$5.config.useCookieStorage = false; + mParticle$5._resetForTests(MPConfig); + mParticle$5.init(apiKey, mParticle$5.config); + var user = mParticle$5.Identity.getCurrentUser(); + user.setUserAttribute('ua-1', 'a'); + user.setUserAttributeList('ua-list', ['a\\', '']); + user.getAllUserAttributes()['ua-list'][0].should.equal('a\\'); + user.getAllUserAttributes()['ua-list'][1].should.equal(''); + user.getAllUserAttributes()['ua-1'].should.equal('a'); + mParticle$5._resetForTests(MPConfig); + // then test cookie storage + mParticle$5.config.useCookieStorage = true; + mParticle$5.init(apiKey, mParticle$5.config); + var user2 = mParticle$5.Identity.getCurrentUser(); + user2.setUserAttribute('ua-1', 'a'); + user2.setUserAttributeList('ua-list', ['a\\', '']); + user2.getAllUserAttributes()['ua-list'][0].should.equal('a\\'); + user2.getAllUserAttributes()['ua-list'][1].should.equal(''); + user2.getAllUserAttributes()['ua-1'].should.equal('a'); + done(); + }); + }); + + var findEventFromRequest$6 = TestsCore.findEventFromRequest, + getForwarderEvent = TestsCore.getForwarderEvent, + setLocalStorage$2 = TestsCore.setLocalStorage, + forwarderDefaultConfiguration$3 = TestsCore.forwarderDefaultConfiguration, + MockForwarder$5 = TestsCore.MockForwarder, + MockSideloadedKit$1 = TestsCore.MockSideloadedKit; + var mockServer$b; + describe('forwarders', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + delete mParticle._instances['default_instance']; + client.post(urls.events, 200); + mockServer$b = sinon$1.createFakeServer(); + mockServer$b.respondImmediately = true; + mockServer$b.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$b.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$b.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$b.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$b.respondWith(urls.forwarding, [202, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + client.restore(); + delete window.MockForwarder1; + mockServer$b.restore(); + }); + it('should add forwarders via dynamic script loading via the addForwarder method', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._getActiveForwarders().length.should.equal(1); + done(); + }); + it('should invoke forwarder setIdentity on initialized forwarders (debug = false)', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.identifyRequest = { + userIdentities: { + google: 'google123' + } + }; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('setUserIdentityCalled', true); + window.MockForwarder1.instance.userIdentities.should.have.property('4', 'google123'); + window.mParticle.identifyRequest = {}; + done(); + }); + it('should permit forwarder if no consent configured.', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = {}; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, null); + enabled.should.be.ok(); + done(); + }); + it('should not permit forwarder if consent configured but there is no user.', function (done) { + var enableForwarder = true; + var consented = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: '123', + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, null); + enabled.should.not.be.ok(); + done(); + }); + var MockUser = function MockUser() { + var consentState = null; + return { + setConsentState: function setConsentState(state) { + consentState = state; + }, + getConsentState: function getConsentState() { + return consentState; + } + }; + }; + it('should disable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and user consent has been rejected', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should disable forwarder if \'Do Not Forward\' when \'Consent Accepted\' is selected and consent has been accepted', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should enable forwarder if \'Only Forward\' when \'Consent Rejected\' is selected and consent has been rejected', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should enable forwarder if \'Only Forward\' when \'Consent Accepted\' is selected and consent has been accepted', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should disable forwarder if \'Only Forward\' when \'Consent Accepted\' is selected and consent has been rejected', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should enable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and consent has been accepted', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should enable forwarder if \'Do Not Forward\' when \'Consent Accepted\' is selected and consent has been rejected', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should enable forwarder if \'Do Not Forward\' when \'Consent Rejected\' is selected and consent has been accepted', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should disable forwarder if \'Do Not Forward\' when CCPA is \'Not Present\' is selected and user CCPA is not present', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = false; + var userConsentPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should disable forwarder if \'Do Not Forward\' when CCPA is \'Present\' is selected and user CCPA is present', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = true; + var userConsentPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should enable forwarder if \'Only Forward\' when CCPA is \'Not Present\' is selected and user CCPA is not present', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = false; + var userConsentPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should enable forwarder if \'Only Forward\' when CCPA data sale opt out is present is selected and user CCPA is present.', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = true; + var userConsentPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should disable forwarder if \'Only Forward\' when CCPA is \'Present\' is selected and user CCPA is not present', function (done) { + var enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = true; + var userConsentPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it('should enable forwarder if \'Do Not Forward\' when CCPA is \'Not Present\' is selected and user CCPA is present', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = false; + var userConsentPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should enable forwarder if \'Do Not Forward\' when CCPA is \'Present\' is selected and user CCPA is not present', function (done) { + var enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consentPresent = true; + var userConsentPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3('MockForwarder'); + config.filteringConsentRuleValues = { + includeOnMatch: enableForwarder, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consentPresent + }] + }; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(userConsentPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(window.MockForwarder1.instance.filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("does not initialize a forwarder when forwarder's isDebug != mParticle.isDevelopmentMode", function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3(); + config.isDebug = true; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + Should(window.MockForwarder1).not.be.ok(); + mParticle.getInstance()._getActiveForwarders().length.should.equal(0); + done(); + }); + it('initializes a forwarder with isDebug = false && mParticle.config.isDevelopmentMode = false', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3(); + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('initCalled', true); + mParticle.getInstance()._getActiveForwarders().length.should.equal(1); + Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1); + done(); + }); + it('initializes a forwarder with isDebug = true && mParticle.config.isDevelopmentMode = true', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = true; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config = forwarderDefaultConfiguration$3(); + config.isDebug = true; + window.mParticle.config.kitConfigs.push(config); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('initCalled', true); + Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1); + done(); + }); + it('initializes forwarders when isDebug = mParticle.config.isDevelopmentMode', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.isDebug = true; + var config2 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.kitConfigs.push(config2); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._getActiveForwarders().length.should.equal(1); + Should(mParticle.getInstance()._Store.configuredForwarders.length).equal(1); + done(); + }); + it("sends events to forwarder when forwarder's isDebug = mParticle.config.isDevelopmentMode ", function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = true; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.isDebug = true; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('send this event to forwarder'); + window.MockForwarder1.instance.should.have.property('processCalled', true); + done(); + }); + it('sends events to forwarder v1 endpoint when mParticle.config.isDevelopmentMode = config.isDebug = false', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mockServer$b.requests = []; + mParticle.logEvent('send this event to forwarder'); + window.MockForwarder1.instance.should.have.property('processCalled', true); + mockServer$b.requests[mockServer$b.requests.length - 1].url.includes('/v1/JS/test_key/Forwarding'); + done(); + }); + it('sends forwarding stats to v2 endpoint when featureFlag setting of batching is true', function (done) { + mParticle._resetForTests(MPConfig); + var clock = sinon$1.useFakeTimers(); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.dataPlan = { + planVersion: 10, + planId: 'plan-slug' + }; + window.mParticle.config.flags = { + reportBatching: true + }; + mParticle.init(apiKey, window.mParticle.config); + mockServer$b.requests = []; + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + 'my-key': 'my-value' + }); + clock.tick(5000); + var event = getForwarderEvent(mockServer$b.requests, 'send this event to forwarder', true); + Should(event).should.be.ok(); + mockServer$b.requests[mockServer$b.requests.length - 1].url.includes('/v2/JS/test_key/Forwarding'); + event.should.have.property('mid', 1); + event.should.have.property('esid', 1234567890); + event.should.have.property('n', 'send this event to forwarder'); + event.should.have.property('attrs'); + event.should.have.property('dp'); + event.dp.should.have.property('PlanVersion', 10); + event.dp.should.have.property('PlanId', 'plan-slug'); + event.should.have.property('dp'); + event.should.have.property('sdk', mParticle.getVersion()); + event.should.have.property('dt', MessageType$2.PageEvent); + event.should.have.property('et', mParticle.EventType.Navigation); + event.should.have.property('dbg', mParticle.getInstance()._Store.SDKConfig.isDevelopmentMode); + event.should.have.property('ct'); + event.should.have.property('eec', 0); + clock.restore(); + done(); + }); + it('should not send forwarding stats to invisible forwarders', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.isVisible = false; + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + 'my-key': 'my-value' + }); + var event = findEventFromRequest$6(client._calls, 'send this event to forwarder', true); + Should(event).should.not.have.property('n'); + done(); + }); + it('should invoke forwarder opt out', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.setOptOut(true); + window.MockForwarder1.instance.should.have.property('setOptOutCalled', true); + done(); + }); + it('should invoke forwarder setuserattribute', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + done(); + }); + it('should invoke forwarder setuserattribute when calling setUserAttributeList', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('gender', ['male']); + window.MockForwarder1.instance.should.have.property('setUserAttributeCalled', true); + done(); + }); + it('should invoke forwarder removeuserattribute', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().removeUserAttribute('gender'); + window.MockForwarder1.instance.should.have.property('removeUserAttributeCalled', true); + done(); + }); + it('should filter user attributes from forwarder on log event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.userAttributeFilters = [mParticle.generateHash('gender')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('UserAttributes'); + event.UserAttributes.should.not.have.property('gender'); + done(); + }); + it('should filter user identities from forwarder on init and bring customerid as first ID', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.userIdentityFilters = [mParticle.IdentityType.Google]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.Identity.modify({ + userIdentities: { + google: 'test@google.com', + email: 'test@gmail.com', + customerid: '123' + } + }); + mParticle.init(apiKey, window.mParticle.config); + mParticle.userIdentitiesFilterOnInitTest.length.should.equal(2); + mParticle.userIdentitiesFilterOnInitTest[0].Type.should.equal(1); + mParticle.userIdentitiesFilterOnInitTest[0].Identity.should.equal('123'); + mParticle.userIdentitiesFilterOnInitTest[1].Type.should.equal(7); + mParticle.userIdentitiesFilterOnInitTest[1].Identity.should.equal('test@gmail.com'); + Should(mParticle.userIdentitiesFilterOnInitTest[2]).not.be.ok(); + done(); + }); + it('should filter user identities from forwarder on log event and bring customerid as first ID', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.userIdentityFilters = [mParticle.IdentityType.Google]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.modify({ + userIdentities: { + google: 'test@google.com', + email: 'test@gmail.com', + customerid: '123' + } + }); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Object.keys(event.UserIdentities).length.should.equal(2); + var googleUserIdentityExits = false; + event.UserIdentities.forEach(function (identity) { + if (identity.Type === mParticle.IdentityType.Google) { + googleUserIdentityExits = true; + } }); + Should(googleUserIdentityExits).not.be.ok(); + event.UserIdentities[0].Type.should.equal(mParticle.IdentityType.CustomerId); + done(); + }); + it('should filter user attributes from forwarder on init, and on subsequent set attribute calls', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.userAttributeFilters = [mParticle.generateHash('gender'), mParticle.generateHash('age')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.userAttributesFilterOnInitTest.should.not.have.property('gender'); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('age', 32); + mParticle.Identity.getCurrentUser().setUserAttribute('weight', 150); + window.MockForwarder1.instance.userAttributes.should.have.property('weight', 150); + window.MockForwarder1.instance.userAttributes.should.not.have.property('age'); + done(); + }); + it('should filter user attributes from forwarder on init, and on subsequent remove attribute calls', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + + // filtered User Attributes that should should not call removeUserAttribute + config1.userAttributeFilters = [mParticle.generateHash('weight'), mParticle.generateHash('age')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); - var states = { - UNSENT: 0, - OPENED: 1, - HEADERS_RECEIVED: 2, - LOADING: 3, - DONE: 4 + // force filtered UA in mock forwarder (due to filtering affecting setUserAttribute) and test init + window.MockForwarder1.instance.userAttributes['weight'] = 150; + mParticle.Identity.getCurrentUser().removeUserAttribute('weight'); + window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(false); + mParticle.userAttributesFilterOnInitTest.should.have.property('weight'); + mParticle.init(apiKey, window.mParticle.config); + var dummyUserAttributes = { + 'gender': 'male', + 'age': 20 }; - extend(FakeXMLHttpRequest, states); - extend(FakeXMLHttpRequest.prototype, states); - - function useFakeXMLHttpRequest() { - FakeXMLHttpRequest.restore = function restore(keepOnCreate) { - if (sinonXhr.supportsXHR) { - globalScope.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest; - } - - if (sinonXhr.supportsActiveX) { - globalScope.ActiveXObject = sinonXhr.GlobalActiveXObject; - } - - delete FakeXMLHttpRequest.restore; - - if (keepOnCreate !== true) { - delete FakeXMLHttpRequest.onCreate; - } - }; - if (sinonXhr.supportsXHR) { - globalScope.XMLHttpRequest = FakeXMLHttpRequest; - } - - if (sinonXhr.supportsActiveX) { - globalScope.ActiveXObject = function ActiveXObject(objId) { - if ( - objId === "Microsoft.XMLHTTP" || - /^Msxml2\.XMLHTTP/i.test(objId) - ) { - return new FakeXMLHttpRequest(); - } - - return new sinonXhr.GlobalActiveXObject(objId); - }; - } - - return FakeXMLHttpRequest; + // force filtered UA in mock forwarder (due to filtering affecting setUserAttribute) and non filtered UA + for (var _i = 0, _Object$keys = Object.keys(dummyUserAttributes); _i < _Object$keys.length; _i++) { + var key = _Object$keys[_i]; + window.MockForwarder1.instance.userAttributes[key] = dummyUserAttributes[key]; } - return { - xhr: sinonXhr, - FakeXMLHttpRequest: FakeXMLHttpRequest, - useFakeXMLHttpRequest: useFakeXMLHttpRequest - }; - } - - module.exports = extend(fakeXMLHttpRequestFor(globalObject), { - fakeXMLHttpRequestFor: fakeXMLHttpRequestFor - }); - - },{"../configure-logger":117,"../event":121,"./blob":126,"@sinonjs/commons":135,"@sinonjs/text-encoding":108,"just-extend":115}],128:[function(require,module,exports){ - - module.exports = { - fakeServer: require("./fake-server"), - fakeServerWithClock: require("./fake-server/fake-server-with-clock"), - fakeXhr: require("./fake-xhr") - }; - - },{"./fake-server":124,"./fake-server/fake-server-with-clock":123,"./fake-xhr":127}],129:[function(require,module,exports){ - arguments[4][42][0].apply(exports,arguments); - },{"./prototypes/array":137,"dup":42}],130:[function(require,module,exports){ - arguments[4][43][0].apply(exports,arguments); - },{"./function-name":133,"dup":43}],131:[function(require,module,exports){ - arguments[4][44][0].apply(exports,arguments); - },{"dup":44}],132:[function(require,module,exports){ - arguments[4][45][0].apply(exports,arguments); - },{"dup":45}],133:[function(require,module,exports){ - arguments[4][46][0].apply(exports,arguments); - },{"dup":46}],134:[function(require,module,exports){ - arguments[4][47][0].apply(exports,arguments); - },{"dup":47}],135:[function(require,module,exports){ - arguments[4][48][0].apply(exports,arguments); - },{"./called-in-order":129,"./class-name":130,"./deprecated":131,"./every":132,"./function-name":133,"./global":134,"./order-by-first-call":136,"./prototypes":140,"./type-of":146,"./value-to-string":147,"dup":48}],136:[function(require,module,exports){ - arguments[4][49][0].apply(exports,arguments); - },{"./prototypes/array":137,"dup":49}],137:[function(require,module,exports){ - arguments[4][50][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":50}],138:[function(require,module,exports){ - arguments[4][51][0].apply(exports,arguments); - },{"./throws-on-proto":145,"dup":51}],139:[function(require,module,exports){ - arguments[4][52][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":52}],140:[function(require,module,exports){ - arguments[4][53][0].apply(exports,arguments); - },{"./array":137,"./function":139,"./map":141,"./object":142,"./set":143,"./string":144,"dup":53}],141:[function(require,module,exports){ - arguments[4][54][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":54}],142:[function(require,module,exports){ - arguments[4][55][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":55}],143:[function(require,module,exports){ - arguments[4][56][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":56}],144:[function(require,module,exports){ - arguments[4][57][0].apply(exports,arguments); - },{"./copy-prototype-methods":138,"dup":57}],145:[function(require,module,exports){ - arguments[4][58][0].apply(exports,arguments); - },{"dup":58}],146:[function(require,module,exports){ - arguments[4][59][0].apply(exports,arguments); - },{"dup":59,"type-detect":151}],147:[function(require,module,exports){ - arguments[4][60][0].apply(exports,arguments); - },{"dup":60}],148:[function(require,module,exports){ - var isarray = require('isarray'); - - /** - * Expose `pathToRegexp`. - */ - module.exports = pathToRegexp; - module.exports.parse = parse; - module.exports.compile = compile; - module.exports.tokensToFunction = tokensToFunction; - module.exports.tokensToRegExp = tokensToRegExp; + // "age" is filtered and should not call removeUserAttribute on forwarder + mParticle.Identity.getCurrentUser().removeUserAttribute('age'); + window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(false); + window.MockForwarder1.instance.userAttributes.should.have.property('age', 20); - /** - * The main path matching regexp utility. - * - * @type {RegExp} - */ - var PATH_REGEXP = new RegExp([ - // Match escaped characters that would otherwise appear in future matches. - // This allows the user to escape special characters that won't transform. - '(\\\\.)', - // Match Express-style parameters and un-named parameters with a prefix - // and optional suffixes. Matches appear as: - // - // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] - // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] - // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] - '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' - ].join('|'), 'g'); + // "gender" is not filtered and should call removeUserAttribute on forwarder + mParticle.Identity.getCurrentUser().removeUserAttribute('gender'); + window.MockForwarder1.instance.removeUserAttributeCalled.should.equal(true); + window.MockForwarder1.instance.userAttributes.should.not.have.property('gender'); + done(); + }); + it('should filter event names', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.eventNameFilters = [mParticle.generateHash(mParticle.EventType.Navigation + 'test event')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.startNewSession(); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('test event', mParticle.EventType.Navigation); + Should(window.MockForwarder1.instance.receivedEvent).not.be.ok(); + mParticle.logEvent('test event 2', mParticle.EventType.Navigation); + Should(window.MockForwarder1.instance.receivedEvent).be.ok(); + done(); + }); + it('should filter page event names', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.screenNameFilters = [mParticle.generateHash(mParticle.EventType.Unknown + 'PageView')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.startNewSession(); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logPageView(); + Should(window.MockForwarder1.instance.receivedEvent).not.be.ok(); + done(); + }); + it('should filter event attributes', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.attributeFilters = [mParticle.generateHash(mParticle.EventType.Navigation + 'test event' + 'test attribute')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('test event', mParticle.EventType.Navigation, { + 'test attribute': 'test value', + 'test attribute 2': 'test value 2' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.EventAttributes.should.not.have.property('test attribute'); + event.EventAttributes.should.have.property('test attribute 2'); + done(); + }); + it('should filter pageview attributes', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.attributeFilters = [mParticle.generateHash(mParticle.EventType.Navigation + 'test event' + 'test attribute')]; + config1.screenAttributeFilters = [mParticle.generateHash(mParticle.EventType.Unknown + 'ScreenA' + 'filteredScreenAttribute')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logPageView('ScreenA', { + 'filteredScreenAttribute': 'this will be filtered', + 'unfilteredScreenAttribute': 'this will not be filtered' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.EventAttributes.should.not.have.property('filteredScreenAttribute'); + event.EventAttributes.should.have.property('unfilteredScreenAttribute', 'this will not be filtered'); + done(); + }); + it('should call logout on forwarder', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.logout(); + window.MockForwarder1.instance.should.have.property('logOutCalled', true); + window.MockForwarder1.instance.should.have.property('onLogoutCompleteCalled', true); + done(); + }); + it('should pass in app name to forwarder on initialize', function (done) { + mParticle.config.appName = 'Unit Tests'; + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('appName', 'Unit Tests'); + done(); + }); + it('should pass in app version to forwarder on initialize', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.config.appVersion = '3.0'; + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('appVersion', '3.0'); + done(); + }); + it('should pass in user identities to forwarder on initialize', function (done) { + mParticle._resetForTests(MPConfig); + setLocalStorage$2(); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + Object.keys(window.MockForwarder1.instance.userIdentities).length.should.equal(1); + done(); + }); + it('should pass in user attributes to forwarder on initialize', function (done) { + mParticle._resetForTests(MPConfig); + setLocalStorage$2(); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('userAttributes'); + window.MockForwarder1.instance.userAttributes.should.have.property('color', 'blue'); + window.mParticle.identifyRequest = {}; + done(); + }); + it('should not forward event if attribute forwarding rule is set', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringEventAttributeValue = { + eventAttributeName: mParticle.generateHash('ForwardingRule').toString(), + eventAttributeValue: mParticle.generateHash('Forward').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + ForwardingRule: 'Forward' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.not.have.property('EventName', 'send this event to forwarder'); + done(); + }); + it('should forward event if event attribute forwarding rule is set and includeOnMatch is true', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringEventAttributeValue = { + eventAttributeName: mParticle.generateHash('ForwardingRule').toString(), + eventAttributeValue: mParticle.generateHash('Forward').toString(), + includeOnMatch: true + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + Foo: 'Bar', + ForwardingRule: 'Forward' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('EventName', 'send this event to forwarder'); + done(); + }); + it('should not forward event if event attribute forwarding rule is set and includeOnMatch is true but attributes do not match', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringEventAttributeValue = { + eventAttributeName: mParticle.generateHash('ForwardingRule').toString(), + eventAttributeValue: mParticle.generateHash('Forward').toString(), + includeOnMatch: true + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + Forwarding: 'Non-Matching' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.not.have.property('EventName', 'send this event to forwarder'); + done(); + }); + it('should not forward event if event attribute forwarding rule is set and includeOnMatch is false', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringEventAttributeValue = { + eventAttributeName: mParticle.generateHash('ForwardingRule').toString(), + eventAttributeValue: mParticle.generateHash('Forward').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.receivedEvent.EventName.should.equal(1); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + ForwardingRule: 'Forward' + }); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).not.be.ok(); + done(); + }); + it('should forward event if event attribute forwarding rule is set and includeOnMatch is false but attributes do not match', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringEventAttributeValue = { + eventAttributeName: mParticle.generateHash('ForwardingRule').toString(), + eventAttributeValue: mParticle.generateHash('Forward').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.receivedEvent.EventName.should.equal(1); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('send this event to forwarder', mParticle.EventType.Navigation, { + Test: 'does not match' + }); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('EventName', 'send this event to forwarder'); + done(); + }); + it('should send event to forwarder if filtering attribute and includingOnMatch is true', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: true + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'Male'); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + event.should.have.property('UserAttributes'); + event.UserAttributes.should.have.property('Gender', 'Male'); + event.EventName.should.equal('test event'); + done(); + }); + it('should not send event to forwarder if filtering attribute and includingOnMatch is false', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'Male'); + //reset received event, which will have the initial session start event on it + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).not.be.ok(); + done(); + }); + it('should permit forwarder if no user attribute value filters configured', function (done) { + var enabled = mParticle.getInstance()._Forwarders.isEnabledForUserAttributes(null, null); + enabled.should.be.ok(); + enabled = mParticle.getInstance()._Forwarders.isEnabledForUserAttributes({}, null); + enabled.should.be.ok(); + done(); + }); + it('should send event to forwarder if there are no user attributes on event if includeOnMatch = false', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + window.MockForwarder1.instance.receivedEvent.EventName.should.equal('test event'); + Should(event).be.ok(); + done(); + }); + it('should not send event to forwarder if there are no user attributes on event if includeOnMatch = true', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: true + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).not.be.ok(); + done(); + }); + it('should send event to forwarder if there is no match and includeOnMatch = false', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).be.ok(); + event.EventName.should.equal('test event'); + done(); + }); + it('should not send event to forwarder if there is no match and includeOnMatch = true', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: true + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).not.be.ok(); + done(); + }); + it('should reinitialize forwarders when user attribute changes', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = { + userAttributeName: mParticle.generateHash('gender').toString(), + userAttributeValue: mParticle.generateHash('male').toString(), + includeOnMatch: false + }; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'Male'); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(0); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).not.be.ok(); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'famale'); + activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(1); + window.MockForwarder1.instance.receivedEvent = null; + mParticle.logEvent('test event'); + event = window.MockForwarder1.instance.receivedEvent; + Should(event).be.ok(); + done(); + }); + it('should send event to forwarder if the filterinUserAttribute object is invalid', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.filteringUserAttributeValue = undefined; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'Male'); + mParticle.logEvent('test event'); + var event = window.MockForwarder1.instance.receivedEvent; + Should(event).be.ok(); + window.MockForwarder1.instance.receivedEvent.EventName.should.equal('test event'); + done(); + }); + it('should call forwarder onUserIdentified method when identity is returned', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('onUserIdentifiedCalled', true); + done(); + }); + it('should queue forwarder stats reporting and send after 5 seconds if batching feature is true', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.flags = { + reportBatching: true + }; + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('not in forwarder'); + var product = mParticle.eCommerce.createProduct('iphone', 'sku', 123, 1); + mParticle.eCommerce.Cart.add(product, true); + var result = getForwarderEvent(mockServer$b.requests, 'not in forwarder'); + Should(result).not.be.ok(); + clock.tick(5001); + result = getForwarderEvent(mockServer$b.requests, 'not in forwarder'); + result.should.be.ok(); + result = getForwarderEvent(mockServer$b.requests, 'eCommerce - AddToCart'); + result.should.be.ok(); + clock.restore(); + done(); + }); + it('should initialize forwarders when a user is not logged in and excludeAnonymousUser=false', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + var mockForwarder2 = new MockForwarder$5('MockForwarder2', 2); + mockForwarder.register(window.mParticle.config); + mockForwarder2.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.excludeAnonymousUser = false; + var config2 = forwarderDefaultConfiguration$3('MockForwarder', 2); + config2.excludeAnonymousUser = true; + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.kitConfigs.push(config2); + mockServer$b.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(1); + mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false); + done(); + }); + it('should only initialize forwarders with excludeUnknownUser = false for non-logged-in users', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + var mockForwarder2 = new MockForwarder$5('MockForwarder2', 2); + mockForwarder.register(window.mParticle.config); + mockForwarder2.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.excludeAnonymousUser = false; + var config2 = forwarderDefaultConfiguration$3('MockForwarder', 2); + config2.excludeAnonymousUser = true; + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.kitConfigs.push(config2); + mockServer$b.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(1); + mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false); + done(); + }); + it('should initialize all forwarders when a user is logged in and the page reloads', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + var mockForwarder2 = new MockForwarder$5('MockForwarder2', 2); + mockForwarder.register(window.mParticle.config); + mockForwarder2.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$3('MockForwarder', 1); + config1.excludeAnonymousUser = false; + var config2 = forwarderDefaultConfiguration$3('MockForwarder', 2); + config2.excludeAnonymousUser = true; + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.kitConfigs.push(config2); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(false); + var user = { + userIdentities: { + customerid: 'customerid3', + email: 'email3@test.com' + } + }; + mockServer$b.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: true + })]); + mParticle.Identity.login(user); + mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(true); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(2); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().isLoggedIn().should.equal(true); + var activeForwarders2 = mParticle.getInstance()._getActiveForwarders(); + activeForwarders2.length.should.equal(2); + done(); + }); + it('should save logged in status of most recent user to cookies when logged in', function (done) { + mParticle._resetForTests(MPConfig); + mockServer$b.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: true + })]); + mParticle.init(apiKey, window.mParticle.config); + var ls = mParticle.getInstance()._Persistence.getLocalStorage(); + ls.l.should.equal(true); + mParticle.init(apiKey, window.mParticle.config); + var ls2 = mParticle.getInstance()._Persistence.getLocalStorage(); + ls2.hasOwnProperty('l').should.equal(true); + mockServer$b.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.Identity.logout(); + var ls3 = mParticle.getInstance()._Persistence.getLocalStorage(); + ls3.l.should.equal(false); + mParticle.init(apiKey, window.mParticle.config); + var ls4 = mParticle.getInstance()._Persistence.getLocalStorage(); + ls4.l.should.equal(false); + done(); + }); + it('should not set integration attributes on forwarders when a non-object attr is passed', function (done) { + mParticle.setIntegrationAttribute(128, 123); + var adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(0); + done(); + }); + it('should set integration attributes on forwarders', function (done) { + mParticle.setIntegrationAttribute(128, { + MCID: 'abcdefg' + }); + var adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + adobeIntegrationAttributes.MCID.should.equal('abcdefg'); + done(); + }); + it('should clear integration attributes when an empty object or a null is passed', function (done) { + mParticle.setIntegrationAttribute(128, { + MCID: 'abcdefg' + }); + var adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(1); + mParticle.setIntegrationAttribute(128, {}); + adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(0); + mParticle.setIntegrationAttribute(128, { + MCID: 'abcdefg' + }); + adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(1); + mParticle.setIntegrationAttribute(128, null); + adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(0); + done(); + }); + it('should set only strings as integration attributes', function (done) { + mParticle.setIntegrationAttribute(128, { + MCID: 'abcdefg', + fail: { + test: 'false' + }, + nullValue: null, + undefinedValue: undefined + }); + var adobeIntegrationAttributes = mParticle.getIntegrationAttributes(128); + Object.keys(adobeIntegrationAttributes).length.should.equal(1); + done(); + }); + it('should add integration delays to the integrationDelays object', function (done) { + mParticle._setIntegrationDelay(128, true); + mParticle._setIntegrationDelay(24, false); + mParticle._setIntegrationDelay(10, true); + var integrationDelays = mParticle._getIntegrationDelays(); + integrationDelays.should.have.property('128', true); + integrationDelays.should.have.property('24', false); + integrationDelays.should.have.property('10', true); + done(); + }); + it('integration test - should not log events if there are any integrations delaying, then resume logging events once delays are gone', function (done) { + mParticle._resetForTests(MPConfig); + // this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128, true); + mParticle._setIntegrationDelay(24, false); + mParticle._setIntegrationDelay(10, true); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('Test Event1'); + client._calls.length.should.equal(0); + mParticle._setIntegrationDelay(10, false); + mParticle._setIntegrationDelay(128, false); + mParticle.logEvent('Test Event2'); + client._calls.length.should.equal(4); + var sessionStartEvent = findEventFromRequest$6(client._calls, 'session_start'); + var ASTEvent = findEventFromRequest$6(client._calls, 'application_state_transition'); + var testEvent1 = findEventFromRequest$6(client._calls, 'Test Event1'); + var testEvent2 = findEventFromRequest$6(client._calls, 'Test Event2'); + sessionStartEvent.should.be.ok(); + ASTEvent.should.be.ok(); + testEvent1.should.be.ok(); + testEvent2.should.be.ok(); + done(); + }); + it('integration test - should send events after a configured delay, or 5 seconds by default if setIntegrationDelays are still true', function (done) { + // testing default of 5000 ms + var clock = sinon$1.useFakeTimers(); + mParticle._resetForTests(MPConfig); + // this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128, true); + Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(1); + mParticle._setIntegrationDelay(24, false); + Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(2); + mParticle._setIntegrationDelay(10, true); + Should(Object.keys(mParticle.getInstance()._preInit.integrationDelays).length).equal(3); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('Test Event1'); + client._calls.length.should.equal(0); + clock.tick(5001); + mParticle.logEvent('Test Event2'); + client._calls.length.should.equal(4); + var sessionStartEvent = findEventFromRequest$6(client._calls, 'session_start'); + var ASTEvent = findEventFromRequest$6(client._calls, 'application_state_transition'); + var testEvent1 = findEventFromRequest$6(client._calls, 'Test Event1'); + var testEvent2 = findEventFromRequest$6(client._calls, 'Test Event2'); + sessionStartEvent.should.be.ok(); + ASTEvent.should.be.ok(); + testEvent1.should.be.ok(); + testEvent2.should.be.ok(); + clock.restore(); + + // testing user-configured integrationDelayTimeout + clock = sinon$1.useFakeTimers(); + mParticle._resetForTests(MPConfig); + mParticle.config.integrationDelayTimeout = 1000; + mParticle._setIntegrationDelay(128, true); + mParticle._setIntegrationDelay(24, false); + mParticle._setIntegrationDelay(10, true); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('Test Event3'); + client._calls.length.should.equal(0); + clock.tick(1001); + mParticle.logEvent('Test Event4'); + client._calls.length.should.equal(4); + var sessionStartEvent2 = findEventFromRequest$6(client._calls, 'session_start'); + var ASTEvent2 = findEventFromRequest$6(client._calls, 'application_state_transition'); + var testEvent3 = findEventFromRequest$6(client._calls, 'Test Event3'); + var testEvent4 = findEventFromRequest$6(client._calls, 'Test Event4'); + sessionStartEvent2.should.be.ok(); + ASTEvent2.should.be.ok(); + testEvent3.should.be.ok(); + testEvent4.should.be.ok(); + clock.restore(); + done(); + }); + it('integration test - after an integration delay is set to false, should fire an event after the event timeout', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle._resetForTests(MPConfig); + // this code will be put in each forwarder as each forwarder is initialized + mParticle._setIntegrationDelay(128, true); + mParticle._setIntegrationDelay(24, false); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('test1'); + client._calls.length.should.equal(0); + // now that we set all integrations to false, the SDK should process queued events + mParticle._setIntegrationDelay(128, false); + clock.tick(5001); + client._calls.length.should.equal(3); + clock.restore(); + done(); + }); + it('parse and capture forwarderConfiguration properly from backend', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.requestConfig = true; + var mockForwarder = new MockForwarder$5('DynamicYield', 128); + var mockForwarder2 = new MockForwarder$5('Adobe', 124); + mockForwarder.register(window.mParticle.config); + mockForwarder2.register(window.mParticle.config); + var config = { + kitConfigs: [{ + name: 'DynamicYield', + moduleId: 128, + isDebug: false, + isVisible: true, + isDebugString: false, + hasDebugString: true, + settings: { + siteId: 8769977 + }, + screenNameFilters: [], + screenAttributeFilters: [], + userIdentityFilters: [], + userAttributeFilters: [], + eventNameFilters: [], + eventTypeFilters: [], + attributeFilters: [], + githubPath: null, + filteringEventAttributeValue: null, + filteringUserAttributeValue: null, + filteringConsentRuleValues: null, + consentRegulationFilters: [], + consentRegulationPurposeFilters: [], + messageTypeFilters: [], + messageTypeStateFilters: [], + eventSubscriptionId: 24884, + excludeAnonymousUser: false + }, { + name: 'Adobe', + moduleId: 124, + isDebug: false, + isVisible: true, + isDebugString: false, + hasDebugString: true, + settings: { + siteId: 8769977 + }, + screenNameFilters: [], + screenAttributeFilters: [], + userIdentityFilters: [], + userAttributeFilters: [], + eventNameFilters: [], + eventTypeFilters: [], + attributeFilters: [], + githubPath: null, + filteringEventAttributeValue: null, + filteringUserAttributeValue: null, + filteringConsentRuleValues: null, + consentRegulationFilters: [], + consentRegulationPurposeFilters: [], + messageTypeFilters: [], + messageTypeStateFilters: [], + eventSubscriptionId: 24884, + excludeAnonymousUser: false + }] + }; + mockServer$b.respondWith(urls.config, [200, {}, JSON.stringify(config)]); + mockServer$b.requests = []; + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(2); + var moduleIds = [124, 128]; + activeForwarders.forEach(function (forwarder) { + moduleIds.indexOf(forwarder.id).should.be.greaterThanOrEqual(0); + }); + done(); + }); + it('configures forwarders before events are logged via identify callback', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.identifyRequest = { + userIdentities: { + google: 'google123' + } + }; + window.mParticle.config.identityCallback = function () { + mParticle.logEvent('test event'); + }; + var mockForwarder = new MockForwarder$5(); + mockForwarder.register(window.mParticle.config); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('processCalled', true); - /** - * Parse a string for the raw tokens. - * - * @param {string} str - * @param {Object=} options - * @return {!Array} - */ - function parse (str, options) { - var tokens = []; - var key = 0; - var index = 0; - var path = ''; - var defaultDelimiter = options && options.delimiter || '/'; - var res; + //mock a page reload which has no configuredForwarders + mParticle.getInstance()._Store.configuredForwarders = []; + mParticle.init(apiKey, window.mParticle.config); + window.MockForwarder1.instance.should.have.property('processCalled', true); + done(); + }); + it('should retain preInit.forwarderConstructors, and reinitialize forwarders after calling reset, then init', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._getActiveForwarders().length.should.equal(1); - while ((res = PATH_REGEXP.exec(str)) != null) { - var m = res[0]; - var escaped = res[1]; - var offset = res.index; - path += str.slice(index, offset); - index = offset + m.length; + // client calls reset + mParticle.reset(); - // Ignore already escaped sequences. - if (escaped) { - path += escaped[1]; - continue - } + // forwarderConstructors are still there + mParticle.getInstance()._preInit.forwarderConstructors.length.should.equal(1); - var next = str[index]; - var prefix = res[2]; - var name = res[3]; - var capture = res[4]; - var group = res[5]; - var modifier = res[6]; - var asterisk = res[7]; + // client reinitializes mParticle after a reset + mParticle.init(apiKey, window.mParticle.config); - // Push the current path onto the tokens. - if (path) { - tokens.push(path); - path = ''; - } + // forwarderConstructors are still there + mParticle.getInstance()._getActiveForwarders().length.should.equal(1); + mParticle.logEvent('send this event to forwarder'); + window.MockForwarder1.instance.should.have.property('processCalled', true); + done(); + }); + it('should send SourceMessageId as part of event sent to forwarders', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('Test Event'); + window.MockForwarder1.instance.receivedEvent.should.have.property('SourceMessageId'); + done(); + }); + it('should send user-defined SourceMessageId as part of event sent to forwarders via baseEvent', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.logBaseEvent({ + messageType: 4, + name: 'Test Event', + data: { + key: 'value' + }, + eventType: mParticle.EventType.Navigation, + customFlags: { + flagKey: 'flagValue' + }, + sourceMessageId: 'abcdefg' + }); + window.MockForwarder1.instance.receivedEvent.should.have.property('SourceMessageId', 'abcdefg'); + done(); + }); + it('should add a logger to forwarders', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5(); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('MockForwarder')); + window.mParticle.config.logLevel = 'verbose'; + var infoMessage; + window.mParticle.config.logger = { + verbose: function verbose(msg) { + infoMessage = msg; + } + }; + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('Test Event'); + infoMessage.should.equal('Test Event sent'); + done(); + }); + describe('kits with suffixes', function () { + it('should add forwarders with suffixes and initialize them accordingly if there is a coresponding kit config with the same suffix', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5('ForwarderWithSuffixV3', 1, 'v3'); + var mockForwarder2 = new MockForwarder$5('ForwarderWithSuffixV4', 1, 'v4'); + mParticle.addForwarder(mockForwarder); + mParticle.addForwarder(mockForwarder2); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffixV3', 1, 'v3')); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffixV4', 1, 'v4')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._getActiveForwarders().length.should.equal(2); + done(); + }); + it('should not add a forwarder with suffix if there is not a corresponding kit config with the same suffix', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$5('ForwarderWithSuffix', 1, 'v3'); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('ForwarderWithSuffix', 1, 'v4')); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._getActiveForwarders().length.should.equal(0); + done(); + }); + }); + describe('side loaded kits', function () { + describe('initialization', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + delete mParticle._instances['default_instance']; + }); + afterEach(function () { + delete window.MockForwarder1; + mockServer$b.restore(); + }); + it('should add sideloaded kits to the active forwarders', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + expect(activeForwarders.length, 'active forwarders length').to.equal(sideloadedKits.length); + expect(activeForwarders[0].name, '1st active forwarder ').to.deep.equal(sideloadedKit1.name); + expect(activeForwarders[1].name, '2nd active forwarder').to.deep.equal(sideloadedKit2.name); + }); + it('should add sideloaded kits along with configured forwarders from server to the active forwarders', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + + // This mockForwarder simulates a server configured forwarder + var mockForwarder = new MockForwarder$5('fooForwarder', 1); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('fooForwarder', 1)); + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + expect(activeForwarders.length, 'active forwarders length').to.equal(sideloadedKits.length + 1); + expect(activeForwarders[0].name, '1st active forwarder name').to.equal('fooForwarder'); + expect(activeForwarders[1].name, '2nd active forwarder ').to.deep.equal(sideloadedKit1.name); + expect(activeForwarders[2].name, '3rd active forwarder').to.deep.equal(sideloadedKit2.name); + }); + it('should add a flag in batches for reporting if sideloaded kits are used', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + + // This mockForwarder simulates a server configured forwarder + var mockForwarder = new MockForwarder$5('fooForwarder', 1); + mParticle.addForwarder(mockForwarder); + window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration$3('fooForwarder', 1)); + mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + expect(mpInstance._Store.sideloadedKitsCount).to.equal(2); + mParticle.logEvent('foo', mParticle.EventType.Navigation); + var batch = JSON.parse(client.lastCall()[1].body); + expect(batch).to.have.property('application_info'); + expect(batch.application_info).to.have.property('sideloaded_kits_count', 2); + }); + it('should NOT add a flag in batches for reporting if sideloaded kits are not used', function () { + mParticle.init(apiKey, window.mParticle.config); + var mpInstance = window.mParticle.getInstance(); + expect(mpInstance._Store.isUsingSideloadedKits).to.be.undefined; + mParticle.logEvent('foo', mParticle.EventType.Navigation); + var batch = JSON.parse(client.lastCall()[1].body); + expect(batch).to.have.property('application_info'); + expect(batch.application_info).not.to.have.property('sideloaded_kits_count'); + }); + }); + describe('forwarding', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + delete mParticle._instances['default_instance']; + }); + afterEach(function () { + delete window.MockForwarder1; + mockServer$b.restore(); + }); + it('should send event to sideloaded kits', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.logEvent('foo', mParticle.EventType.Navigation); + var sideloadedKit1Event = window.SideloadedKit11.instance.receivedEvent; + var sideloadedKit2Event = window.SideloadedKit22.instance.receivedEvent; + sideloadedKit1Event.should.have.property('EventName', 'foo'); + sideloadedKit2Event.should.have.property('EventName', 'foo'); + }); + it('should invoke sideloaded identify call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.identifyRequest = { + userIdentities: { + google: 'google123' + } + }; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + window.SideloadedKit11.instance.should.have.property('setUserIdentityCalled', true); + window.SideloadedKit22.instance.should.have.property('setUserIdentityCalled', true); + window.SideloadedKit11.instance.should.have.property('onUserIdentifiedCalled', true); + window.SideloadedKit22.instance.should.have.property('onUserIdentifiedCalled', true); + }); + it('should invoke sideloaded set/removeUserAttribute call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().removeUserAttribute('gender'); + window.SideloadedKit11.instance.should.have.property('setUserAttributeCalled', true); + window.SideloadedKit22.instance.should.have.property('setUserAttributeCalled', true); + window.SideloadedKit11.instance.should.have.property('removeUserAttributeCalled', true); + window.SideloadedKit22.instance.should.have.property('removeUserAttributeCalled', true); + }); + it('should invoke sideloaded logout call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.logout(); + window.SideloadedKit11.instance.should.have.property('onLogoutCompleteCalled', true); + window.SideloadedKit22.instance.should.have.property('onLogoutCompleteCalled', true); + }); + it('should invoke sideloaded login call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.login({ + userIdentities: { + customerid: 'abc' + } + }); + window.SideloadedKit11.instance.should.have.property('onLoginCompleteCalled', true); + window.SideloadedKit22.instance.should.have.property('onLoginCompleteCalled', true); + }); + it('should invoke sideloaded modify call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.modify({ + userIdentities: { + customerid: 'abc' + } + }); + window.SideloadedKit11.instance.should.have.property('onModifyCompleteCalled', true); + window.SideloadedKit22.instance.should.have.property('onModifyCompleteCalled', true); + }); + it('should invoke sideloaded modify call', function () { + var sideloadedKit1 = new MockSideloadedKit$1('SideloadedKit1', 1); + var sideloadedKit2 = new MockSideloadedKit$1('SideloadedKit2', 2); + var mpSideloadedKit1 = new mParticle.MPSideloadedKit(sideloadedKit1); + var mpSideloadedKit2 = new mParticle.MPSideloadedKit(sideloadedKit2); + var sideloadedKits = [mpSideloadedKit1, mpSideloadedKit2]; + window.mParticle.config.sideloadedKits = sideloadedKits; + mParticle.init(apiKey, window.mParticle.config); + mParticle.setOptOut(true); + window.SideloadedKit11.instance.should.have.property('setOptOutCalled', true); + window.SideloadedKit22.instance.should.have.property('setOptOutCalled', true); + }); + }); + }); + }); - var partial = prefix != null && next != null && next !== prefix; - var repeat = modifier === '+' || modifier === '*'; - var optional = modifier === '?' || modifier === '*'; - var delimiter = res[2] || defaultDelimiter; - var pattern = capture || group; + describe('helpers', function () { + beforeEach(function () { + mParticle.init(apiKey, window.mParticle.config); + }); + it('should correctly validate an attribute value', function (done) { + var validatedString = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue('testValue1'); + var validatedNumber = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(1); + var validatedNull = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(null); + var validatedObject = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue({}); + var validatedArray = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue([]); + var validatedUndefined = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(undefined); + validatedString.should.be.ok(); + validatedNumber.should.be.ok(); + validatedNull.should.be.ok(); + validatedObject.should.not.be.ok(); + validatedArray.should.not.be.ok(); + validatedUndefined.should.not.be.ok(); + done(); + }); + it('should return event name in warning when sanitizing invalid attributes', function (done) { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.logEvent('eventName', mParticle.EventType.Location, { + invalidValue: {} + }); + bond.called.should.eql(true); + bond.callCount.should.equal(1); + bond.getCalls()[0].args[0].should.eql("For 'eventName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); + done(); + }); + it('should return product name in warning when sanitizing invalid attributes', function (done) { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.eCommerce.createProduct('productName', 'sku', 1, 1, 'variant', 'category', 'brand', 'position', 'couponCode', { + invalidValue: {} + }); + bond.called.should.eql(true); + bond.callCount.should.equal(1); + bond.getCalls()[0].args[0].should.eql("For 'productName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); + done(); + }); + it('should return commerce event name in warning when sanitizing invalid attributes', function (done) { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + var product1 = mParticle.eCommerce.createProduct('prod1', 'prod1sku', 999); + var product2 = mParticle.eCommerce.createProduct('prod2', 'prod2sku', 799); + var customAttributes = { + invalidValue: {} + }; + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, [product1, product2], customAttributes); + bond.called.should.eql(true); + bond.callCount.should.equal(1); + bond.getCalls()[0].args[0].should.eql("For 'eCommerce - AddToCart', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); + done(); + }); + it('should correctly validate an identity request with copyUserAttribute as a key using any identify method', function (done) { + var identityApiData = { + userIdentities: { + customerid: '123' + }, + copyUserAttributes: true + }; + var identifyResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'identify'); + var logoutResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'logout'); + var loginResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'login'); + var modifyResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'modify'); + identifyResult.valid.should.equal(true); + logoutResult.valid.should.equal(true); + loginResult.valid.should.equal(true); + modifyResult.valid.should.equal(true); + done(); + }); + it('should correctly parse string or number', function (done) { + var string = 'abc'; + var number = 123; + var object = {}; + var array = []; + var stringResult = mParticle.getInstance()._Helpers.parseStringOrNumber(string); + var numberResult = mParticle.getInstance()._Helpers.parseStringOrNumber(number); + var objectResult = mParticle.getInstance()._Helpers.parseStringOrNumber(object); + var arrayResult = mParticle.getInstance()._Helpers.parseStringOrNumber(array); + var nullResult = mParticle.getInstance()._Helpers.parseStringOrNumber(null); + stringResult.should.equal(string); + numberResult.should.equal(number); + Should(objectResult).not.be.ok(); + Should(arrayResult).not.be.ok(); + Should(nullResult).not.be.ok(); + done(); + }); + it('should filterUserIdentities and include customerId as first in the array', function (done) { + var filterList = [2, 4, 6, 8]; + var userIdentitiesObject = { + email: 'test@gmail.com', + other: 'abc', + customerid: '123', + facebook: 'facebook123', + google: 'google123', + yahoo: 'yahoo123' + }; + var filteredIdentities = mParticle.getInstance()._Helpers.filterUserIdentities(userIdentitiesObject, filterList); + filteredIdentities.length.should.equal(3); + filteredIdentities[0].should.have.property('Identity', '123'); + filteredIdentities[0].should.have.property('Type', 1); + filteredIdentities[1].should.have.property('Identity', 'test@gmail.com'); + filteredIdentities[1].should.have.property('Type', 7); + filteredIdentities[2].should.have.property('Identity', 'abc'); + filteredIdentities[2].should.have.property('Type', 0); + done(); + }); + it('should return the appropriate boolean for if events should be delayed by an integration', function (done) { + var integrationDelays1 = { + 128: false, + 20: false, + 10: true + }; + var integrationDelays2 = { + 128: true + }; + var integrationDelays3 = { + 128: false + }; + var integrationDelays4 = { + 128: false, + 20: false, + 10: false + }; + var result1 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays1); + var result2 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays2); + var result3 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays3); + var result4 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays4); + result1.should.equal(true); + result2.should.equal(true); + result3.should.equal(false); + result4.should.equal(false); + done(); + }); + it('should return false if integration delay object is empty', function (done) { + var emptyIntegrationDelays = {}; + var result1 = mParticle.getInstance()._Helpers.isDelayedByIntegration(emptyIntegrationDelays); + result1.should.equal(false); + done(); + }); + it('should return expected boolean value when strings are passed', function (done) { + mParticle.getInstance()._Helpers.returnConvertedBoolean('false').should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean(false).should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true); + mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true); + mParticle.getInstance()._Helpers.returnConvertedBoolean('randomstring').should.equal(true); + mParticle.getInstance()._Helpers.returnConvertedBoolean(0).should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean(1).should.equal(true); + mParticle.getInstance()._Helpers.returnConvertedBoolean('0').should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean('1').should.equal(true); + mParticle.getInstance()._Helpers.returnConvertedBoolean(null).should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean(undefined).should.equal(false); + mParticle.getInstance()._Helpers.returnConvertedBoolean('').should.equal(false); + done(); + }); + it('should return 0 when hashing undefined or null', function (done) { + mParticle.generateHash(undefined).should.equal(0); + mParticle.generateHash(null).should.equal(0); + _typeof(mParticle.generateHash(false)).should.equal('number'); + mParticle.generateHash(false).should.not.equal(0); + done(); + }); + it('should generate random value', function (done) { + var randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); + randomValue.should.be.ok(); + window.crypto.getRandomValues = undefined; + randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); + randomValue.should.be.ok(); + //old browsers may return undefined despite + //defining the getRandomValues API. + window.crypto.getRandomValues = function (a) { + a = undefined; + return a; + }; + randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); + randomValue.should.be.ok(); + done(); + }); + it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in', function (done) { + var cookieName = mParticle.getInstance()._Helpers.createMainStorageName(apiKey); + cookieName.should.equal('mprtcl-v4_test_key'); + done(); + }); + it('should create a storage name based on default mParticle storage version if no apiKey is passed in', function (done) { + var cookieName = mParticle.getInstance()._Helpers.createMainStorageName(); + cookieName.should.equal('mprtcl-v4'); + done(); + }); + it('should create a product storage name based on default mParticle storage version + apiKey if apiKey is passed in', function (done) { + var cookieName = mParticle.getInstance()._Helpers.createProductStorageName(apiKey); + cookieName.should.equal('mprtcl-prodv4_test_key'); + done(); + }); + it('should create a product storage name based on default mParticle storage version if no apiKey is passed in', function (done) { + var cookieName = mParticle.getInstance()._Helpers.createProductStorageName(); + cookieName.should.equal('mprtcl-prodv4'); + done(); + }); + }); - tokens.push({ - name: name || key++, - prefix: prefix || '', - delimiter: delimiter, - optional: optional, - repeat: repeat, - partial: partial, - asterisk: !!asterisk, - pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') + function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } + function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } + function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } + var getLocalStorage$3 = TestsCore.getLocalStorage, + setLocalStorage$1 = TestsCore.setLocalStorage, + findCookie = TestsCore.findCookie, + forwarderDefaultConfiguration$2 = TestsCore.forwarderDefaultConfiguration, + getLocalStorageProducts$1 = TestsCore.getLocalStorageProducts, + findEventFromRequest$5 = TestsCore.findEventFromRequest, + findBatch$4 = TestsCore.findBatch, + getIdentityEvent$1 = TestsCore.getIdentityEvent, + setCookie = TestsCore.setCookie, + MockForwarder$4 = TestsCore.MockForwarder, + HTTPCodes$1 = Constants.HTTPCodes; + var mockServer$a; + describe('identity', function () { + beforeEach(function () { + delete mParticle.config.useCookieStorage; + client.post(urls.events, 200); + mockServer$a = sinon$1.createFakeServer(); + mockServer$a.respondImmediately = true; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$a.restore(); + client.restore(); + mParticle._resetForTests(MPConfig); + }); + it('should respect consent rules on consent-change', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var mockForwarder = new MockForwarder$4('MockForwarder1'); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$2('MockForwarder1', 1); + config1.filteringConsentRuleValues = { + includeOnMatch: true, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: true + }] + }; + var mockForwarder2 = new MockForwarder$4('MockForwarder2', 2); + mockForwarder2.register(window.mParticle.config); + var config2 = forwarderDefaultConfiguration$2('MockForwarder2', 2); + config2.filteringConsentRuleValues = { + includeOnMatch: true, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 2'), + hasConsented: true + }] + }; + window.mParticle.config.kitConfigs.push(config1); + window.mParticle.config.kitConfigs.push(config2); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + var activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.not.be.ok(); + var consentState = mParticle.Consent.createConsentState(); + consentState.addGDPRConsentState('foo purpose 1', mParticle.Consent.createGDPRConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(consentState); + activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(1); + activeForwarders[0].name.should.equal('MockForwarder1'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mParticle.Identity.login(); + activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.not.be.ok(); + consentState = mParticle.Consent.createConsentState(); + consentState.addGDPRConsentState('foo purpose 2', mParticle.Consent.createGDPRConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(consentState); + activeForwarders = mParticle.getInstance()._getActiveForwarders(); + activeForwarders.length.should.equal(1); + activeForwarders[0].name.should.equal('MockForwarder2'); + done(); + }); + it('should not do an identity swap if there is no MPID change', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var cookiesBefore = getLocalStorage$3(); + mParticle.getInstance()._Identity.checkIdentitySwap(testMPID, testMPID); + var cookiesAfter = mParticle.getInstance()._Persistence.getLocalStorage(); + cookiesBefore.cu.should.equal(cookiesAfter.cu); + done(); + }); + it('should do an identity swap if there is an MPID change', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var cookiesBefore = getLocalStorage$3(); + mParticle.getInstance()._Identity.checkIdentitySwap(testMPID, 'currentMPID'); + var cookiesAfter = mParticle.getInstance()._Persistence.getLocalStorage(); + cookiesBefore.cu.should.equal(testMPID); + cookiesAfter.cu.should.equal('currentMPID'); + done(); + }); + it('should store all MPIDs associated with a sessionId, then clear MPIDs from currentSessionMPIDs when a new session starts', function (done) { + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(); + var localStorageDataBeforeSessionEnd = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorageDataBeforeSessionEnd.gs.csm.length.should.equal(2); + mParticle.endSession(); + var localStorageDataAfterSessionEnd1 = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorageDataAfterSessionEnd1.gs.should.not.have.property('csm'); + mParticle.logEvent('hi'); + mParticle.Identity.login(); + var localStorageAfterLoggingEvent = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorageAfterLoggingEvent.gs.csm.length.should.equal(1); + done(); + }); + it('localStorage - should switch user cookies to new mpid details from cookies when a new mpid is provided', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.useCookieStorage = false; + setLocalStorage$1(); + mParticle.init(apiKey, window.mParticle.config); + var cookies1 = mParticle.getInstance()._Persistence.getLocalStorage(); + cookies1.cu.should.equal(testMPID); + cookies1[testMPID].should.have.property('csd'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(); + var cookiesAfterMPIDChange = mParticle.getInstance()._Persistence.getLocalStorage(); + cookiesAfterMPIDChange.should.have.properties(['cu', 'otherMPID', testMPID, 'gs']); + cookiesAfterMPIDChange.should.have.property('cu', 'otherMPID'); + cookiesAfterMPIDChange[testMPID].should.have.property('csd'); + var props = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props.forEach(function (prop) { + cookiesAfterMPIDChange[testMPID].should.not.have.property(prop); + cookiesAfterMPIDChange['otherMPID'].should.not.have.property(prop); }); - } - - // Match any characters still remaining. - if (index < str.length) { - path += str.substr(index); - } - - // If the path exists, push it onto the end. - if (path) { - tokens.push(path); - } - - return tokens - } - - /** - * Compile a string to a template function for the path. - * - * @param {string} str - * @param {Object=} options - * @return {!function(Object=, Object=)} - */ - function compile (str, options) { - return tokensToFunction(parse(str, options), options) - } - - /** - * Prettier encoding of URI path segments. - * - * @param {string} - * @return {string} - */ - function encodeURIComponentPretty (str) { - return encodeURI(str).replace(/[\/?#]/g, function (c) { - return '%' + c.charCodeAt(0).toString(16).toUpperCase() - }) - } - - /** - * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. - * - * @param {string} - * @return {string} - */ - function encodeAsterisk (str) { - return encodeURI(str).replace(/[?#]/g, function (c) { - return '%' + c.charCodeAt(0).toString(16).toUpperCase() - }) - } - - /** - * Expose a method for transforming tokens into the path function. - */ - function tokensToFunction (tokens, options) { - // Compile all the tokens into regexps. - var matches = new Array(tokens.length); - - // Compile all the patterns before compilation. - for (var i = 0; i < tokens.length; i++) { - if (typeof tokens[i] === 'object') { - matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options)); - } - } - - return function (obj, opts) { - var path = ''; - var data = obj || {}; - var options = opts || {}; - var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent; - - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - - if (typeof token === 'string') { - path += token; - - continue - } - - var value = data[token.name]; - var segment; - - if (value == null) { - if (token.optional) { - // Prepend partial segment prefixes. - if (token.partial) { - path += token.prefix; - } - - continue - } else { - throw new TypeError('Expected "' + token.name + '" to be defined') - } + done(); + }); + it('cookies - should switch user cookies to new mpid details from cookies when a new mpid is provided', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.useCookieStorage = true; + setLocalStorage$1(); + mParticle.init(apiKey, window.mParticle.config); + var cookiesAfterInit = findCookie(); + cookiesAfterInit.should.have.properties('gs', 'cu', testMPID); + var props1 = ['mpid', 'ui', 'ua', 'les', 'sid', 'ie', 'dt', 'sa', 'ss', 'cp']; + props1.forEach(function (prop) { + cookiesAfterInit.should.not.have.property(prop); + }); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(); + var cookiesAfterMPIDChange = findCookie(); + cookiesAfterMPIDChange.should.have.properties(['cu', 'gs', 'otherMPID', testMPID]); + cookiesAfterMPIDChange.should.have.property('cu', 'otherMPID'); + var props2 = ['ie', 'sa', 'ss', 'dt', 'les', 'av', 'cgid', 'das', 'sid', 'c', 'mpid', 'cp']; + props2.forEach(function (prop) { + cookiesAfterMPIDChange[testMPID].should.not.have.property(prop); + cookiesAfterMPIDChange['otherMPID'].should.not.have.property(prop); + }); + done(); + }); + it('should swap property identityType for identityName', function (done) { + var data = { + userIdentities: {} + }; + data.userIdentities.other = 'id1'; + data.userIdentities.customerid = 'id2'; + data.userIdentities.facebook = 'id3'; + data.userIdentities.twitter = 'id4'; + data.userIdentities.google = 'id5'; + data.userIdentities.microsoft = 'id6'; + data.userIdentities.yahoo = 'id7'; + data.userIdentities.email = 'id8'; + data.userIdentities.facebookcustomaudienceid = 'id9'; + data.userIdentities.other2 = 'id10'; + data.userIdentities.other3 = 'id11'; + data.userIdentities.other4 = 'id12'; + var count = 0; + for (var key in data.userIdentities) { + mParticle.IdentityType.getIdentityType(key).should.equal(count); + count++; + // 8 is alias, which was removed + if (count === 8) { + count = 9; } - - if (isarray(value)) { - if (!token.repeat) { - throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') - } - - if (value.length === 0) { - if (token.optional) { - continue - } else { - throw new TypeError('Expected "' + token.name + '" to not be empty') - } - } - - for (var j = 0; j < value.length; j++) { - segment = encode(value[j]); - - if (!matches[i].test(segment)) { - throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') - } - - path += (j === 0 ? token.prefix : token.delimiter) + segment; - } - - continue + } + done(); + }); + it('should create a proper identity request', function (done) { + var data = { + userIdentities: {} + }, + platform = 'web', + sdkVendor = 'mparticle', + sdkVersion = '1.0.0', + deviceId = 'abc', + context = null; + data.userIdentities.other = 'id1'; + data.userIdentities.customerid = 'id2'; + data.userIdentities.facebook = 'id3'; + data.userIdentities.twitter = 'id4'; + data.userIdentities.google = 'id5'; + data.userIdentities.microsoft = 'id6'; + data.userIdentities.yahoo = 'id7'; + data.userIdentities.email = 'id8'; + data.userIdentities.facebookcustomaudienceid = 'id9'; + data.userIdentities.other2 = 'id10'; + data.userIdentities.other3 = 'id11'; + data.userIdentities.other4 = 'id12'; + data.userIdentities.other5 = 'id13'; + data.userIdentities.other6 = 'id14'; + data.userIdentities.other7 = 'id15'; + data.userIdentities.other8 = 'id16'; + data.userIdentities.other9 = 'id17'; + data.userIdentities.other10 = 'id18'; + data.userIdentities.mobile_number = 'id19'; + data.userIdentities.phone_number_2 = 'id20'; + data.userIdentities.phone_number_3 = 'id21'; + var identityRequest = mParticle.getInstance()._Identity.IdentityRequest.createIdentityRequest(data, platform, sdkVendor, sdkVersion, deviceId, context, testMPID); + identityRequest.should.have.properties(['client_sdk', 'environment', 'context', 'known_identities', 'previous_mpid', 'request_id', 'request_timestamp_ms']); + identityRequest.client_sdk.should.have.properties(['platform', 'sdk_vendor', 'sdk_version']); + identityRequest.client_sdk.platform.should.equal(platform); + identityRequest.client_sdk.sdk_vendor.should.equal(sdkVendor); + identityRequest.environment.should.equal('production'); + identityRequest.previous_mpid.should.equal(testMPID); + identityRequest.known_identities.should.have.properties(['other', 'customerid', 'facebook', 'twitter', 'google', 'microsoft', 'yahoo', 'email', 'facebookcustomaudienceid', 'other2', 'other3', 'other4', 'other5', 'other6', 'other7', 'other8', 'other9', 'other10', 'phone_number_2', 'phone_number_3', 'mobile_number', 'device_application_stamp']); + identityRequest.known_identities.other.should.equal('id1'); + identityRequest.known_identities.customerid.should.equal('id2'); + identityRequest.known_identities.facebook.should.equal('id3'); + identityRequest.known_identities.twitter.should.equal('id4'); + identityRequest.known_identities.google.should.equal('id5'); + identityRequest.known_identities.microsoft.should.equal('id6'); + identityRequest.known_identities.yahoo.should.equal('id7'); + identityRequest.known_identities.email.should.equal('id8'); + identityRequest.known_identities.facebookcustomaudienceid.should.equal('id9'); + identityRequest.known_identities.other2.should.equal('id10'); + identityRequest.known_identities.other3.should.equal('id11'); + identityRequest.known_identities.other4.should.equal('id12'); + identityRequest.known_identities.other5.should.equal('id13'); + identityRequest.known_identities.other6.should.equal('id14'); + identityRequest.known_identities.other7.should.equal('id15'); + identityRequest.known_identities.other8.should.equal('id16'); + identityRequest.known_identities.other9.should.equal('id17'); + identityRequest.known_identities.other10.should.equal('id18'); + identityRequest.known_identities.mobile_number.should.equal('id19'); + identityRequest.known_identities.phone_number_2.should.equal('id20'); + identityRequest.known_identities.phone_number_3.should.equal('id21'); + done(); + }); + it('should create a proper modify identity request', function (done) { + var oldIdentities = {}, + platform = 'web', + sdkVendor = 'mparticle', + sdkVersion = '1.0.0', + deviceId = 'abc', + context = null; + oldIdentities['other'] = 'id1'; + oldIdentities['customerid'] = 'id2'; + oldIdentities['facebook'] = 'id3'; + oldIdentities['twitter'] = 'id4'; + oldIdentities['google'] = 'id5'; + oldIdentities['microsoft'] = 'id6'; + oldIdentities['yahoo'] = 'id7'; + oldIdentities['email'] = 'id8'; + oldIdentities['facebookcustomaudienceid'] = 'id9'; + oldIdentities['other1'] = 'id10'; + oldIdentities['other2'] = 'id11'; + oldIdentities['other3'] = 'id12'; + oldIdentities['other4'] = 'id13'; + oldIdentities['other5'] = 'id14'; + oldIdentities['other6'] = 'id15'; + oldIdentities['other7'] = 'id16'; + oldIdentities['other8'] = 'id17'; + oldIdentities['other9'] = 'id18'; + oldIdentities['other10'] = 'id19'; + oldIdentities['mobile_number'] = 'id20'; + oldIdentities['phone_number_2'] = 'id21'; + oldIdentities['phone_number_3'] = 'id22'; + var newIdentities = {}; + newIdentities.other = 'id14'; + newIdentities.customerid = 'id15'; + newIdentities.facebook = 'id16'; + newIdentities.twitter = 'id17'; + newIdentities.google = 'id18'; + newIdentities.microsoft = 'id19'; + newIdentities.yahoo = 'id20'; + newIdentities.email = 'id21'; + newIdentities.facebookcustomaudienceid = 'id22'; + newIdentities.other1 = 'id23'; + newIdentities.other2 = 'id24'; + newIdentities.other3 = 'id25'; + newIdentities.other4 = 'id26'; + newIdentities.other5 = 'id27'; + newIdentities.other6 = 'id28'; + newIdentities.other7 = 'id29'; + newIdentities.other8 = 'id30'; + newIdentities.other9 = 'id31'; + newIdentities.other10 = 'id32'; + newIdentities.mobile_number = 'id33'; + newIdentities.phone_number_2 = 'id34'; + newIdentities.phone_number_3 = 'id35'; + var identityRequest = mParticle.getInstance()._Identity.IdentityRequest.createModifyIdentityRequest(oldIdentities, newIdentities, platform, sdkVendor, sdkVersion, deviceId, context, testMPID); + identityRequest.should.have.properties(['client_sdk', 'environment', 'identity_changes', 'request_id', 'request_timestamp_ms']); + identityRequest.client_sdk.should.have.properties(['platform', 'sdk_vendor', 'sdk_version']); + identityRequest.client_sdk.platform.should.equal('web'); + identityRequest.client_sdk.sdk_vendor.should.equal('mparticle'); + identityRequest.environment.should.equal('production'); + identityRequest.identity_changes[0].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[0].old_value.should.equal('id1'); + identityRequest.identity_changes[0].identity_type.should.equal('other'); + identityRequest.identity_changes[0].new_value.should.equal('id14'); + identityRequest.identity_changes[1].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[1].old_value.should.equal('id2'); + identityRequest.identity_changes[1].identity_type.should.equal('customerid'); + identityRequest.identity_changes[1].new_value.should.equal('id15'); + identityRequest.identity_changes[2].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[2].old_value.should.equal('id3'); + identityRequest.identity_changes[2].identity_type.should.equal('facebook'); + identityRequest.identity_changes[2].new_value.should.equal('id16'); + identityRequest.identity_changes[3].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[3].old_value.should.equal('id4'); + identityRequest.identity_changes[3].identity_type.should.equal('twitter'); + identityRequest.identity_changes[3].new_value.should.equal('id17'); + identityRequest.identity_changes[4].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[4].old_value.should.equal('id5'); + identityRequest.identity_changes[4].identity_type.should.equal('google'); + identityRequest.identity_changes[4].new_value.should.equal('id18'); + identityRequest.identity_changes[5].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[5].old_value.should.equal('id6'); + identityRequest.identity_changes[5].identity_type.should.equal('microsoft'); + identityRequest.identity_changes[5].new_value.should.equal('id19'); + identityRequest.identity_changes[6].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[6].old_value.should.equal('id7'); + identityRequest.identity_changes[6].identity_type.should.equal('yahoo'); + identityRequest.identity_changes[6].new_value.should.equal('id20'); + identityRequest.identity_changes[7].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[7].old_value.should.equal('id8'); + identityRequest.identity_changes[7].identity_type.should.equal('email'); + identityRequest.identity_changes[7].new_value.should.equal('id21'); + identityRequest.identity_changes[8].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[8].old_value.should.equal('id9'); + identityRequest.identity_changes[8].identity_type.should.equal('facebookcustomaudienceid'); + identityRequest.identity_changes[8].new_value.should.equal('id22'); + identityRequest.identity_changes[9].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[9].old_value.should.equal('id10'); + identityRequest.identity_changes[9].identity_type.should.equal('other1'); + identityRequest.identity_changes[9].new_value.should.equal('id23'); + identityRequest.identity_changes[10].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[10].old_value.should.equal('id11'); + identityRequest.identity_changes[10].identity_type.should.equal('other2'); + identityRequest.identity_changes[10].new_value.should.equal('id24'); + identityRequest.identity_changes[11].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[11].old_value.should.equal('id12'); + identityRequest.identity_changes[11].identity_type.should.equal('other3'); + identityRequest.identity_changes[11].new_value.should.equal('id25'); + identityRequest.identity_changes[12].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[12].old_value.should.equal('id13'); + identityRequest.identity_changes[12].identity_type.should.equal('other4'); + identityRequest.identity_changes[12].new_value.should.equal('id26'); + identityRequest.identity_changes[13].old_value.should.equal('id14'); + identityRequest.identity_changes[13].identity_type.should.equal('other5'); + identityRequest.identity_changes[13].new_value.should.equal('id27'); + identityRequest.identity_changes[14].old_value.should.equal('id15'); + identityRequest.identity_changes[14].identity_type.should.equal('other6'); + identityRequest.identity_changes[14].new_value.should.equal('id28'); + identityRequest.identity_changes[15].old_value.should.equal('id16'); + identityRequest.identity_changes[15].identity_type.should.equal('other7'); + identityRequest.identity_changes[15].new_value.should.equal('id29'); + identityRequest.identity_changes[16].old_value.should.equal('id17'); + identityRequest.identity_changes[16].identity_type.should.equal('other8'); + identityRequest.identity_changes[16].new_value.should.equal('id30'); + identityRequest.identity_changes[17].old_value.should.equal('id18'); + identityRequest.identity_changes[17].identity_type.should.equal('other9'); + identityRequest.identity_changes[17].new_value.should.equal('id31'); + identityRequest.identity_changes[18].old_value.should.equal('id19'); + identityRequest.identity_changes[18].identity_type.should.equal('other10'); + identityRequest.identity_changes[18].new_value.should.equal('id32'); + identityRequest.identity_changes[19].old_value.should.equal('id20'); + identityRequest.identity_changes[19].identity_type.should.equal('mobile_number'); + identityRequest.identity_changes[19].new_value.should.equal('id33'); + identityRequest.identity_changes[20].old_value.should.equal('id21'); + identityRequest.identity_changes[20].identity_type.should.equal('phone_number_2'); + identityRequest.identity_changes[20].new_value.should.equal('id34'); + identityRequest.identity_changes[21].old_value.should.equal('id22'); + identityRequest.identity_changes[21].identity_type.should.equal('phone_number_3'); + identityRequest.identity_changes[21].new_value.should.equal('id35'); + done(); + }); + it('should not make a request when an invalid request is sent to login', function (done) { + var identityAPIRequest1 = { + userIdentities: 'badUserIdentitiesString' + }; + mParticle.Identity.login(identityAPIRequest1); + var badData1 = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(badData1).not.be.ok(); + var identityAPIRequest2 = { + userIdentities: ['bad', 'user', 'identities', 'array'] + }; + mParticle.Identity.login(identityAPIRequest2); + var badData2 = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(badData2).not.be.ok(); + var identityAPIRequest3 = { + userIdentities: undefined + }; + mParticle.Identity.login(identityAPIRequest3); + var badData3 = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(badData3).not.be.ok(); + var identityAPIRequest4 = { + userIdentities: true + }; + mParticle.Identity.login(identityAPIRequest4); + var badData4 = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(badData4).not.be.ok(); + done(); + }); + it('should not make a request when an invalid request is sent to logout', function (done) { + var identityAPIRequest1 = { + userIdentities: 'badUserIdentitiesString' + }; + mParticle.Identity.logout(identityAPIRequest1); + var badData1 = getIdentityEvent$1(mockServer$a.requests, 'logout'); + Should(badData1).not.be.ok(); + var identityAPIRequest2 = { + userIdentities: ['bad', 'user', 'identities', 'array'] + }; + mParticle.Identity.logout(identityAPIRequest2); + var badData2 = getIdentityEvent$1(mockServer$a.requests, 'logout'); + Should(badData2).not.be.ok(); + var identityAPIRequest3 = { + userIdentities: undefined + }; + mParticle.Identity.logout(identityAPIRequest3); + var badData3 = getIdentityEvent$1(mockServer$a.requests, 'logout'); + Should(badData3).not.be.ok(); + var identityAPIRequest4 = { + userIdentities: true + }; + mParticle.Identity.logout(identityAPIRequest4); + var badData4 = getIdentityEvent$1(mockServer$a.requests, 'logout'); + Should(badData4).not.be.ok(); + done(); + }); + it('should not make a request when an invalid request is sent to modify', function (done) { + var identityAPIRequest1 = { + userIdentities: 'badUserIdentitiesString' + }; + mParticle.Identity.modify(identityAPIRequest1); + var badData1 = getIdentityEvent$1(mockServer$a.requests, 'modify'); + Should(badData1).not.be.ok(); + var identityAPIRequest2 = { + userIdentities: ['bad', 'user', 'identities', 'array'] + }; + mParticle.Identity.modify(identityAPIRequest2); + var badData2 = getIdentityEvent$1(mockServer$a.requests, 'modify'); + Should(badData2).not.be.ok(); + var identityAPIRequest3 = { + userIdentities: null + }; + mParticle.Identity.modify(identityAPIRequest3); + var badData3 = getIdentityEvent$1(mockServer$a.requests, 'modify'); + Should(badData3).not.be.ok(); + var identityAPIRequest4 = { + userIdentities: undefined + }; + mParticle.Identity.modify(identityAPIRequest4); + var badData4 = getIdentityEvent$1(mockServer$a.requests, 'modify'); + Should(badData4).not.be.ok(); + var identityAPIRequest5 = { + userIdentities: true + }; + mParticle.Identity.modify(identityAPIRequest5); + var badData5 = getIdentityEvent$1(mockServer$a.requests, 'modify'); + Should(badData5).not.be.ok(); + done(); + }); + it('should not make a request when an invalid request is sent to identify', function (done) { + mockServer$a.requests = []; + var identityAPIRequest1 = { + userIdentities: 'badUserIdentitiesString' + }; + mParticle.Identity.identify(identityAPIRequest1); + var badData1 = getIdentityEvent$1(mockServer$a.requests, 'identify'); + Should(badData1).not.be.ok(); + var identityAPIRequest2 = { + userIdentities: ['bad', 'user', 'identities', 'array'] + }; + mParticle.Identity.identify(identityAPIRequest2); + var badData2 = getIdentityEvent$1(mockServer$a.requests, 'identify'); + Should(badData2).not.be.ok(); + var identityAPIRequest3 = { + userIdentities: undefined + }; + mParticle.Identity.identify(identityAPIRequest3); + var badData3 = getIdentityEvent$1(mockServer$a.requests, 'identify'); + Should(badData3).not.be.ok(); + var identityAPIRequest4 = { + userIdentities: true + }; + mParticle.Identity.identify(identityAPIRequest4); + var badData4 = getIdentityEvent$1(mockServer$a.requests, 'identify'); + Should(badData4).not.be.ok(); + done(); + }); + it('should have old_value === null when there is no previous identity of a certain type and a new identity of that type', function (done) { + var oldIdentities = {}; + oldIdentities['facebook'] = 'old_facebook_id'; + var newIdentities = {}; + newIdentities.other = 'new_other_id'; + newIdentities.facebook = 'new_facebook_id'; + var identityRequest = mParticle.getInstance()._Identity.IdentityRequest.createModifyIdentityRequest(oldIdentities, newIdentities); + identityRequest.identity_changes[0].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[0].should.have.property('old_value', null); + identityRequest.identity_changes[0].identity_type.should.equal('other'); + identityRequest.identity_changes[0].new_value.should.equal('new_other_id'); + identityRequest.identity_changes[1].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[1].should.have.property('old_value', 'old_facebook_id'); + identityRequest.identity_changes[1].identity_type.should.equal('facebook'); + identityRequest.identity_changes[1].new_value.should.equal('new_facebook_id'); + done(); + }); + it('should have new_value === null when there is a previous identity of a certain type and no new identity of that type', function (done) { + var oldIdentities = {}; + oldIdentities['other'] = 'old_other_id'; + oldIdentities['facebook'] = 'old_facebook_id'; + var newIdentities = {}; + newIdentities.facebook = 'new_facebook_id'; + var identityRequest = mParticle.getInstance()._Identity.IdentityRequest.createModifyIdentityRequest(oldIdentities, newIdentities); + identityRequest.identity_changes[0].should.have.properties(['identity_type', 'new_value', 'old_value']); + identityRequest.identity_changes[0].old_value.should.equal('old_facebook_id'); + identityRequest.identity_changes[0].identity_type.should.equal('facebook'); + identityRequest.identity_changes[0].new_value.should.equal('new_facebook_id'); + identityRequest.identity_changes.length.should.equal(1); + done(); + }); + it('should create a proper send request when passing identities to modify', function (done) { + var identityAPIData = { + userIdentities: { + email: 'rob@gmail.com' } - - segment = token.asterisk ? encodeAsterisk(value) : encode(value); - - if (!matches[i].test(segment)) { - throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') + }; + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.modify(identityAPIData); + var data = getIdentityEvent$1(mockServer$a.requests, 'modify'); + data.identity_changes.length.should.equal(1); + data.identity_changes[0].should.have.properties('old_value', 'new_value', 'identity_type'); + data.identity_changes[0].should.have.properties('old_value', 'new_value', 'identity_type'); + done(); + }); + it('Ensure that automatic identify is not called more than once.', function (done) { + mParticle._resetForTests(MPConfig); + var spy = sinon$1.spy(); + mParticle.config.identityCallback = spy; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + spy.calledOnce.should.be.ok(); + mParticle.startNewSession(); + spy.calledOnce.should.be.ok(); + done(); + }); + it('queue events when MPID is 0, and then flush events once MPID changes', function (done) { + mParticle._resetForTests(MPConfig); + mockServer$a.respondWith(urls.identify, [0, {}, JSON.stringify({})]); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('Test Event1'); + var testEvent1 = findEventFromRequest$5(client._calls, 'Test Event1'); + Should(testEvent1).not.be.ok(); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.logEvent('Test Event2'); + mParticle.Identity.login(); + // server requests will have AST, sessionStart, Test1, Test2, and login + testEvent1 = findEventFromRequest$5(client._calls, 'Test Event1'); + client._calls.length.should.equal(4); + var testEvent2 = findEventFromRequest$5(client._calls, 'Test Event2'); + var ASTEvent = findEventFromRequest$5(client._calls, 'application_state_transition'); + var sessionStartEvent = findEventFromRequest$5(client._calls, 'session_start'); + var loginEvent = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(testEvent1).be.ok(); + Should(testEvent2).be.ok(); + Should(ASTEvent).be.ok(); + Should(sessionStartEvent).be.ok(); + Should(loginEvent).be.ok(); + done(); + }); + it('getUsers should return all mpids available in local storage', function (done) { + mParticle._resetForTests(MPConfig); + var user1 = {}; + var user2 = {}; + var user3 = { + userIdentities: { + customerid: 'customerid3', + email: 'email3@test.com' } + }; + mParticle.init(apiKey, window.mParticle.config); - path += token.prefix + segment; - } - - return path - } - } - - /** - * Escape a regular expression string. - * - * @param {string} str - * @return {string} - */ - function escapeString (str) { - return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') - } - - /** - * Escape the capturing group by escaping special characters and meaning. - * - * @param {string} group - * @return {string} - */ - function escapeGroup (group) { - return group.replace(/([=!:$\/()])/g, '\\$1') - } - - /** - * Attach the keys as a property of the regexp. - * - * @param {!RegExp} re - * @param {Array} keys - * @return {!RegExp} - */ - function attachKeys (re, keys) { - re.keys = keys; - return re - } - - /** - * Get the flags for a regexp from the options. - * - * @param {Object} options - * @return {string} - */ - function flags (options) { - return options && options.sensitive ? '' : 'i' - } - - /** - * Pull out keys from a regexp. - * - * @param {!RegExp} path - * @param {!Array} keys - * @return {!RegExp} - */ - function regexpToRegexp (path, keys) { - // Use a negative lookahead to match only capturing groups. - var groups = path.source.match(/\((?!\?)/g); - - if (groups) { - for (var i = 0; i < groups.length; i++) { - keys.push({ - name: i, - prefix: null, - delimiter: null, - optional: false, - repeat: false, - partial: false, - asterisk: false, - pattern: null - }); + // get user 1 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user1', + is_logged_in: false + })]); + mParticle.Identity.login(user1); + + // get user 2 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user2', + is_logged_in: false + })]); + mParticle.Identity.login(user2); + + // get user 3 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user3', + is_logged_in: false + })]); + mParticle.Identity.login(user3); + + // init again using user 1 + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user1', + is_logged_in: false + })]); + mParticle.identifyRequest = user1; + mParticle.init(apiKey, window.mParticle.config); + var users = mParticle.Identity.getUsers(); + //this includes the original, starting user, in addition to the 3 added above + Should(users).have.length(4); + var _iterator = _createForOfIteratorHelper(users), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var i = _step.value; + Should.exist(mParticle.Identity.getUser(i.getMPID())); + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); } - } - - return attachKeys(path, keys) - } - - /** - * Transform an array into a regexp. - * - * @param {!Array} path - * @param {Array} keys - * @param {!Object} options - * @return {!RegExp} - */ - function arrayToRegexp (path, keys, options) { - var parts = []; - - for (var i = 0; i < path.length; i++) { - parts.push(pathToRegexp(path[i], keys, options).source); - } - - var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)); - - return attachKeys(regexp, keys) - } - - /** - * Create a path regexp from string input. - * - * @param {string} path - * @param {!Array} keys - * @param {!Object} options - * @return {!RegExp} - */ - function stringToRegexp (path, keys, options) { - return tokensToRegExp(parse(path, options), keys, options) - } - - /** - * Expose a function for taking tokens and returning a RegExp. - * - * @param {!Array} tokens - * @param {(Array|Object)=} keys - * @param {Object=} options - * @return {!RegExp} - */ - function tokensToRegExp (tokens, keys, options) { - if (!isarray(keys)) { - options = /** @type {!Object} */ (keys || options); - keys = []; - } - - options = options || {}; - - var strict = options.strict; - var end = options.end !== false; - var route = ''; - - // Iterate over the tokens and create our regexp string. - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - - if (typeof token === 'string') { - route += escapeString(token); - } else { - var prefix = escapeString(token.prefix); - var capture = '(?:' + token.pattern + ')'; - - keys.push(token); + Should.not.exist(mParticle.Identity.getUser('gs')); + Should.not.exist(mParticle.Identity.getUser('cu')); + Should.not.exist(mParticle.Identity.getUser('0')); + Should.not.exist(mParticle.Identity.getUser('user4')); + done(); + }); + it('should only update its own cookies, not any other mpids when initializing with a different set of credentials', function (done) { + mParticle._resetForTests(MPConfig); + var user1 = { + userIdentities: { + customerid: 'customerid1', + email: 'email1@test.com' + } + }; + var user2 = { + userIdentities: { + customerid: 'customerid2', + email: 'email2@test.com' + } + }; + var user3 = { + userIdentities: { + customerid: 'customerid3', + email: 'email3@test.com' + } + }; + mParticle.init(apiKey, window.mParticle.config); - if (token.repeat) { - capture += '(?:' + prefix + capture + ')*'; + // get user 1 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user1', + is_logged_in: false + })]); + mParticle.Identity.login(user1); + mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user1'); + + // get user 2 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user2', + is_logged_in: false + })]); + mParticle.Identity.login(user2); + mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user2'); + + // get user 3 into cookies + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'user3', + is_logged_in: false + })]); + mParticle.Identity.login(user3); + mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user3'); + + // init again using user 1 + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'user1', + is_logged_in: false + })]); + mParticle.identifyRequest = user1; + mParticle.init(apiKey, window.mParticle.config); + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.user1.ua.user.should.equal('user1'); + localStorage.user1.ui.should.have.property('1', 'customerid1'); + localStorage.user1.ui.should.have.property('7', 'email1@test.com'); + localStorage.user2.ua.user.should.equal('user2'); + localStorage.user2.ui.should.have.property('1', 'customerid2'); + localStorage.user2.ui.should.have.property('7', 'email2@test.com'); + localStorage.user3.ua.user.should.equal('user3'); + localStorage.user3.ui.should.have.property('1', 'customerid3'); + localStorage.user3.ui.should.have.property('7', 'email3@test.com'); + done(); + }); + it('should create a new modified user identity object, removing any invalid identity types', function (done) { + var previousUIByName = { + customerid: 'customerid1', + email: 'email2@test.com', + twitter: 'test3', + device_application_stamp: 'das-test' + }; + var newUIByName = { + google: 'google4', + twitter: 'twitter5', + invalidKey: 'test' + }; + var combinedUIsByType = mParticle.getInstance()._Identity.IdentityRequest.combineUserIdentities(previousUIByName, newUIByName); + combinedUIsByType.should.have.properties([1, 3, 4, 7]); + combinedUIsByType[1].should.equal('customerid1'); + combinedUIsByType[3].should.equal('twitter5'); + combinedUIsByType[4].should.equal('google4'); + combinedUIsByType[7].should.equal('email2@test.com'); + // if an invalid identity type is added to the + combinedUIsByType.should.not.have.property(false); + Object.keys(combinedUIsByType).length.should.equal(4); + done(); + }); + it('should reject a callback that is not a function', function (done) { + var identityRequest = { + userIdentities: { + customerid: 123 + } + }; + var badCallback = 'string'; + mockServer$a.requests = []; + mParticle.Identity.login(identityRequest, badCallback); + mParticle.Identity.logout(identityRequest, badCallback); + mParticle.Identity.modify(identityRequest, badCallback); + mParticle.Identity.identify(identityRequest, badCallback); + mockServer$a.requests.length.should.equal(0); + done(); + }); + it("should find the related MPID's cookies when given a UI with fewer IDs when passed to login, logout, and identify, and then log events with updated cookies", function (done) { + mParticle._resetForTests(MPConfig); + var user1 = { + userIdentities: { + customerid: 'customerid1' + } + }; + var user1modified = { + userIdentities: { + email: 'email2@test.com' + } + }; + mParticle.config.identifyRequest = user1; + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.modify(user1modified); + mParticle.Identity.getCurrentUser().setUserAttribute('foo1', 'bar1'); + var product1 = mParticle.eCommerce.createProduct('iPhone', '12345', '1000', 2); + mParticle.eCommerce.Cart.add(product1); + mParticle.logEvent('Test Event1'); + var testEvent1Batch = findBatch$4(client._calls, 'Test Event1'); + testEvent1Batch.user_attributes.should.have.property('foo1', 'bar1'); + testEvent1Batch.user_identities.should.have.property('customer_id', 'customerid1'); + testEvent1Batch.user_identities.should.have.property('email', 'email2@test.com'); + var products = getLocalStorageProducts$1(); + products.testMPID.cp[0].should.have.property('Name', 'iPhone', 'sku', 'quantity'); + products.testMPID.cp[0].should.have.property('Sku', '12345'); + products.testMPID.cp[0].should.have.property('Price', 1000); + products.testMPID.cp[0].should.have.property('Quantity', 2); + var user2 = { + userIdentities: { + customerid: 'customerid2' + } + }; + mockServer$a.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.logout(user2); + mParticle.logEvent('Test Event2'); + var testEvent2Batch = findBatch$4(client._calls, 'Test Event2'); + Object.keys(testEvent2Batch.user_attributes).length.should.equal(0); + testEvent2Batch.user_identities.should.have.property('customer_id', 'customerid2'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'testMPID', + is_logged_in: false + })]); + mParticle.Identity.login(user1); + mParticle.logEvent('Test Event3'); + var testEvent3Batch = findBatch$4(client._calls, 'Test Event3'); + testEvent3Batch.user_attributes.should.have.property('foo1', 'bar1'); + Object.keys(testEvent3Batch.user_identities).length.should.equal(2); + testEvent3Batch.user_identities.should.have.property('customer_id', 'customerid1'); + testEvent3Batch.user_identities.should.have.property('email', 'email2@test.com'); + var products2 = getLocalStorageProducts$1(); + products2.testMPID.cp[0].should.have.property('Name', 'iPhone', 'sku', 'quantity'); + products2.testMPID.cp[0].should.have.property('Sku', '12345'); + products2.testMPID.cp[0].should.have.property('Price', 1000); + products2.testMPID.cp[0].should.have.property('Quantity', 2); + done(); + }); + it('Should maintain cookie structure when initializing multiple identity requests, and reinitializing with a previous one will keep the last MPID ', function (done) { + mParticle._resetForTests(MPConfig); + var user1 = { + userIdentities: { + customerid: '1' + } + }; + var user2 = { + userIdentities: { + customerid: '2' + } + }; + var user3 = { + userIdentities: { + customerid: '3' + } + }; + var user4 = { + userIdentities: { + customerid: '4' + } + }; + mParticle.config.identifyRequest = user1; + mParticle.init(apiKey, window.mParticle.config); + var user1UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); + user1UIs.userIdentities.customerid.should.equal('1'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle.Identity.login(user2); + var user2UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); + user2UIs.userIdentities.customerid.should.equal('2'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid3', + is_logged_in: false + })]); + mParticle.Identity.login(user3); + var user3UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); + user3UIs.userIdentities.customerid.should.equal('3'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid4', + is_logged_in: false + })]); + mParticle.Identity.login(user4); + var user4UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); + user4UIs.userIdentities.customerid.should.equal('4'); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + var user5 = mParticle.Identity.getCurrentUser(); + user5.getUserIdentities().userIdentities.customerid.should.equal('4'); + user5.getMPID().should.equal('mpid4'); + var data = mParticle.getInstance()._Persistence.getLocalStorage(); + data.cu.should.equal('mpid4'); + data.testMPID.ui[1].should.equal('1'); + data.mpid2.ui[1].should.equal('2'); + data.mpid3.ui[1].should.equal('3'); + data.mpid4.ui[1].should.equal('4'); + mParticle.identifyRequest = null; + done(); + }); + it('should properly validate identityApiRequest values', function (done) { + var badUserIdentitiesArray = { + userIdentities: { + customerid: [] + } + }; + var badUserIdentitiesObject = { + userIdentities: { + customerid: {} + } + }; + var badUserIdentitiesBoolean = { + userIdentities: { + customerid: false + } + }; + var badUserIdentitiesUndefined = { + userIdentities: { + customerid: undefined + } + }; + var validUserIdentitiesString = { + userIdentities: { + customerid: '123' + } + }; + var validUserIdentitiesNull = { + userIdentities: { + customerid: null + } + }; + var invalidUserIdentitiesCombo = { + userIdentities: { + customerid: '123', + email: undefined + } + }; + var badUserIdentitiesArrayResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(badUserIdentitiesArray); + var badUserIdentitiesObjectResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(badUserIdentitiesObject); + var badUserIdentitiesBooleanResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(badUserIdentitiesBoolean); + var badUserIdentitiesUndefinedResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(badUserIdentitiesUndefined); + var validUserIdentitiesNullResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(validUserIdentitiesNull); + var validUserIdentitiesStringResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(validUserIdentitiesString); + var invalidUserIdentitiesComboResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(invalidUserIdentitiesCombo); + badUserIdentitiesArrayResult.valid.should.equal(false); + badUserIdentitiesObjectResult.valid.should.equal(false); + badUserIdentitiesBooleanResult.valid.should.equal(false); + badUserIdentitiesUndefinedResult.valid.should.equal(false); + validUserIdentitiesNullResult.valid.should.equal(true); + validUserIdentitiesStringResult.valid.should.equal(true); + invalidUserIdentitiesComboResult.valid.should.equal(false); + done(); + }); + it('should not send requests to the server with invalid userIdentity values', function (done) { + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.requests = []; + var result; + var badUserIdentitiesArray = { + userIdentities: { + customerid: [] + } + }; + var badUserIdentitiesObject = { + userIdentities: { + customerid: {} + } + }; + var badUserIdentitiesBoolean = { + userIdentities: { + customerid: false + } + }; + var badUserIdentitiesUndefined = { + userIdentities: { + customerid: undefined } - - if (token.optional) { - if (!token.partial) { - capture = '(?:' + prefix + '(' + capture + '))?'; - } else { - capture = prefix + '(' + capture + ')?'; + }; + var validUserIdentitiesString = { + userIdentities: { + customerid: '123' + } + }; + var validUserIdentitiesNull = { + userIdentities: { + customerid: null + } + }; + var callback = function callback(resp) { + result = resp; + }; + var invalidUserIdentitiesArray = [badUserIdentitiesArray, badUserIdentitiesObject, badUserIdentitiesBoolean, badUserIdentitiesUndefined]; + var validUserIdentities = [validUserIdentitiesString, validUserIdentitiesNull]; + var identityMethods = ['login', 'logout', 'identify', 'modify']; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$a.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$a.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + identityMethods.forEach(function (identityMethod) { + invalidUserIdentitiesArray.forEach(function (badIdentities) { + mParticle.Identity[identityMethod](badIdentities, callback); + result.httpCode.should.equal(-4); + result.body.should.equal(Constants.Messages.ValidationMessages.UserIdentitiesInvalidValues); + result = null; + }); + validUserIdentities.forEach(function (goodIdentities) { + mParticle.Identity[identityMethod](goodIdentities, callback); + result.httpCode.should.equal(200); + result.body.mpid.should.equal(testMPID); + result = null; + }); + }); + done(); + }); + it('should have no user identities when logging out or in with no object', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var user = { + userIdentities: { + customerid: '123' + } + }; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mParticle.Identity.login(user); + var userIdentities1 = mParticle.Identity.getCurrentUser().getUserIdentities(); + mockServer$a.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'mpid1', + is_logged_in: false + })]); + mParticle.Identity.logout(); + var userIdentities2 = mParticle.Identity.getCurrentUser().getUserIdentities(); + userIdentities1.userIdentities.should.have.property('customerid', '123'); + Object.keys(userIdentities2.userIdentities).length.should.equal(0); + done(); + }); + it("saves proper cookies for each user's products, and purchases record cartProducts correctly", function (done) { + mParticle._resetForTests(MPConfig); + var identityAPIRequest1 = { + userIdentities: { + customerid: '123' + } + }; + mParticle.identifyRequest = identityAPIRequest1; + mParticle.init(apiKey, window.mParticle.config); + var product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), + product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 2), + product3 = mParticle.eCommerce.createProduct('Windows', 'SKU3', 3), + product4 = mParticle.eCommerce.createProduct('HTC', 'SKU4', 4); + mParticle.eCommerce.Cart.add([product1, product2]); + var identityAPIRequest2 = { + userIdentities: { + customerid: '234' + } + }; + var products = getLocalStorageProducts$1(); + var cartProducts = products[testMPID].cp; + cartProducts[0].Name.should.equal('iPhone'); + cartProducts[1].Name.should.equal('Android'); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(identityAPIRequest2); + mParticle.eCommerce.Cart.add([product3, product4]); + var products2 = getLocalStorageProducts$1(); + var cartProducts2 = products2['otherMPID'].cp; + cartProducts2[0].Name.should.equal('Windows'); + cartProducts2[1].Name.should.equal('HTC'); + mParticle.eCommerce.logCheckout(1); + var checkoutEvent = findEventFromRequest$5(client._calls, 'checkout'); + checkoutEvent.data.product_action.should.have.property('products', null); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(identityAPIRequest1); + client._calls = []; + mParticle.eCommerce.logCheckout(1); + var checkoutEvent2 = findEventFromRequest$5(client._calls, 'checkout'); + checkoutEvent2.data.product_action.should.have.property('products', null); + done(); + }); + it('should update cookies after modifying identities', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var user = { + userIdentities: { + customerid: 'customerId1' + } + }; + var modifiedUser = { + userIdentities: { + customerid: 'customerId2' + } + }; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mockServer$a.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(user); + mParticle.Identity.modify(modifiedUser); + var cookie = mParticle.getInstance()._Persistence.getLocalStorage(); + cookie.testMPID.ui[1].should.equal('customerId2'); + done(); + }); + it('does not run onUserAlias if it is not a function', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var user1 = { + userIdentities: { + customerid: 'customerId1' + } + }; + var user2 = { + userIdentities: { + customerid: 'customerId2' + }, + onUserAlias: null + }; + var product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), + product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1); + mParticle.eCommerce.Cart.add([product1, product2]); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(user1); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mockServer$a.requests = []; + mParticle.Identity.login(user2); + mockServer$a.requests.length.should.equal(0); + done(); + }); + it('should run onUserAlias if it is a function', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var hasBeenRun = false; + var user1 = { + userIdentities: { + customerid: 'customerId1' + } + }; + var user2 = { + userIdentities: { + customerid: 'customerId2' + }, + onUserAlias: function onUserAlias() { + hasBeenRun = true; + } + }; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(user1); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(user2); + hasBeenRun.should.equal(true); + done(); + }); + it('should setUserAttributes, setUserAttributeLists, removeUserAttributes, and removeUserAttributeLists properly in onUserAlias', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var user1 = { + userIdentities: { + customerid: 'customerId1' + } + }; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(user1); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttribute('age', 27); + var user1Attrs = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + user1Attrs.should.have.property('gender', 'male'); + user1Attrs.should.have.property('age', 27); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + var user1Object, user2Object; + var user2 = { + userIdentities: { + customerid: 'customerId2' + }, + onUserAlias: function onUserAlias(user1, user2) { + var user1Attributes = user1.getAllUserAttributes(); + for (var key in user1Attributes) { + if (key !== 'gender') { + user2.setUserAttribute(key, user1Attributes[key]); + } } - } else { - capture = prefix + '(' + capture + ')'; + user2.setUserAttributeList('list', [1, 2, 3, 4, 5]); + user1.removeUserAttribute('age'); + user1Object = user1; + user2Object = user2; } - - route += capture; + }; + mParticle.Identity.login(user2); + var user1ObjectAttrs = user1Object.getAllUserAttributes(); + user1ObjectAttrs.should.not.have.property('age'); + user1ObjectAttrs.should.have.property('gender', 'male'); + var user2Attrs = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + user2Attrs.should.not.have.property('gender'); + user2Attrs.should.have.property('age', 27); + var user2ObjectAttrs = user2Object.getAllUserAttributes(); + user2ObjectAttrs.should.not.have.property('gender'); + user2ObjectAttrs.should.have.property('age', 27); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID2', + is_logged_in: false + })]); + var user2AttributeListsBeforeRemoving, user3UserAttributeListsBeforeAdding, user2AttributeListsAfterRemoving, user3UserAttributeListsAfterAdding; + var user3 = { + userIdentities: { + customerid: 'customerId3' + }, + onUserAlias: function onUserAlias(user2, user3) { + user2AttributeListsBeforeRemoving = user2.getUserAttributesLists(); + user3UserAttributeListsBeforeAdding = user3.getUserAttributesLists(); + user2.removeAllUserAttributes(); + user3.setUserAttributeList('list', [1, 2, 3, 4, 5]); + user2AttributeListsAfterRemoving = user2.getUserAttributesLists(); + user3UserAttributeListsAfterAdding = user3.getUserAttributesLists(); + } + }; + mParticle.Identity.login(user3); + user2AttributeListsBeforeRemoving.list.length.should.equal(5); + Should(Object.keys(user3UserAttributeListsBeforeAdding).length).not.be.ok(); + Should(Object.keys(user2AttributeListsAfterRemoving).length).not.be.ok(); + user3UserAttributeListsAfterAdding.list.length.should.equal(5); + done(); + }); + it('should return an empty array when no cart products exist', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var user1 = { + userIdentities: { + customerid: 'customerId1' + } + }; + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(user1); + var products = mParticle.Identity.getCurrentUser().getCart().getCartProducts(); + Should(products.length).not.be.ok(); + done(); + }); + it('should make a request when copyUserAttributes is included on the identity request', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var identityAPIRequest1 = { + userIdentities: { + customerid: '123' + }, + copyUserAttributes: true + }; + mockServer$a.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.logout(identityAPIRequest1); + var logoutData = getIdentityEvent$1(mockServer$a.requests, 'logout'); + Should(logoutData).be.ok(); + mParticle.Identity.login(identityAPIRequest1); + var loginData = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(loginData).be.ok(); + mParticle.Identity.modify(identityAPIRequest1); + var modifyData = getIdentityEvent$1(mockServer$a.requests, 'login'); + Should(modifyData).be.ok(); + done(); + }); + it('should trigger the identifyCallback when a successful identify call is sent', function (done) { + // MP.sessionID does not exist yet because we perform an mParticle._resetForTests(MPConfig); + mParticle._resetForTests(MPConfig); + var mpid; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.config.identityCallback = function (resp) { + mpid = resp.body.mpid; + }; + mParticle.init(apiKey, window.mParticle.config); + mpid.should.equal('MPID1'); + done(); + }); + it('should trigger the identityCallback before eventQueue is flushed', function (done) { + mParticle._resetForTests(MPConfig); + var clock = sinon$1.useFakeTimers(); + mockServer$a.respondImmediately = false; + mockServer$a.autoRespond = true; + mockServer$a.autoRespondAfter = 500; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.config.identityCallback = function () { + mParticle.Identity.getCurrentUser().setUserAttribute('foo', 'bar'); + }; + client._calls = []; + mParticle.init(apiKey, window.mParticle.config); + (client._calls.length === 0).should.equal["true"]; + clock.tick(1000); + var sessionStartEventBatch = findBatch$4(client._calls, 'session_start'); + var ASTEventBatch = findBatch$4(client._calls, 'application_state_transition'); + sessionStartEventBatch.user_attributes.should.have.property('foo', 'bar'); + ASTEventBatch.user_attributes.should.have.property('foo', 'bar'); + clock.restore(); + done(); + }); + it('should still trigger the identifyCallback when no identify request is sent because there are already cookies', function (done) { + mParticle._resetForTests(MPConfig); + var les = new Date().getTime(); + var cookies = "{'gs':{'ie':1|'dt':'test_key'|'cgid':'886e874b-862b-4822-a24a-1146cd057101'|'das':'62c91b8d-fef6-44ea-b2cc-b55714b0d827'|'csm':'WyJ0ZXN0TVBJRCJd'|'sid':'2535f9ed-ab19-4a7c-9eeb-ce4e41e0cb06'|'les': " + les + "|'ssd':1518536950916}|'testMPID':{'ui':'eyIxIjoiY3VzdG9tZXJpZDEifQ=='}|'cu':'testMPID'}"; + mParticle.config.useCookieStorage = true; + setCookie(workspaceCookieName, cookies, true); + //does not actually hit the server because identity request is not sent + var result; + mParticle.config.identityCallback = function (resp) { + resp.getUser().setUserAttribute('attr', 'value'); + result = resp; + }; + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + client._calls = []; + mParticle.init(apiKey, window.mParticle.config); + //the only server request is the AST, there is no request to Identity + client._calls.length.should.equal(1); + result.should.have.properties('body', 'httpCode', 'getUser'); + result.httpCode.should.equal(-3); + result.body.should.have.properties('context', 'is_ephemeral', 'matched_identities', 'mpid'); + Should(result.body.context).not.be.ok(); + Should(result.body.is_ephemeral).not.be.ok(); + result.body.matched_identities.should.have.property('customerid', 'customerid1'); + result.body.mpid.should.equal('testMPID'); + result.getUser().getMPID().should.equal('testMPID'); + result.getUser().getAllUserAttributes().should.have.property('attr', 'value'); + done(); + }); + it('identifyCallback response should have a getUser function on the result object', function (done) { + var result; + mParticle._resetForTests(MPConfig); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mParticle.config.identityCallback = function (resp) { + result = resp; + resp.getUser().setUserAttribute('test', 'value'); + }; + mParticle.init(apiKey, window.mParticle.config); + result.should.have.property('getUser'); + mParticle.Identity.getCurrentUser().getAllUserAttributes().should.have.property('test', 'value'); + done(); + }); + it('identityCallback responses should all have a getUser function on their result objects', function (done) { + var result, loginResult, logoutResult, modifyResult; + mParticle._resetForTests(MPConfig); + mParticle.config.identityCallback = function (resp) { + resp.getUser().setUserAttribute('attr', 'value'); + result = resp; + }; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false, + status: 200 + })]); + mParticle.init(apiKey, window.mParticle.config); + var identityRequest = { + userIdentities: { + customerid: 'test123' + } + }; + function loginCallback(result) { + loginResult = result; } - } - - var delimiter = escapeString(options.delimiter || '/'); - var endsWithDelimiter = route.slice(-delimiter.length) === delimiter; - - // In non-strict mode we allow a slash at the end of match. If the path to - // match already ends with a slash, we remove it for consistency. The slash - // is valid at the end of a path match, not in the middle. This is important - // in non-ending mode, where "/test/" shouldn't match "/test//route". - if (!strict) { - route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?'; - } - - if (end) { - route += '$'; - } else { - // In non-ending mode, we need the capturing groups to match as much as - // possible by using a positive lookahead to the end or next path segment. - route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)'; - } - - return attachKeys(new RegExp('^' + route, flags(options)), keys) - } - - /** - * Normalize the given path string, returning a regular expression. - * - * An empty array can be passed in for the keys, which will hold the - * placeholder key descriptions. For example, using `/user/:id`, `keys` will - * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. - * - * @param {(string|RegExp|Array)} path - * @param {(Array|Object)=} keys - * @param {Object=} options - * @return {!RegExp} - */ - function pathToRegexp (path, keys, options) { - if (!isarray(keys)) { - options = /** @type {!Object} */ (keys || options); - keys = []; - } - - options = options || {}; + function logoutCallback(result) { + logoutResult = result; + } + function modifyCallback(result) { + modifyResult = result; + } + mParticle.Identity.login(identityRequest, loginCallback); + mParticle.Identity.logout(identityRequest, logoutCallback); + mParticle.Identity.modify(identityRequest, modifyCallback); + result.should.have.properties('body', 'httpCode', 'getUser'); + result.httpCode.should.equal(200); + result.body.should.have.properties('mpid', 'status'); + result.body.mpid.should.equal('MPID1'); + result.getUser().getMPID().should.equal('MPID1'); + result.getUser().getAllUserAttributes().should.have.property('attr', 'value'); + loginResult.getUser().getMPID().should.equal('MPID1'); + logoutResult.getUser().getMPID().should.equal('MPID1'); + modifyResult.getUser().getMPID().should.equal('MPID1'); + loginResult.getUser().getAllUserAttributes().should.have.property('attr', 'value'); + logoutResult.getUser().getAllUserAttributes().should.have.property('attr', 'value'); + modifyResult.getUser().getAllUserAttributes().should.have.property('attr', 'value'); + done(); + }); + it('should call identify when there is an active session but no current user', function (done) { + // this broken cookie state occurs when an initial identify request is made, fails, and the + // client had no programmatic handling of a failed identify request + mParticle._resetForTests(MPConfig); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + + // invalid customerid of type number, so mParticle.init(apiKey, window.mParticle.config) will fail, but create cookies + // without a current user + mParticle.config.identifyRequest = { + userIdentities: { + customerid: 123 + } + }; + mockServer$a.requests = []; + mParticle.init(apiKey, window.mParticle.config); + var cookies = mParticle.getInstance()._Persistence.getPersistence(); + cookies.should.have.property('gs'); + cookies.should.not.have.property('cu'); + (mParticle.Identity.getCurrentUser() === null).should.equal(true); - if (path instanceof RegExp) { - return regexpToRegexp(path, /** @type {!Array} */ (keys)) - } + // change to a valid customerid + mParticle.config.identifyRequest = { + userIdentities: { + customerid: '123' + } + }; + mockServer$a.requests = []; + mParticle.init(apiKey, window.mParticle.config); + cookies = mParticle.getInstance()._Persistence.getPersistence(); + cookies.should.have.property('gs'); + cookies.should.have.have.property('cu', 'MPID1'); + mParticle.Identity.getCurrentUser().should.not.equal(null); + done(); + }); + it('Users should have firstSeenTime and lastSeenTime', function (done) { + mParticle._resetForTests(MPConfig); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mockServer$a.requests = []; + var clock = sinon$1.useFakeTimers(); + clock.tick(100); + mParticle.init(apiKey, window.mParticle.config); + var currentUser = mParticle.Identity.getCurrentUser(); + currentUser.should.not.equal(null); + Should(currentUser.getFirstSeenTime()).not.equal(null); + Should(currentUser.getLastSeenTime()).not.equal(null); + clock.tick(100); + currentUser.getFirstSeenTime().should.equal(100); + currentUser.getLastSeenTime().should.equal(200); + clock.restore(); + done(); + }); + it('firstSeenTime should stay the same for a user', function (done) { + mParticle._resetForTests(MPConfig); + var clock = sinon$1.useFakeTimers(); + clock.tick(100); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mockServer$a.requests = []; + mParticle.init(apiKey, window.mParticle.config); + var currentUser = mParticle.Identity.getCurrentUser(); + currentUser.should.not.equal(null); + var user1FirstSeen = currentUser.getFirstSeenTime(); + clock.tick(20); + var user1LastSeen = currentUser.getLastSeenTime(); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID2', + is_logged_in: false + })]); + mockServer$a.requests = []; + mParticle.Identity.login(); + currentUser = mParticle.Identity.getCurrentUser(); + currentUser.getMPID().should.equal('MPID2'); + + //new user's firstSeenTime should be greater than or equal to the preceeding user's lastSeenTime + (currentUser.getFirstSeenTime() >= user1LastSeen).should.equal(true); + currentUser.getFirstSeenTime().should.equal(120); + clock.tick(20); + var user1 = mParticle.Identity.getUser('MPID1'); + user1.getFirstSeenTime().should.equal(user1FirstSeen); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + mockServer$a.requests = []; + mParticle.Identity.login(); + currentUser = mParticle.Identity.getCurrentUser(); + currentUser.getMPID().should.equal('MPID1'); + currentUser.getFirstSeenTime().should.equal(user1FirstSeen); + (currentUser.getLastSeenTime() > user1LastSeen).should.equal(true); + clock.restore(); + done(); + }); + it('List returned by Identity.getUsers() should be sorted by lastSeenTime, with nulls last', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + lst: 200 + }, + 2: { + lst: 400 + }, + 3: { + lst: 300 + }, + 4: {}, + 5: { + lst: 700 + }, + cu: '1' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + var users = mParticle.Identity.getUsers(); + users.length.should.equal(5); + users[0].getMPID().should.equal('1'); + users[1].getMPID().should.equal('5'); + users[2].getMPID().should.equal('2'); + users[3].getMPID().should.equal('3'); + users[4].getMPID().should.equal('4'); + Should(users[4].getLastSeenTime()).equal(null); + done(); + }); + it('does not error when simultaneous identity calls are out', function (done) { + var errorMessages = []; + mParticle._resetForTests(MPConfig); + mParticle.config.logger = { + error: function error(msg) { + errorMessages.push(msg); + } + }; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.identityCallInFlight = true; + mParticle.setLogLevel('warning'); + mParticle.Identity.login({ + userIdentities: { + customerid: 'test' + } + }); + errorMessages.length.should.equal(0); + done(); + }); + it('Startup identity callback should include getPreviousUser()', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'test', + les: new Date().getTime() + }, + testMPID: { + lst: 100 + }, + testMPID2: { + lst: 200 + }, + cu: 'testMPID' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + var identityResult; + function identityCallback(result) { + identityResult = result; + } + mParticle.config.identityCallback = identityCallback; + mParticle.init(apiKey, window.mParticle.config); + identityResult.getUser().getMPID().should.equal('testMPID'); + Should(identityResult.getPreviousUser()).not.equal(null); + Should(identityResult.getPreviousUser().getMPID()).equal('testMPID2'); + done(); + }); + it('Identity callback should include getPreviousUser()', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + testMPID: { + lst: 200 + }, + testMPID2: { + lst: 100 + }, + cu: 'testMPID' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + var loginResult; + function identityCallback(result) { + loginResult = result; + } + mParticle.Identity.login({}, identityCallback); + mParticle.Identity.getCurrentUser().getMPID().should.equal('testMPID'); + loginResult.getUser().getMPID().should.equal('testMPID'); + Should(loginResult.getPreviousUser()).not.equal(null); + loginResult.getPreviousUser().getMPID().should.equal('testMPID2'); + done(); + }); + it('should return the correct user for Previous User', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + lst: 200 + }, + 2: { + lst: 400 + }, + 3: { + lst: 300 + }, + 4: { + lst: 600 + }, + 5: { + lst: 100 + }, + cu: '1' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: '1', + is_logged_in: false + })]); + var identityResult; + mParticle.Identity.identify({}, function (result) { + identityResult = result; + }); + identityResult.getUser().getMPID().should.equal('1'); + identityResult.getPreviousUser().getMPID().should.equal('4'); + done(); + }); + it('Alias request should be received when API is called validly', function (done) { + mockServer$a.requests = []; + var aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4 + }; + mockServer$a.respondWith(urls.alias, [200, {}, JSON.stringify({})]); + mParticle.Identity.aliasUsers(aliasRequest); + mockServer$a.requests.length.should.equal(1); + var request = mockServer$a.requests[0]; + request.url.should.equal(urls.alias); + var requestBody = JSON.parse(request.requestBody); + Should(requestBody['request_id']).not.equal(null); + Should(requestBody['request_type']).equal('alias'); + Should(requestBody['environment']).equal('production'); + Should(requestBody['api_key']).equal(mParticle.getInstance()._Store.devToken); + var dataBody = requestBody['data']; + Should(dataBody).not.equal(null); + Should(dataBody['destination_mpid']).equal(1); + Should(dataBody['source_mpid']).equal(2); + Should(dataBody['start_unixtime_ms']).equal(3); + Should(dataBody['end_unixtime_ms']).equal(4); + done(); + }); + it('Alias request should include scope if specified', function (done) { + mockServer$a.requests = []; + var aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4, + scope: 'mpid' + }; + mockServer$a.respondWith(urls.alias, [200, {}, JSON.stringify({})]); + mParticle.Identity.aliasUsers(aliasRequest); + mockServer$a.requests.length.should.equal(1); + var request = mockServer$a.requests[0]; + request.url.should.equal(urls.alias); + var requestBody = JSON.parse(request.requestBody); + var dataBody = requestBody['data']; + Should(dataBody['scope']).equal('mpid'); + done(); + }); + it('Should reject malformed Alias Requests', function (done) { + mParticle.config.logLevel = 'verbose'; + var warnMessage = null; + mParticle.config.logger = { + warning: function warning(msg) { + warnMessage = msg; + } + }; + mParticle.init(apiKey, window.mParticle.config); + var callbackResult; - if (isarray(path)) { - return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options) - } + //missing sourceMpid + var aliasRequest = { + destinationMpid: 1, + startTime: 3, + endTime: 4 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue); + Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingMpid); + Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingMpid); + callbackResult = null; + warnMessage = null; + + //missing destinationMpid + aliasRequest = { + sourceMpid: 2, + startTime: 3, + endTime: 4 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue); + Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingMpid); + Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingMpid); + callbackResult = null; + warnMessage = null; + + //same destinationMpid & sourceMpid + aliasRequest = { + destinationMpid: 1, + sourceMpid: 1, + startTime: 3, + endTime: 4 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue); + Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasNonUniqueMpid); + Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasNonUniqueMpid); + callbackResult = null; + warnMessage = null; + + //endTime before startTime + aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 4, + endTime: 3 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue); + Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasStartBeforeEndTime); + Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasStartBeforeEndTime); + callbackResult = null; + warnMessage = null; + + //missing endTime and startTime + aliasRequest = { + destinationMpid: 1, + sourceMpid: 2 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(HTTPCodes$1.validationIssue); + Should(callbackResult.message).equal(Constants.Messages.ValidationMessages.AliasMissingTime); + Should(warnMessage).equal(Constants.Messages.ValidationMessages.AliasMissingTime); + callbackResult = null; + warnMessage = null; + + //sanity test, make sure properly formatted requests are accepted + aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4 + }; + mockServer$a.respondWith(urls.alias, [200, {}, JSON.stringify({})]); + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(200); + Should(callbackResult.message).equal(undefined); + Should(warnMessage).equal(null); + callbackResult = null; + done(); + }); + it('Should parse error info from Alias Requests', function (done) { + mParticle.init(apiKey, window.mParticle.config); + var errorMessage = 'this is a sample error message'; + var callbackResult; + mockServer$a.respondWith(urls.alias, [400, {}, JSON.stringify({ + message: errorMessage, + code: 'ignored code' + })]); + var aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + callbackResult.httpCode.should.equal(400); + callbackResult.message.should.equal(errorMessage); + done(); + }); + it('Should properly create AliasRequest', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + fst: 200, + lst: 400 + }, + cu: '2' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + var clock = sinon$1.useFakeTimers(); + clock.tick(1000); + var destinationUser = mParticle.Identity.getCurrentUser(); + var sourceUser = mParticle.Identity.getUser('1'); + var aliasRequest = mParticle.Identity.createAliasRequest(sourceUser, destinationUser); + Should(aliasRequest.sourceMpid).equal('1'); + Should(aliasRequest.destinationMpid).equal('2'); + Should(aliasRequest.startTime).equal(200); + Should(aliasRequest.endTime).equal(400); + clock.restore(); + done(); + }); + it('Should fill in missing fst and lst in createAliasRequest', function (done) { + mParticle._resetForTests(MPConfig); + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + fst: 200, + lst: 400 + }, + 2: {}, + cu: '3' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + var clock = sinon$1.useFakeTimers(); + clock.tick(1000); + var destinationUser = mParticle.Identity.getCurrentUser(); + var sourceUser = mParticle.Identity.getUser('2'); + var aliasRequest = mParticle.Identity.createAliasRequest(sourceUser, destinationUser); + Should(aliasRequest.sourceMpid).equal('2'); + Should(aliasRequest.destinationMpid).equal('3'); + //should grab the earliest fst out of any user if user does not have fst + Should(aliasRequest.startTime).equal(200); + //should grab currentTime if user does not have lst + Should(aliasRequest.endTime).equal(1000); + clock.restore(); + done(); + }); + it('Should fix startTime when default is outside max window create AliasRequest', function (done) { + mParticle._resetForTests(MPConfig); + var millisPerDay = 24 * 60 * 60 * 1000; + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + fst: 200 + }, + cu: '2' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; - return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options) - } + //set max Alias startTime age to 1 day + mParticle.config.aliasMaxWindow = 1; + mParticle.init(apiKey, window.mParticle.config); + var clock = sinon$1.useFakeTimers(); + clock.tick(millisPerDay * 2); + var destinationUser = mParticle.Identity.getCurrentUser(); + var sourceUser = mParticle.Identity.getUser('1'); + var aliasRequest = mParticle.Identity.createAliasRequest(sourceUser, destinationUser); + Should(aliasRequest.sourceMpid).equal('1'); + Should(aliasRequest.destinationMpid).equal('2'); + var oldestAllowedStartTime = new Date().getTime() - mParticle.getInstance()._Store.SDKConfig.aliasMaxWindow * millisPerDay; + Should(aliasRequest.startTime).equal(oldestAllowedStartTime); + Should(aliasRequest.endTime).equal(new Date().getTime()); + clock.restore(); + done(); + }); + it('should warn if legal aliasRequest cannot be created with MParticleUser', function (done) { + var millisPerDay = 24 * 60 * 60 * 1000; + mParticle.config.logLevel = 'verbose'; + var warnMessage = null; + mParticle.config.logger = { + warning: function warning(msg) { + warnMessage = msg; + } + }; + var cookies = JSON.stringify({ + gs: { + sid: 'fst Test', + les: new Date().getTime() + }, + 1: { + fst: 200, + lst: 300 + }, + cu: '2' + }); + setCookie(workspaceCookieName, cookies); + mParticle.useCookieStorage = true; + //set max Alias startTime age to 1 day + mParticle.config.aliasMaxWindow = 1; + mParticle.init(apiKey, window.mParticle.config); + var clock = sinon$1.useFakeTimers(); + clock.tick(millisPerDay * 2); + var destinationUser = mParticle.Identity.getCurrentUser(); + var sourceUser = mParticle.Identity.getUser('1'); + var aliasRequest = mParticle.Identity.createAliasRequest(sourceUser, destinationUser); + Should(aliasRequest.sourceMpid).equal('1'); + Should(aliasRequest.destinationMpid).equal('2'); + var oldestAllowedStartTime = new Date().getTime() - mParticle.getInstance()._Store.SDKConfig.aliasMaxWindow * millisPerDay; + Should(aliasRequest.startTime).equal(oldestAllowedStartTime); + Should(aliasRequest.endTime).equal(300); + Should(warnMessage).equal('Source User has not been seen in the last ' + mParticle.getInstance()._Store.SDKConfig.maxAliasWindow + ' days, Alias Request will likely fail'); + clock.restore(); + done(); + }); + it("Alias request should have environment 'development' when isDevelopmentMode is true", function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.isDevelopmentMode = true; + mParticle.init(apiKey, window.mParticle.config); + mockServer$a.requests = []; + var aliasRequest = { + destinationMpid: 1, + sourceMpid: 2, + startTime: 3, + endTime: 4 + }; + mParticle.Identity.aliasUsers(aliasRequest); + mockServer$a.requests.length.should.equal(1); + var request = mockServer$a.requests[0]; + var requestBody = JSON.parse(request.requestBody); + Should(requestBody['environment']).equal('development'); + done(); + }); + it('should set isFirtRun to false after an app is initialized', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.isFirstRun.should.equal(false); + mockServer$a.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID1', + is_logged_in: false + })]); + mParticle.Identity.login({ + userIdentities: { + customerid: 'abc' + } + }); + var ls = mParticle.getInstance()._Persistence.getLocalStorage(); + ls['testMPID'].lst.should.not.equal(null); + done(); + }); + it('should send back an httpCode of -1 when there is a no coverage (http code returns 0)', function (done) { + mParticle._resetForTests(MPConfig); + var result; + function identityCallback(response) { + result = response; + } + mockServer$a.respondWith(urls.identify, [0, {}, JSON.stringify({ + body: null + })]); + mParticle.config.identityCallback = identityCallback; + mParticle.init(apiKey, window.mParticle.config); + result.httpCode.should.equal(-1); + done(); + }); + it('should use the custom device id in known_identities when passed via setDeviceId', function (done) { + mParticle._resetForTests(MPConfig); + mockServer$a.requests = []; + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + body: null + })]); + mParticle.init(apiKey, window.mParticle.config); + var data = getIdentityEvent$1(mockServer$a.requests, 'identify'); + data.known_identities.device_application_stamp.length.should.equal(36); + mParticle.setDeviceId('foo-guid'); + mParticle.Identity.login({ + userIdentities: { + customerid: 'test' + } + }); + var data2 = getIdentityEvent$1(mockServer$a.requests, 'login'); + data2.known_identities.device_application_stamp.should.equal('foo-guid'); + done(); + }); + it('should use the custom device id in known_identities when set via mParticle.config', function (done) { + mParticle._resetForTests(MPConfig); + mockServer$a.respondWith(urls.identify, [200, {}, JSON.stringify({ + body: null + })]); + mockServer$a.requests = []; + window.mParticle.config.deviceId = 'foo-guid'; + mParticle.init(apiKey, window.mParticle.config); + var data = getIdentityEvent$1(mockServer$a.requests, 'identify'); + data.known_identities.device_application_stamp.should.equal('foo-guid'); + done(); + }); + describe('Deprecate Cart', function () { + afterEach(function () { + sinon$1.restore(); + }); + it('should deprecate the user\'s cart', function () { + mParticle.init(apiKey, window.mParticle.config); + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.getInstance().Identity.getCurrentUser().getCart(); + mParticle.Identity.getCurrentUser().getCart(); + bond.called.should.eql(true); + bond.callCount.should.equal(2); + bond.getCalls()[0].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart() will be removed in future releases'); + }); + it('should deprecate add', function () { + mParticle.init(apiKey, window.mParticle.config); + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.getInstance().Identity.getCurrentUser().getCart().add(product); + mParticle.Identity.getCurrentUser().getCart().add(product); + bond.called.should.eql(true); + // deprecates on both .getCart, then .add + bond.callCount.should.equal(4); + bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().add() will be removed in future releases'); + }); + it('should deprecate remove', function () { + mParticle.init(apiKey, window.mParticle.config); + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.getInstance().Identity.getCurrentUser().getCart().remove(product, true); + mParticle.Identity.getCurrentUser().getCart().remove(product, true); + bond.called.should.eql(true); + // deprecates on both .getCart, then .add + bond.callCount.should.equal(4); + bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().remove() will be removed in future releases'); + }); + it('should deprecate clear', function () { + mParticle.init(apiKey, window.mParticle.config); + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.getInstance().Identity.getCurrentUser().getCart().clear(); + mParticle.Identity.getCurrentUser().getCart().clear(); + bond.called.should.eql(true); + // deprecates on both .getCart, then .add + bond.callCount.should.equal(4); + bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().clear() will be removed in future releases'); + }); + it('should deprecate getCartProducts', function () { + mParticle.init(apiKey, window.mParticle.config); + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.getInstance().Identity.getCurrentUser().getCart().getCartProducts(); + mParticle.Identity.getCurrentUser().getCart().getCartProducts(); + bond.called.should.eql(true); + // deprecates on both .getCart, then .add + bond.callCount.should.equal(4); + bond.getCalls()[1].args[0].should.eql('Deprecated function Identity.getCurrentUser().getCart().getCartProducts() will be removed in future releases'); + }); + }); + }); - },{"isarray":149}],149:[function(require,module,exports){ - module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; - }; + var getIdentityEvent = TestsCore.getIdentityEvent, + findEventFromRequest$4 = TestsCore.findEventFromRequest, + findBatch$3 = TestsCore.findBatch; + var mockServer$9; + describe('event logging', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + client.post(urls.events, 200); + delete mParticle._instances['default_instance']; + mockServer$9 = sinon$1.createFakeServer(); + mockServer$9.respondImmediately = true; + mockServer$9.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$9.restore(); + client.restore(); + mParticle._resetForTests(MPConfig); + }); + it('should log an event', function (done) { + window.mParticle.logEvent('Test Event', mParticle.EventType.Navigation, { + mykey: 'myvalue' + }); + var testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + var testEventBatch = findBatch$3(client._calls, 'Test Event'); + testEvent.data.should.have.property('event_name', 'Test Event'); + testEvent.data.should.have.property('custom_event_type', 'navigation'); + testEvent.data.should.have.property('custom_attributes'); + testEvent.data.custom_attributes.should.have.property('mykey', 'myvalue'); + testEventBatch.should.have.property('mpid', testMPID); + done(); + }); + it('should log an event with new device id when set on setDeviceId', function (done) { + window.mParticle.logEvent('Test Event', mParticle.EventType.Navigation, { + mykey: 'myvalue' + }); + var testEventBatch = findBatch$3(client._calls, 'Test Event'); + // this das should be the SDK auto generated one, which is 36 characters long + testEventBatch.mp_deviceid.should.have.length(36); + mParticle.setDeviceId('foo-guid'); + window.mParticle.logEvent('Test Event2'); + var testEvent2Batch = findBatch$3(client._calls, 'Test Event2'); + + // das should be the one passed to setDeviceId() + testEvent2Batch.should.have.property('mp_deviceid', 'foo-guid'); + done(); + }); + it('should log an event with new device id when set via mParticle.config', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.deviceId = 'foo-guid'; + mParticle.init(apiKey, window.mParticle.config); + window.mParticle.logEvent('Test Event'); + var testEventBatch = findBatch$3(client._calls, 'Test Event'); - },{}],150:[function(require,module,exports){ - module.exports = { - stdout: false, - stderr: false - }; + // this das should be the SDK auto generated one + testEventBatch.should.have.property('mp_deviceid', 'foo-guid'); + done(); + }); + it('should allow an event to bypass server upload', function (done) { + window.mParticle.logEvent('Test Standard Upload', mParticle.EventType.Navigation, { + mykey: 'myvalue' + }, {}, { + shouldUploadEvent: true + }); + window.mParticle.logEvent('Test Upload Bypass', mParticle.EventType.Navigation, { + mykey: 'myvalue' + }, {}, { + shouldUploadEvent: false + }); + var uploadEvent = findEventFromRequest$4(client._calls, 'Test Standard Upload'); + var uploadEventBatch = findBatch$3(client._calls, 'Test Standard Upload'); + var bypassedEvent = findEventFromRequest$4(client._calls, 'Test Upload Bypass'); + uploadEvent.should.be.ok(); + uploadEvent.data.should.have.property('event_name', 'Test Standard Upload'); + uploadEvent.data.should.have.property('custom_event_type', 'navigation'); + uploadEvent.data.should.have.property('custom_attributes'); + uploadEvent.data.custom_attributes.should.have.property('mykey', 'myvalue'); + uploadEventBatch.should.have.property('mpid', testMPID); + Should(bypassedEvent).not.be.ok(); + done(); + }); + it('should allow an event to bypass server upload via logBaseEvent', function (done) { + window.mParticle.logBaseEvent({ + name: 'Test Standard Upload', + messageType: MessageType$2.PageEvent, + eventType: mParticle.EventType.Navigation, + data: { + mykey: 'myvalue' + }, + customFlags: {} + }, { + shouldUploadEvent: true + }); + window.mParticle.logBaseEvent({ + name: 'Test Upload Bypass', + messageType: MessageType$2.PageEvent, + eventType: mParticle.EventType.Navigation, + data: { + mykey: 'myvalue' + }, + customFlags: {} + }, { + shouldUploadEvent: false + }); + var uploadEvent = findEventFromRequest$4(client._calls, 'Test Standard Upload'); + var uploadEventBatch = findBatch$3(client._calls, 'Test Standard Upload'); + var bypassedEvent = findEventFromRequest$4(client._calls, 'Test Upload Bypass'); + uploadEvent.should.be.ok(); + uploadEvent.data.should.have.property('event_name', 'Test Standard Upload'); + uploadEvent.data.should.have.property('custom_event_type', 'navigation'); + uploadEvent.data.should.have.property('custom_attributes'); + uploadEvent.data.custom_attributes.should.have.property('mykey', 'myvalue'); + uploadEventBatch.should.have.property('mpid', testMPID); + Should(bypassedEvent).not.be.ok(); + done(); + }); + it('should log an error', function (done) { + mParticle.logError('my error'); + var errorEvent = findEventFromRequest$4(client._calls, 'my error'); + Should(errorEvent).be.ok(); + errorEvent.data.should.have.property('message', 'Error'); + errorEvent.data.should.have.property('custom_attributes'); + errorEvent.data.custom_attributes.should.have.property('m', 'my error'); + done(); + }); + it('should log an error with name, message, stack', function (done) { + var error = new Error('my error'); + error.stack = 'my stacktrace'; + mParticle.logError(error); + var errorEvent = findEventFromRequest$4(client._calls, 'my error'); + Should(errorEvent).be.ok(); + errorEvent.data.should.have.property('message', 'Error'); + errorEvent.data.should.have.property('custom_attributes'); + errorEvent.data.custom_attributes.should.have.property('m', 'my error'); + errorEvent.data.custom_attributes.should.have.property('s', 'Error'); + errorEvent.data.custom_attributes.should.have.property('t', 'my stacktrace'); + done(); + }); + it('should log an error with custom attrs', function (done) { + var error = new Error('my error'); + error.stack = 'my stacktrace'; + mParticle.logError(error, { + location: 'my path', + myData: 'my data' + }); + var errorEvent = findEventFromRequest$4(client._calls, 'my error'); + Should(errorEvent).be.ok(); + errorEvent.data.should.have.property('message', 'Error'); + errorEvent.data.should.have.property('custom_attributes'); + errorEvent.data.custom_attributes.should.have.property('location', 'my path'); + errorEvent.data.custom_attributes.should.have.property('myData', 'my data'); + done(); + }); + it('should sanitize error custom attrs', function (done) { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.logError('my error', { + invalid: ['my invalid attr'], + valid: 10 + }); + var errorEvent = findEventFromRequest$4(client._calls, 'my error'); + Should(errorEvent).be.ok(); + errorEvent.data.should.have.property('message', 'Error'); + errorEvent.data.should.have.property('custom_attributes'); + errorEvent.data.custom_attributes.should.have.property('valid', 10); + errorEvent.data.custom_attributes.should.not.have.property('invalid'); + bond.called.should.eql(true); + bond.callCount.should.equal(1); + bond.getCalls()[0].args[0].should.eql('For \'my error\', the corresponding attribute value of \'invalid\' must be a string, number, boolean, or null.'); + done(); + }); + it('should log an AST with firstRun = true when first visiting a page, and firstRun = false when reloading the page', function (done) { + var astEvent = findEventFromRequest$4(client._calls, 'application_state_transition'); + astEvent.data.should.have.property('application_transition_type', 'application_initialized'); + astEvent.data.should.have.property('is_first_run', true); + astEvent.data.should.have.property('is_upgrade', false); + if (document.referrer && document.referrer.length > 0) { + astEvent.data.should.have.property('launch_referral', window.location.href); + } + client._calls = []; + mParticle.init(apiKey, window.mParticle.config); + var astEvent2 = findEventFromRequest$4(client._calls, 'application_state_transition'); + astEvent2.data.should.have.property('is_first_run', false); + done(); + }); + it('should log an AST on init with firstRun = false when cookies already exist', function (done) { + // cookies currently exist, mParticle.init called from beforeEach + client._calls = []; + // log second AST + mParticle.init(apiKey, window.mParticle.config); + var astEvent = findEventFromRequest$4(client._calls, 'application_state_transition'); + astEvent.data.should.have.property('is_first_run', false); + done(); + }); + it('should log a page view', function (done) { + mParticle.logPageView(); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).be.ok(); + pageViewEvent.data.should.have.property('custom_attributes'); + pageViewEvent.data.custom_attributes.should.have.property('hostname', window.location.hostname); + pageViewEvent.data.custom_attributes.should.have.property('title', window.document.title); + done(); + }); + it('should log custom page view', function (done) { + mParticle.logPageView('My Page View', { + testattr: 1 + }, { + 'MyCustom.Flag': 'Test' + }); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).be.ok(); + pageViewEvent.data.should.have.property('custom_attributes'); + pageViewEvent.data.should.have.property('screen_name', 'My Page View'); + pageViewEvent.data.custom_attributes.should.have.property('testattr', 1); + pageViewEvent.data.custom_flags.should.have.property('MyCustom.Flag', 'Test'); + done(); + }); + it('should pass custom flags in page views', function (done) { + mParticle.logPageView('test', null, { + 'MyCustom.Flag': 'Test' + }); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).be.ok(); + pageViewEvent.data.should.have.property('custom_flags'); + pageViewEvent.data.custom_flags.should.have.property('MyCustom.Flag', 'Test'); + done(); + }); + it('should allow a page view to bypass server upload', function (done) { + mParticle.logPageView('test bypass', null, null, { + shouldUploadEvent: false + }); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).not.be.ok(); + done(); + }); + it('should not log a PageView event if there are invalid attrs', function (done) { + mParticle.logPageView('test1', 'invalid', null); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).not.be.ok(); + done(); + }); + it('should not log an event that has an invalid customFlags', function (done) { + mParticle.logPageView('test', null, 'invalid'); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + Should(pageViewEvent).not.be.ok(); + done(); + }); + it('should log event with name PageView when an invalid event name is passed', function (done) { + client._calls = []; + mParticle.logPageView(null); + client._calls.length.should.equal(1); + var pageViewEvent = findEventFromRequest$4(client._calls, 'screen_view'); + pageViewEvent.data.screen_name.should.equal('PageView'); + client._calls = []; + mParticle.logPageView({ + test: 'test' + }); + client._calls.length.should.equal(1); + var pageViewEvent2 = findEventFromRequest$4(client._calls, 'screen_view'); + pageViewEvent2.data.screen_name.should.equal('PageView'); + client._calls = []; + mParticle.logPageView([1, 2, 3]); + client._calls.length.should.equal(1); + var pageViewEvent3 = findEventFromRequest$4(client._calls, 'screen_view'); + pageViewEvent3.data.screen_name.should.equal('PageView'); + done(); + }); + it('should log opt out', function (done) { + mParticle.setOptOut(true); + var optOutEvent = findEventFromRequest$4(client._calls, 'opt_out'); + optOutEvent.event_type.should.equal('opt_out'); + optOutEvent.data.should.have.property('is_opted_out', true); + done(); + }); + it('log event requires name', function (done) { + client._calls = []; + mParticle.logEvent(); + client._calls.should.have.lengthOf(0); + done(); + }); + it('log event requires valid event type', function (done) { + client._calls = []; + mParticle.logEvent('test', 100); + client._calls.should.have.lengthOf(0); + done(); + }); + it('event attributes must be object', function (done) { + mParticle.logEvent('Test Event', null, 1); + var testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + testEvent.data.should.have.property('custom_attributes', null); + done(); + }); + it('opting out should prevent events being sent', function (done) { + mParticle.setOptOut(true); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(0); + done(); + }); + it('after logging optout, and reloading, events still should not be sent until opt out is enabled when using local storage', function (done) { + mParticle.setOptOut(true); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(0); + mParticle.setOptOut(false); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(1); + mParticle.setOptOut(true); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(0); + done(); + }); + it('after logging optout, and reloading, events still should not be sent until opt out is enabled when using cookie storage', function (done) { + mParticle.config.useCookieStorage = true; + mParticle.init(apiKey, window.mParticle.config); + mParticle.setOptOut(true); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(0); + mParticle.setOptOut(false); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(1); + mParticle.setOptOut(true); + mParticle.init(apiKey, window.mParticle.config); + client._calls = []; + mParticle.logEvent('test'); + client._calls.should.have.lengthOf(0); + done(); + }); + it('should log logout event', function (done) { + mockServer$9.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.logout(); + var data = getIdentityEvent(mockServer$9.requests, 'logout'); + data.should.have.properties('client_sdk', 'environment', 'previous_mpid', 'request_id', 'request_timestamp_ms', 'context'); + done(); + }); + it('should log login event', function (done) { + mockServer$9.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.login(); + var data = getIdentityEvent(mockServer$9.requests, 'login'); + data.should.have.properties('client_sdk', 'environment', 'previous_mpid', 'request_id', 'request_timestamp_ms', 'context'); + done(); + }); + it('should log modify event', function (done) { + mockServer$9.respondWith(urls.modify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.Identity.modify(); + var data = getIdentityEvent(mockServer$9.requests, 'modify'); + data.should.have.properties('client_sdk', 'environment', 'identity_changes', 'request_id', 'request_timestamp_ms', 'context'); + done(); + }); + it('should send das with each event logged', function (done) { + window.mParticle.logEvent('Test Event'); + var testEventBatch = findBatch$3(client._calls, 'Test Event'); + testEventBatch.should.have.property('mp_deviceid'); + testEventBatch.mp_deviceid.length.should.equal(36); + done(); + }); + it('should send consent state with each event logged', function (done) { + var consentState = mParticle.Consent.createConsentState(); + consentState.addGDPRConsentState('foo purpose', mParticle.Consent.createGDPRConsent(true, 10, 'foo document', 'foo location', 'foo hardwareId')); + mParticle.Identity.getCurrentUser().setConsentState(consentState); + window.mParticle.logEvent('Test Event'); + var testEvent = findBatch$3(client._calls, 'Test Event'); + testEvent.should.have.property('consent_state'); + testEvent.consent_state.should.have.property('gdpr'); + testEvent.consent_state.gdpr.should.have.property('foo purpose'); + var purpose = testEvent.consent_state.gdpr['foo purpose']; + purpose.should.have.property('timestamp_unixtime_ms', 10); + purpose.should.have.property('document', 'foo document'); + purpose.should.have.property('location', 'foo location'); + purpose.should.have.property('hardware_id', 'foo hardwareId'); + mParticle.Identity.getCurrentUser().setConsentState(null); + window.mParticle.logEvent('Test Event2'); + var testEvent2 = findBatch$3(client._calls, 'Test Event2'); + testEvent2.should.have.property('consent_state', null); + done(); + }); + it('should log integration attributes with each event', function (done) { + mParticle.setIntegrationAttribute(128, { + MCID: 'abcdefg' + }); + mParticle.logEvent('Test Event'); + var testEvent = findBatch$3(client._calls, 'Test Event'); + testEvent.should.have.property('integration_attributes'); + testEvent.integration_attributes.should.have.property('128'); + testEvent.integration_attributes['128'].should.have.property('MCID', 'abcdefg'); + done(); + }); + it('should run the callback once when tracking succeeds', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle.init(apiKey, window.mParticle.config); + var successCallbackCalled = false; + var numberTimesCalled = 0; + mParticle.startTrackingLocation(function () { + numberTimesCalled += 1; + successCallbackCalled = true; + mParticle.logEvent('Test Event'); + }); - },{}],151:[function(require,module,exports){ - (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.typeDetect = factory()); - }(this, (function () { - /* ! - * type-detect - * Copyright(c) 2013 jake luer - * MIT Licensed - */ - var promiseExists = typeof Promise === 'function'; + // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000); + successCallbackCalled.should.equal(true); + var testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + testEvent.data.location.latitude.should.equal(52.5168); + testEvent.data.location.longitude.should.equal(13.3889); + client._calls = []; + + //this will hit the watch position again, but won't call the callback again + clock.tick(1000); + numberTimesCalled.should.equal(1); + testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + Should(testEvent).not.be.ok(); + clock.restore(); + done(); + }); + it('should run the callback once when tracking fails', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle.init(apiKey, window.mParticle.config); + var successCallbackCalled = false; + var numberTimesCalled = 0; + navigator.geolocation.shouldFail = true; + mParticle.startTrackingLocation(function () { + numberTimesCalled += 1; + successCallbackCalled = true; + mParticle.logEvent('Test Event'); + }); - /* eslint-disable no-undef */ - var globalObject = typeof self === 'object' ? self : global; // eslint-disable-line id-blacklist + // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000); + successCallbackCalled.should.equal(true); + var testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + testEvent.data.should.have.property('location', null); + client._calls = []; + + //this will hit the watch position again, but won't call the callback again + clock.tick(1000); + numberTimesCalled.should.equal(1); + testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + Should(testEvent).not.be.ok(); + navigator.geolocation.shouldFail = false; + clock.restore(); + done(); + }); + it('should pass the found or existing position to the callback in startTrackingLocation', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle.init(apiKey, window.mParticle.config); + var currentPosition; + function callback(position) { + currentPosition = position; + } + mParticle.startTrackingLocation(callback); + + // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000); + var latitudeResult = 52.5168; + var longitudeResult = 13.3889; + currentPosition.coords.latitude.should.equal(latitudeResult); + currentPosition.coords.longitude.should.equal(longitudeResult); + clock.restore(); + done(); + }); + it('should run the callback if tracking already exists', function (done) { + var clock = sinon$1.useFakeTimers(); + mParticle.init(apiKey, window.mParticle.config); + mParticle.startTrackingLocation(); + var successCallbackCalled = false; + function callback() { + successCallbackCalled = true; + mParticle.logEvent('Test Event'); + } + mParticle.startTrackingLocation(callback); + + // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) + clock.tick(1000); + successCallbackCalled.should.equal(true); + var testEvent = findEventFromRequest$4(client._calls, 'Test Event'); + var latitudeResult = 52.5168; + var longitudeResult = 13.3889; + testEvent.data.location.latitude.should.equal(latitudeResult); + testEvent.data.location.longitude.should.equal(longitudeResult); + clock.restore(); + done(); + }); + it('should log appName in the payload on v3 endpoint when set on config prior to init', function (done) { + mParticle.config.appName = 'a name'; + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.application_info.should.have.property('application_name', 'a name'); + delete window.mParticle.config.flags; + done(); + }); + it('should log AST first_run as true on new page loads, and false for when a page has previously been loaded', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, mParticle.config); + var batch = JSON.parse(client.lastOptions().body); + batch.events[0].data.should.have.property('is_first_run', true); + mParticle.init(apiKey, mParticle.config); + var batch2 = JSON.parse(client.lastOptions().body); + batch2.events[0].data.should.have.property('is_first_run', false); + delete window.mParticle.config.flags; + done(); + }); + it('should log AST with launch_referral with a url', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, mParticle.config); + var batch = JSON.parse(client.lastOptions().body); + batch.events[0].data.should.have.property('launch_referral'); + batch.events[0].data.launch_referral.should.startWith('http://localhost'); + delete window.mParticle.config.flags; + done(); + }); + it('should log appName in the payload on v3 endpoint when set on config prior to init', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, mParticle.config); + mParticle.setAppName('another name'); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.application_info.should.have.property('application_name', 'another name'); + delete window.mParticle.config.flags; + done(); + }); + it('should log a batch to v3 with data planning in the payload', function (done) { + mParticle.config.logLevel = 'verbose'; + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.dataPlan = { + planId: 'plan-slug', + planVersion: 10 + }; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.have.property('context'); + batch.context.should.have.property('data_plan'); + batch.context.data_plan.should.have.property('plan_version', 10); + batch.context.data_plan.should.have.property('plan_id', 'plan-slug'); + delete window.mParticle.config.flags; + done(); + }); + it('should log a batch to v3 with no version if no version is passed', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.dataPlan = { + planId: 'plan-slug' + }; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.have.property('context'); + batch.context.should.have.property('data_plan'); + batch.context.data_plan.should.not.have.property('plan_version'); + batch.context.data_plan.should.have.property('plan_id', 'plan-slug'); + delete window.mParticle.config.flags; + done(); + }); + it('should log a batch to v3 with no context if no data plan is passed', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.dataPlan = { + planVersion: 10 + }; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.not.have.property('context'); + delete window.mParticle.config.flags; + done(); + }); + it('should log an error if a non slug string is passed as the dataplan planId', function (done) { + var errorMessage; + mParticle.config.logLevel = 'verbose'; + mParticle.config.logger = { + error: function error(msg) { + if (!errorMessage) { + errorMessage = msg; + } + } + }; + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.dataPlan = { + planId: 'not a slug', + planVersion: 10 + }; + mParticle.init(apiKey, mParticle.config); + window.mParticle.logEvent('Test Event'); + errorMessage.should.equal('Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.not.have.property('context'); + delete window.mParticle.config.flags; + done(); + }); + it('should log consent properly to v3 endpoint ', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.config.dataPlan = { + planVersion: 10 + }; + mParticle.init(apiKey, mParticle.config); + var user = mParticle.Identity.getCurrentUser(); + // Add to your consent state + var consentState = mParticle.Consent.createConsentState(); + var ccpa = mParticle.Consent.createCCPAConsent(true, Date.now(), "doc1", "location1", "hardwareid"); + consentState.setCCPAConsentState(ccpa); + var location_collection_consent = mParticle.Consent.createGDPRConsent(true, Date.now(), "doc1", "location1", "hardwareid"); + + // Add to your consent state + consentState.addGDPRConsentState("My GDPR Purpose", location_collection_consent); + user.setConsentState(consentState); + window.mParticle.logEvent('Test Event'); + var batch = JSON.parse(client.lastOptions().body); + batch.should.have.property('consent_state'); + batch.consent_state.should.have.properties(['gdpr', 'ccpa']); + batch.consent_state.gdpr.should.have.property('my gdpr purpose'); + batch.consent_state.gdpr['my gdpr purpose'].should.have.property('consented', true); + batch.consent_state.gdpr['my gdpr purpose'].should.have.property('document', 'doc1'); + batch.consent_state.gdpr['my gdpr purpose'].should.have.property('location', 'location1'); + batch.consent_state.gdpr['my gdpr purpose'].should.have.property('hardware_id', 'hardwareid'); + batch.consent_state.gdpr['my gdpr purpose'].should.have.property('timestamp_unixtime_ms'); + batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('consented', true); + batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('document', 'doc1'); + batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('location', 'location1'); + batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('hardware_id', 'hardwareid'); + batch.consent_state.ccpa['data_sale_opt_out'].should.have.property('timestamp_unixtime_ms'); + delete window.mParticle.config.flags; + done(); + }); + it('should sanitize transaction attributes in the payload on v3 endpoint', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, mParticle.config); + var product1 = mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999, 1); + var product2 = mParticle.eCommerce.createProduct('galaxy', 'galaxySKU', 799, 1); + var transactionAttributes = { + Id: 'foo-transaction-id', + Revenue: 'string', + Tax: 'string', + Shipping: 'string' + }; + var customAttributes = { + sale: true + }; + var customFlags = { + 'Google.Category': 'travel' + }; + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, [product1, product2], customAttributes, customFlags, transactionAttributes); + var batch = JSON.parse(client.lastOptions().body); + batch.events[0].data.product_action.total_amount.should.equal(0); + batch.events[0].data.product_action.shipping_amount.should.equal(0); + batch.events[0].data.product_action.tax_amount.should.equal(0); + delete window.mParticle.config.flags; + done(); + }); + it('should sanitize product attributes in the payload on v3 endpoint', function (done) { + mParticle.config.flags = { + eventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, mParticle.config); + var product1 = mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 'string', 'string', 'variant', 'category', 'brand', 'string', 'coupon'); + var product2 = mParticle.eCommerce.createProduct('galaxy', 'galaxySKU', 'string', 'string', 'variant', 'category', 'brand', 'string', 'coupon'); + var transactionAttributes = { + Id: 'foo-transaction-id', + Revenue: 'string', + Tax: 'string', + Shipping: 'string' + }; + var customAttributes = { + sale: true + }; + var customFlags = { + 'Google.Category': 'travel' + }; + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, [product1, product2], customAttributes, customFlags, transactionAttributes); + var batch = JSON.parse(client.lastOptions().body); + (batch.events[0].data.product_action.products[0].position === null).should.equal(true); + batch.events[0].data.product_action.products[0].price.should.equal(0); + batch.events[0].data.product_action.products[0].quantity.should.equal(0); + batch.events[0].data.product_action.products[0].total_product_amount.should.equal(0); + (batch.events[0].data.product_action.products[1].position === null).should.equal(true); + batch.events[0].data.product_action.products[1].price.should.equal(0); + batch.events[0].data.product_action.products[1].quantity.should.equal(0); + batch.events[0].data.product_action.products[1].total_product_amount.should.equal(0); + delete window.mParticle.config.flags; + done(); + }); + }); - var symbolExists = typeof Symbol !== 'undefined'; - var mapExists = typeof Map !== 'undefined'; - var setExists = typeof Set !== 'undefined'; - var weakMapExists = typeof WeakMap !== 'undefined'; - var weakSetExists = typeof WeakSet !== 'undefined'; - var dataViewExists = typeof DataView !== 'undefined'; - var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; - var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; - var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; - var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; - var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); - var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); - var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; - var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); - var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; - var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); - var toStringLeftSliceLength = 8; - var toStringRightSliceLength = -1; - /** - * ### typeOf (obj) - * - * Uses `Object.prototype.toString` to determine the type of an object, - * normalising behaviour across engine versions & well optimised. - * - * @param {Mixed} object - * @return {String} object type - * @api public - */ - function typeDetect(obj) { - /* ! Speed optimisation - * Pre: - * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) - * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) - * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) - * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) - * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) - * Post: - * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) - * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) - * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) - * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) - * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) - */ - var typeofObj = typeof obj; - if (typeofObj !== 'object') { - return typeofObj; - } + var getLocalStorageProducts = TestsCore.getLocalStorageProducts, + forwarderDefaultConfiguration$1 = TestsCore.forwarderDefaultConfiguration, + findEventFromRequest$3 = TestsCore.findEventFromRequest, + MockForwarder$3 = TestsCore.MockForwarder; + var mockServer$8; + describe('eCommerce', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + delete mParticle._instances['default_instance']; + mockServer$8 = sinon$1.createFakeServer(); + mockServer$8.respondImmediately = true; + client.post(urls.events, 200); + mockServer$8.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$8.restore(); + client.restore(); + mParticle._resetForTests(MPConfig); + }); + it('should create ecommerce product', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400, 2); + product.should.have.property('Name', 'iPhone'); + product.should.have.property('Sku', '12345'); + product.should.have.property('Price', 400); + product.should.have.property('Quantity', 2); + done(); + }); + it('should create transaction attributes', function (done) { + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + transactionAttributes.should.have.property('Id', '12345'); + transactionAttributes.should.have.property('Affiliation', 'test-affiliation'); + transactionAttributes.should.have.property('CouponCode', 'coupon-code'); + transactionAttributes.should.have.property('Revenue', 44334); + transactionAttributes.should.have.property('Shipping', 600); + transactionAttributes.should.have.property('Tax', 200); + done(); + }); + it('should log ecommerce event', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', '400', 2, 'Plus', 'Phones', 'Apple', 1, 'my-coupon-code', { + customkey: 'customvalue' + }), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logPurchase(transactionAttributes, product); + var purchaseEvent = findEventFromRequest$3(client._calls, 'purchase'); + purchaseEvent.data.should.have.property('product_action'); + purchaseEvent.data.product_action.should.have.property('action', 'purchase'); + purchaseEvent.data.product_action.should.have.property('transaction_id', '12345'); + purchaseEvent.data.product_action.should.have.property('affiliation', 'test-affiliation'); + purchaseEvent.data.product_action.should.have.property('coupon_code', 'coupon-code'); + purchaseEvent.data.product_action.should.have.property('total_amount', 44334); + purchaseEvent.data.product_action.should.have.property('shipping_amount', 600); + purchaseEvent.data.product_action.should.have.property('tax_amount', 200); + purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + purchaseEvent.data.product_action.products[0].should.have.property('id', '12345'); + purchaseEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + purchaseEvent.data.product_action.products[0].should.have.property('price', 400); + purchaseEvent.data.product_action.products[0].should.have.property('quantity', 2); + purchaseEvent.data.product_action.products[0].should.have.property('brand', 'Apple'); + purchaseEvent.data.product_action.products[0].should.have.property('variant', 'Plus'); + purchaseEvent.data.product_action.products[0].should.have.property('category', 'Phones'); + purchaseEvent.data.product_action.products[0].should.have.property('total_product_amount', 800); + purchaseEvent.data.product_action.products[0].should.have.property('position', 1); + purchaseEvent.data.product_action.products[0].should.have.property('coupon_code', 'my-coupon-code'); + purchaseEvent.data.product_action.products[0].should.have.property('custom_attributes'); + purchaseEvent.data.product_action.products[0].custom_attributes.should.have.property('customkey', 'customvalue'); + done(); + }); + it('should not log a ecommerce event if there is a typo in the product action type', function (done) { + // fetchMock calls will have session start and AST events, we want to reset so that we can prove the product action type does not go through (length remains 0 after logging) + client._calls = []; + var product = mParticle.eCommerce.createProduct('iPhone', '12345', '400'); + + // At this point, mockServer.requests contains 3 requests - an identity, + // session start, and AST event. + // We empty it in order to prove the following event does not send an event + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Typo, + // <------ will result in a null when converting the product action type as this is not a real value + [product]); + client._calls.length.should.equal(0); + done(); + }); + it('should log badly formed ecommerce event', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', Infinity, '2-foo', 'Plus', 'Phones', 'Apple', '1-foo', 'my-coupon-code', { + customkey: 'customvalue' + }), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', '44334-foo', '600-foo', '200-foo'); + mParticle.eCommerce.logPurchase(transactionAttributes, product); + var purchaseEvent = findEventFromRequest$3(client._calls, 'purchase'); + purchaseEvent.data.should.have.property('product_action'); + purchaseEvent.data.product_action.should.have.property('action', 'purchase'); + purchaseEvent.data.product_action.should.have.property('transaction_id', '12345'); + purchaseEvent.data.product_action.should.have.property('affiliation', 'test-affiliation'); + purchaseEvent.data.product_action.should.have.property('coupon_code', 'coupon-code'); + purchaseEvent.data.product_action.should.have.property('total_amount', 0); + purchaseEvent.data.product_action.should.have.property('shipping_amount', 0); + purchaseEvent.data.product_action.should.have.property('tax_amount', 0); + purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + purchaseEvent.data.product_action.products[0].should.have.property('id', '12345'); + purchaseEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + purchaseEvent.data.product_action.products[0].should.have.property('price', 0); + purchaseEvent.data.product_action.products[0].should.have.property('quantity', 0); + purchaseEvent.data.product_action.products[0].should.have.property('brand', 'Apple'); + purchaseEvent.data.product_action.products[0].should.have.property('variant', 'Plus'); + purchaseEvent.data.product_action.products[0].should.have.property('category', 'Phones'); + purchaseEvent.data.product_action.products[0].should.have.property('position', null); + purchaseEvent.data.product_action.products[0].should.have.property('coupon_code', 'my-coupon-code'); + purchaseEvent.data.product_action.products[0].should.have.property('total_product_amount', 0); + purchaseEvent.data.product_action.products[0].should.have.property('custom_attributes'); + purchaseEvent.data.product_action.products[0].custom_attributes.should.have.property('customkey', 'customvalue'); + done(); + }); + it('should log identical events for logPurchase and logProductAction with product action type of `purchase`', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', '400', 2, 'Plus', 'Phones', 'Apple', 1, 'my-coupon-code', { + customkey: 'customvalue' + }), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logPurchase(transactionAttributes, product); + var purchaseEvent1 = findEventFromRequest$3(client._calls, 'purchase'); + client._calls = []; + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, product, null, null, transactionAttributes); + var purchaseEvent2 = findEventFromRequest$3(client._calls, 'purchase'); + var productAction1 = purchaseEvent1.data.product_action; + var productAction2 = purchaseEvent2.data.product_action; + productAction1.action.should.equal(productAction2.action); + productAction1.transaction_id.should.equal(productAction2.transaction_id); + productAction1.affiliation.should.equal(productAction2.affiliation); + productAction1.coupon_code.should.equal(productAction2.coupon_code); + productAction1.total_amount.should.equal(productAction2.total_amount); + productAction1.shipping_amount.should.equal(productAction2.shipping_amount); + productAction1.tax_amount.should.equal(productAction2.tax_amount); + productAction1.products.length.should.equal(productAction2.products.length); + productAction1.products[0].name.should.equal(productAction2.products[0].name); + productAction1.products[0].id.should.equal(productAction2.products[0].id); + productAction1.products[0].price.should.equal(productAction2.products[0].price); + productAction1.products[0].quantity.should.equal(productAction2.products[0].quantity); + productAction1.products[0].brand.should.equal(productAction2.products[0].brand); + productAction1.products[0].variant.should.equal(productAction2.products[0].variant); + productAction1.products[0].category.should.equal(productAction2.products[0].category); + productAction1.products[0].position.should.equal(productAction2.products[0].position); + productAction1.products[0].coupon_code.should.equal(productAction2.products[0].coupon_code); + productAction1.products[0].total_product_amount.should.equal(productAction2.products[0].total_product_amount); + productAction1.products[0].custom_attributes.customkey.should.equal(productAction2.products[0].custom_attributes.customkey); + done(); + }); + it('logPurchase should support array of products', function (done) { + var product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), + product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345'); + mParticle.eCommerce.logPurchase(transactionAttributes, [product1, product2]); + var purchaseEvent = findEventFromRequest$3(client._calls, 'purchase'); + purchaseEvent.data.should.have.property('product_action'); + purchaseEvent.data.product_action.should.have.property('products')["with"].lengthOf(2); + purchaseEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + purchaseEvent.data.product_action.products[1].should.have.property('name', 'Android'); + done(); + }); + it('logRefund should support array of products', function (done) { + var product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), + product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345'); + mParticle.eCommerce.logRefund(transactionAttributes, [product1, product2]); + var refundEvent = findEventFromRequest$3(client._calls, 'refund'); + refundEvent.data.should.have.property('product_action'); + refundEvent.data.product_action.should.have.property('products')["with"].lengthOf(2); + refundEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + refundEvent.data.product_action.products[1].should.have.property('name', 'Android'); + done(); + }); + it('should create promotion', function (done) { + var promotion = mParticle.eCommerce.createPromotion('12345', 'my-creative', 'creative-name', 1); + Should(promotion).be.ok(); + promotion.should.have.property('Id', '12345'); + promotion.should.have.property('Creative', 'my-creative'); + promotion.should.have.property('Name', 'creative-name'); + promotion.should.have.property('Position', 1); + done(); + }); + it('should log promotion click', function (done) { + var promotion = mParticle.eCommerce.createPromotion('12345', 'my-creative', 'creative-name', 1); + mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, promotion); + var promotionEvent = findEventFromRequest$3(client._calls, 'click'); + Should(promotionEvent).be.ok(); + promotionEvent.data.promotion_action.should.have.property('action', PromotionActionType$1.PromotionClick); + promotionEvent.data.promotion_action.should.have.property('promotions'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('id', '12345'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('name', 'creative-name'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('creative', 'my-creative'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('position', 1); + done(); + }); + it('should allow multiple promotions to be logged at once', function (done) { + var promotion1 = mParticle.eCommerce.createPromotion('12345', 'my-creative1', 'creative-name1', 1); + var promotion2 = mParticle.eCommerce.createPromotion('67890', 'my-creative2', 'creative-name2', 2); + mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, [promotion1, promotion2]); + var promotionEvent = findEventFromRequest$3(client._calls, 'click'); + Should(promotionEvent).be.ok(); + promotionEvent.data.promotion_action.should.have.property('action', PromotionActionType$1.PromotionClick); + promotionEvent.data.promotion_action.should.have.property('promotions'); + promotionEvent.data.promotion_action.promotions.length.should.equal(2); + promotionEvent.data.promotion_action.promotions[0].should.have.property('id', '12345'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('name', 'creative-name1'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('creative', 'my-creative1'); + promotionEvent.data.promotion_action.promotions[0].should.have.property('position', 1); + promotionEvent.data.promotion_action.promotions[1].should.have.property('id', '67890'); + promotionEvent.data.promotion_action.promotions[1].should.have.property('name', 'creative-name2'); + promotionEvent.data.promotion_action.promotions[1].should.have.property('creative', 'my-creative2'); + promotionEvent.data.promotion_action.promotions[1].should.have.property('position', 2); + done(); + }); + it('should allow an promotions to bypass server upload', function (done) { + var promotion = mParticle.eCommerce.createPromotion('12345', 'my-creative', 'creative-name', 1); + mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, promotion, {}, {}, { + shouldUploadEvent: false + }); + var promotionEvent = findEventFromRequest$3(client._calls, 'click'); + Should(promotionEvent).not.be.ok(); + done(); + }); + it('should create impression', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400), + impression = mParticle.eCommerce.createImpression('impression-name', product); + impression.should.have.property('Name', 'impression-name'); + impression.should.have.property('Product'); + impression.Product.should.have.property('Sku', '12345'); + done(); + }); + it('should log impression event', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400), + impression = mParticle.eCommerce.createImpression('impression-name', product); + mParticle.eCommerce.logImpression(impression); + var impressionEvent = findEventFromRequest$3(client._calls, 'impression'); + Should(impressionEvent).be.ok(); + impressionEvent.data.should.have.property('product_impressions')["with"].lengthOf(1); + impressionEvent.data.product_impressions[0].should.have.property('product_impression_list', 'impression-name'); + impressionEvent.data.product_impressions[0].should.have.property('products')["with"].lengthOf(1); + impressionEvent.data.product_impressions[0].products[0].should.have.property('id', '12345'); + done(); + }); + it('should allow an impression to bypass server upload', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400), + impression = mParticle.eCommerce.createImpression('impression-name', product); + mParticle.eCommerce.logImpression(impression, null, null, { + shouldUploadEvent: false + }); + var impressionEvent = findEventFromRequest$3(client._calls, 'impression'); + Should(impressionEvent).not.be.ok(); + done(); + }); + it('should log multiple impression when an array of impressions is passed', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400), + impression = mParticle.eCommerce.createImpression('impression-name1', product), + product2 = mParticle.eCommerce.createProduct('Android', '23456', 200), + impression2 = mParticle.eCommerce.createImpression('impression-name2', product2); + mParticle.eCommerce.logImpression([impression, impression2]); + var impressionEvent = findEventFromRequest$3(client._calls, 'impression'); + Should(impressionEvent).be.ok(); + impressionEvent.data.should.have.property('product_impressions')["with"].lengthOf(2); + impressionEvent.data.product_impressions[0].should.have.property('product_impression_list', 'impression-name1'); + impressionEvent.data.product_impressions[0].should.have.property('products')["with"].lengthOf(1); + impressionEvent.data.product_impressions[0].products[0].should.have.property('id', '12345'); + impressionEvent.data.product_impressions[1].should.have.property('product_impression_list', 'impression-name2'); + impressionEvent.data.product_impressions[1].should.have.property('products')["with"].lengthOf(1); + impressionEvent.data.product_impressions[1].products[0].should.have.property('id', '23456'); + done(); + }); + it('should log ecommerce refund', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400, 2, 'Apple', 'Plus', 'Phones'), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logRefund(transactionAttributes, product); + var refundEvent = findEventFromRequest$3(client._calls, 'refund'); + Should(refundEvent).be.ok(); + refundEvent.data.should.have.property('product_action'); + refundEvent.data.product_action.should.have.property('action', 'refund'); + refundEvent.data.product_action.should.have.property('transaction_id', '12345'); + refundEvent.data.product_action.should.have.property('affiliation', 'test-affiliation'); + refundEvent.data.product_action.should.have.property('coupon_code', 'coupon-code'); + refundEvent.data.product_action.should.have.property('total_amount', 44334); + refundEvent.data.product_action.should.have.property('shipping_amount', 600); + refundEvent.data.product_action.should.have.property('tax_amount', 200); + refundEvent.data.product_action.products.should.have.length(1); + refundEvent.data.product_action.products[0].should.have.property('id', '12345'); + refundEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + refundEvent.data.product_action.products[0].should.have.property('price', 400); + refundEvent.data.product_action.products[0].should.have.property('quantity', 2); + refundEvent.data.product_action.products[0].should.have.property('brand', 'Phones'); + refundEvent.data.product_action.products[0].should.have.property('variant', 'Apple'); + refundEvent.data.product_action.products[0].should.have.property('category', 'Plus'); + refundEvent.data.product_action.products[0].should.have.property('total_product_amount', 800); + done(); + }); + it('should log identical events for logRefund and logProductAction with a product action of `refund`', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', '400', 2, 'Plus', 'Phones', 'Apple', 1, 'my-coupon-code', { + customkey: 'customvalue' + }), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logRefund(transactionAttributes, product); + var refundEvent1 = findEventFromRequest$3(client._calls, 'refund'); + client._calls = []; + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Refund, product, null, null, transactionAttributes); + var refundEvent2 = findEventFromRequest$3(client._calls, 'refund'); + Should(refundEvent1).be.ok(); + Should(refundEvent2).be.ok(); + refundEvent1.data.product_action.action.should.equal(refundEvent2.data.product_action.action); + refundEvent1.data.product_action.transaction_id.should.equal(refundEvent2.data.product_action.transaction_id); + refundEvent1.data.product_action.affiliation.should.equal(refundEvent2.data.product_action.affiliation); + refundEvent1.data.product_action.coupon_code.should.equal(refundEvent2.data.product_action.coupon_code); + refundEvent1.data.product_action.total_amount.should.equal(refundEvent2.data.product_action.total_amount); + refundEvent1.data.product_action.shipping_amount.should.equal(refundEvent2.data.product_action.shipping_amount); + refundEvent1.data.product_action.tax_amount.should.equal(refundEvent2.data.product_action.tax_amount); + refundEvent1.data.product_action.products.length.should.equal(refundEvent2.data.product_action.products.length); + refundEvent1.data.product_action.products[0].id.should.equal(refundEvent2.data.product_action.products[0].id); + refundEvent1.data.product_action.products[0].price.should.equal(refundEvent2.data.product_action.products[0].price); + refundEvent1.data.product_action.products[0].quantity.should.equal(refundEvent2.data.product_action.products[0].quantity); + refundEvent1.data.product_action.products[0].brand.should.equal(refundEvent2.data.product_action.products[0].brand); + refundEvent1.data.product_action.products[0].variant.should.equal(refundEvent2.data.product_action.products[0].variant); + refundEvent1.data.product_action.products[0].category.should.equal(refundEvent2.data.product_action.products[0].category); + refundEvent1.data.product_action.products[0].position.should.equal(refundEvent2.data.product_action.products[0].position); + done(); + }); + it('should allow a product action to bypass server upload', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', '400', 2, 'Plus', 'Phones', 'Apple', 1, 'my-coupon-code', { + customkey: 'customvalue' + }), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, product, null, null, transactionAttributes, { + shouldUploadEvent: false + }); + var event = findEventFromRequest$3(client._calls, 'purchase'); + Should(event).not.be.ok(); + done(); + }); + it('should add products to cart', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.Cart.add(product, true); + var addToCartEvent = findEventFromRequest$3(client._calls, 'add_to_cart'); + addToCartEvent.data.should.have.property('product_action'); + addToCartEvent.data.product_action.should.have.property('action', 'add_to_cart'); + addToCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + addToCartEvent.data.product_action.products[0].should.have.property('id', '12345'); + done(); + }); + it('should remove products to cart', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.Cart.add(product); + mParticle.eCommerce.Cart.remove({ + Sku: '12345' + }, true); + var removeFromCartEvent = findEventFromRequest$3(client._calls, 'remove_from_cart'); + removeFromCartEvent.data.should.have.property('product_action'); + removeFromCartEvent.data.product_action.should.have.property('action', 'remove_from_cart'); + removeFromCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + removeFromCartEvent.data.product_action.products[0].should.have.property('id', '12345'); + done(); + }); + it('should update cart products in cookies after adding/removing product to/from a cart and clearing cart', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.Cart.add(product); + var products1 = getLocalStorageProducts(); + products1[testMPID].cp[0].should.have.properties(['Name', 'Sku', 'Price']); + mParticle.eCommerce.Cart.remove(product); + var products2 = getLocalStorageProducts(); + products2[testMPID].cp.length.should.equal(0); + mParticle.eCommerce.Cart.add(product); + var products3 = getLocalStorageProducts(); + products3[testMPID].cp[0].should.have.properties(['Name', 'Sku', 'Price']); + mParticle.eCommerce.Cart.clear(); + var products4 = getLocalStorageProducts(); + products4[testMPID].cp.length.should.equal(0); + done(); + }); + it('should not add the (config.maxProducts + 1st) item to cookie cartItems and only send cookie cartProducts when logging', function (done) { + mParticle.config.maxProducts = 10; + mParticle.config.workspaceToken = workspaceToken; + mParticle.init(apiKey, window.mParticle.config); + var product = mParticle.eCommerce.createProduct('Product', '12345', 400); + for (var i = 0; i < mParticle.config.maxProducts; i++) { + mParticle.eCommerce.Cart.add(product); + } + mParticle.eCommerce.Cart.add(mParticle.eCommerce.createProduct('Product11', '12345', 400)); + var products1 = getLocalStorageProducts(); + var foundProductInCookies = products1[testMPID].cp.filter(function (product) { + return product.Name === 'Product11'; + })[0]; + products1[testMPID].cp.length.should.equal(10); + Should(foundProductInCookies).be.ok(); + done(); + }); + it('should log checkout via deprecated logCheckout method', function (done) { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.eCommerce.logCheckout(1, 'Visa'); + var checkoutEvent = findEventFromRequest$3(client._calls, 'checkout'); + Should(checkoutEvent).be.ok(); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql('mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead'); + checkoutEvent.should.have.property('event_type', 'commerce_event'); + checkoutEvent.data.should.have.property('product_action'); + checkoutEvent.data.product_action.should.have.property('action', 'checkout'); + checkoutEvent.data.product_action.should.have.property('checkout_step', 1); + checkoutEvent.data.product_action.should.have.property('checkout_options', 'Visa'); + done(); + }); + it('should log checkout via mParticle.logProductAction method', function (done) { + var product1 = mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + var product2 = mParticle.eCommerce.createProduct('galaxy', 'galaxySKU', 799); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Checkout, [product1, product2], null, null, { + Step: 4, + Option: 'Visa' + }); + var checkoutEvent = findEventFromRequest$3(client._calls, 'checkout'); + Should(checkoutEvent).be.ok(); + checkoutEvent.should.have.property('event_type', 'commerce_event'); + checkoutEvent.data.should.have.property('product_action'); + checkoutEvent.data.product_action.should.have.property('action', 'checkout'); + checkoutEvent.data.product_action.should.have.property('checkout_step', 4); + checkoutEvent.data.product_action.should.have.property('checkout_options', 'Visa'); + checkoutEvent.data.product_action.products[0].should.have.property('id', 'iphoneSKU'); + checkoutEvent.data.product_action.products[1].should.have.property('id', 'galaxySKU'); + done(); + }); + it('should log checkout option', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mockServer$8.requests = []; + mParticle.eCommerce.logProductAction(ProductActionType$1.CheckoutOption, product, { + color: 'blue' + }); + var checkoutOptionEvent = findEventFromRequest$3(client._calls, 'checkout_option'); + Should(checkoutOptionEvent).be.ok(); + checkoutOptionEvent.should.have.property('event_type', 'commerce_event'); + checkoutOptionEvent.data.should.have.property('product_action'); + checkoutOptionEvent.data.product_action.should.have.property('action', 'checkout_option'); + checkoutOptionEvent.data.custom_attributes.should.have.property('color', 'blue'); + done(); + }); + it('should log product action', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.logProductAction(ProductActionType$1.ViewDetail, product); + var viewDetailEvent = findEventFromRequest$3(client._calls, 'view_detail'); + Should(viewDetailEvent).be.ok(); + viewDetailEvent.should.have.property('event_type', 'commerce_event'); + viewDetailEvent.data.should.have.property('product_action'); + viewDetailEvent.data.product_action.should.have.property('action', 'view_detail'); + viewDetailEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + viewDetailEvent.data.product_action.products[0].should.have.property('id', '12345'); + done(); + }); + it('should fail to create product if name not a string', function (done) { + var product = mParticle.eCommerce.createProduct(null); + var product2 = mParticle.eCommerce.createProduct(undefined); + var product3 = mParticle.eCommerce.createProduct(['product']); + var product4 = mParticle.eCommerce.createProduct(123); + var product5 = mParticle.eCommerce.createProduct({ + key: 'value' + }); + Should(product).not.be.ok(); + Should(product2).not.be.ok(); + Should(product3).not.be.ok(); + Should(product4).not.be.ok(); + Should(product5).not.be.ok(); + done(); + }); + it('should fail to create product if sku not a string or a number', function (done) { + var product = mParticle.eCommerce.createProduct('test', null); + var product2 = mParticle.eCommerce.createProduct('test', { + key: 'value' + }); + var product3 = mParticle.eCommerce.createProduct('test', []); + var product4 = mParticle.eCommerce.createProduct('test', undefined); + Should(product).not.be.ok(); + Should(product2).not.be.ok(); + Should(product3).not.be.ok(); + Should(product4).not.be.ok(); + done(); + }); + it('should fail to create product if price not a string or number', function (done) { + var product = mParticle.eCommerce.createProduct('test', 'sku', null); + var product2 = mParticle.eCommerce.createProduct('test', 'sku', null); + var product3 = mParticle.eCommerce.createProduct('test', 'sku', null); + var product4 = mParticle.eCommerce.createProduct('test', 'sku', null); + Should(product).not.be.ok(); + Should(product2).not.be.ok(); + Should(product3).not.be.ok(); + Should(product4).not.be.ok(); + done(); + }); + it('should fail to create impression if name is not specified', function (done) { + var impression = mParticle.eCommerce.createImpression(null); + Should(impression).not.be.ok(); + done(); + }); + it('should fail to create impression if product is not specified', function (done) { + var impression = mParticle.eCommerce.createImpression('name', null); + Should(impression).not.be.ok(); + done(); + }); + it('should set product position to 0 if null', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400, 2, 'Apple', 'Plus', 'Phones'), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes('12345', 'test-affiliation', 'coupon-code', 44334, 600, 200); + mParticle.eCommerce.logPurchase(transactionAttributes, product); + var purchaseEvent = findEventFromRequest$3(client._calls, 'purchase'); + purchaseEvent.data.product_action.products[0].should.not.have.property('position'); + done(); + }); + it('should support array of products when adding to cart', function (done) { + var product1 = mParticle.eCommerce.createProduct('iPhone', '12345', 400, 2), + product2 = mParticle.eCommerce.createProduct('Nexus', '67890', 300, 1); + mParticle.eCommerce.Cart.add([product1, product2], true); + var addToCartEvent = findEventFromRequest$3(client._calls, 'add_to_cart'); + Should(addToCartEvent).be.ok(); + addToCartEvent.data.should.have.property('product_action'); + addToCartEvent.data.product_action.should.have.property('action', 'add_to_cart'); + addToCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(2); + addToCartEvent.data.product_action.products[0].should.have.property('id', '12345'); + addToCartEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + addToCartEvent.data.product_action.products[1].should.have.property('id', '67890'); + addToCartEvent.data.product_action.products[1].should.have.property('name', 'Nexus'); + done(); + }); + it('should support a single product when adding to cart', function (done) { + var product1 = mParticle.eCommerce.createProduct('iPhone', '12345', 400, 2); + mParticle.eCommerce.Cart.add(product1, true); + var addToCartEvent = findEventFromRequest$3(client._calls, 'add_to_cart'); + Should(addToCartEvent).be.ok(); + addToCartEvent.data.should.have.property('product_action'); + addToCartEvent.data.product_action.should.have.property('action', 'add_to_cart'); + addToCartEvent.data.product_action.should.have.property('products')["with"].lengthOf(1); + addToCartEvent.data.product_action.products[0].should.have.property('id', '12345'); + addToCartEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + done(); + }); + it('expand product purchase commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.eCommerce.setCurrencyCode('foo-currency'); + var productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + var product = mParticle.eCommerce.createProduct('Foo name', 'Foo sku', 100.0, 4, 'foo-variant', 'foo-category', 'foo-brand', 5, 'foo-productcouponcode', productAttributes); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('foo-transaction-id', 'foo-affiliation', 'foo-couponcode', 400, 10, 8); + mParticle.eCommerce.logPurchase(transactionAttributes, product, false, eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('ProductAction'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(2); + var plusOneEvent = expandedEvents[0]; + plusOneEvent.should.have.property('EventName', 'eCommerce - purchase - Total'); + plusOneEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + var attributes = plusOneEvent.EventAttributes; + attributes.should.have.property('Transaction Id', 'foo-transaction-id'); + attributes.should.have.property('Affiliation', 'foo-affiliation'); + attributes.should.have.property('Coupon Code', 'foo-couponcode'); + attributes.should.have.property('Total Amount', 400); + attributes.should.have.property('Shipping Amount', 10); + attributes.should.have.property('Product Count', 1); + attributes.should.have.property('Tax Amount', 8); + attributes.should.have.property('Currency Code', 'foo-currency'); + attributes.should.have.property('foo-event-attribute-key', 'foo-event-attribute-value'); + var productEvent = expandedEvents[1]; + productEvent.should.have.property('EventName', 'eCommerce - purchase - Item'); + productEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + attributes = productEvent.EventAttributes; + attributes.should.not.have.property('Affiliation'); + attributes.should.not.have.property('Total Amount'); + attributes.should.not.have.property('Shipping Amount'); + attributes.should.not.have.property('Tax Amount'); + attributes.should.have.property('foo-event-attribute-key'); + attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); + attributes.should.have.property('Brand', 'foo-brand'); + attributes.should.have.property('Category', 'foo-category'); + attributes.should.have.property('Name', 'Foo name'); + attributes.should.have.property('Id', 'Foo sku'); + attributes.should.have.property('Item Price', 100.0); + attributes.should.have.property('Quantity', 4); + attributes.should.have.property('Position', 5); + attributes.should.have.property('foo-attribute-key', 'foo-product-attribute-value'); + done(); + }); + it('expand product refund commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + var product = mParticle.eCommerce.createProduct('Foo name', 'Foo sku', 100.0, 4, 'foo-variant', 'foo-category', 'foo-brand', 5, 'foo-productcouponcode', productAttributes); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('foo-transaction-id', 'foo-affiliation', 'foo-couponcode', 400, 10, 8); + mParticle.eCommerce.logRefund(transactionAttributes, product, false, eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('ProductAction'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(2); + var plusOneEvent = expandedEvents[0]; + plusOneEvent.should.have.property('EventName', 'eCommerce - refund - Total'); + var attributes = plusOneEvent.EventAttributes; + attributes.should.have.property('Product Count', 1); + var productEvent = expandedEvents[1]; + productEvent.should.have.property('EventName', 'eCommerce - refund - Item'); + done(); + }); + it('expand non-plus-one-product commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + var product = mParticle.eCommerce.createProduct('Foo name', 'Foo sku', 100.0, 4, 'foo-variant', 'foo-category', 'foo-brand', 5, 'foo-productcouponcode', productAttributes); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.RemoveFromWishlist, product, eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('ProductAction'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(1); + var productEvent = expandedEvents[0]; + productEvent.should.have.property('EventName', 'eCommerce - remove_from_wishlist - Item'); + productEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + var attributes = productEvent.EventAttributes; + attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); + attributes.should.have.property('Brand', 'foo-brand'); + attributes.should.have.property('Category', 'foo-category'); + attributes.should.have.property('Name', 'Foo name'); + attributes.should.have.property('Id', 'Foo sku'); + attributes.should.have.property('Item Price', 100.0); + attributes.should.have.property('Quantity', 4); + attributes.should.have.property('Position', 5); + attributes.should.have.property('foo-attribute-key', 'foo-product-attribute-value'); + done(); + }); + it('expand checkout commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + eventAttributes['Checkout Step'] = 'foo-step'; + eventAttributes['Checkout Options'] = 'foo-options'; + var productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; + var product = mParticle.eCommerce.createProduct('Foo name', 'Foo sku', 100.0, 4, 'foo-variant', 'foo-category', 'foo-brand', 5, 'foo-productcouponcode', productAttributes); + mParticle.eCommerce.Cart.add(product, true); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Checkout, [product], eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('ProductAction'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(1); + var productEvent = expandedEvents[0]; + productEvent.should.have.property('EventName', 'eCommerce - checkout - Item'); + productEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + var attributes = productEvent.EventAttributes; + attributes.should.have.property('Checkout Step', 'foo-step'); + attributes.should.have.property('Checkout Options', 'foo-options'); + attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); + attributes.should.have.property('Brand', 'foo-brand'); + attributes.should.have.property('Category', 'foo-category'); + attributes.should.have.property('Name', 'Foo name'); + attributes.should.have.property('Id', 'Foo sku'); + attributes.should.have.property('Item Price', 100.0); + attributes.should.have.property('Quantity', 4); + attributes.should.have.property('Position', 5); + attributes.should.have.property('foo-attribute-key', 'foo-product-attribute-value'); + done(); + }); + it('expand promotion commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + var promotion = mParticle.eCommerce.createPromotion('foo-id', 'foo-creative', 'foo-name', 5); + mParticle.eCommerce.logPromotion(mParticle.PromotionType.PromotionClick, promotion, eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('PromotionAction'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(1); + var promotionEvent = expandedEvents[0]; + promotionEvent.should.have.property('EventName', 'eCommerce - click - Item'); + promotionEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + var attributes = promotionEvent.EventAttributes; + attributes.should.have.property('Id', 'foo-id'); + attributes.should.have.property('Creative', 'foo-creative'); + attributes.should.have.property('Name', 'foo-name'); + attributes.should.have.property('Position', 5); + attributes.should.have.property('foo-event-attribute-key', 'foo-event-attribute-value'); + done(); + }); + it('expand null commerce event', function (done) { + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(null); + (expandedEvents == null).should.be["true"]; + done(); + }); + it('expand impression commerce event', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$3(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration$1('MockForwarder', 1); + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; + var eventAttributes = {}; + eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; + var product = mParticle.eCommerce.createProduct('Foo name', 'Foo sku', 100.0, 4, 'foo-variant', 'foo-category', 'foo-brand', 5, 'foo-productcouponcode', productAttributes); + var impression = mParticle.eCommerce.createImpression('suggested products list', product); + mParticle.eCommerce.logImpression(impression, eventAttributes); + window.MockForwarder1.instance.receivedEvent.should.have.property('ProductImpressions'); + var expandedEvents = mParticle.eCommerce.expandCommerceEvent(window.MockForwarder1.instance.receivedEvent); + expandedEvents.should.be["instanceof"](Array).and.have.lengthOf(1); + var impressionEvent = expandedEvents[0]; + impressionEvent.should.have.property('EventName', 'eCommerce - Impression - Item'); + impressionEvent.should.have.property('EventCategory', mParticle.EventType.Transaction); + var attributes = impressionEvent.EventAttributes; + attributes.should.have.property('Product Impression List', 'suggested products list'); + attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); + attributes.should.have.property('Brand', 'foo-brand'); + attributes.should.have.property('Category', 'foo-category'); + attributes.should.have.property('Name', 'Foo name'); + attributes.should.have.property('Id', 'Foo sku'); + attributes.should.have.property('Item Price', 100.0); + attributes.should.have.property('Quantity', 4); + attributes.should.have.property('Position', 5); + attributes.should.have.property('foo-attribute-key', 'foo-product-attribute-value'); + attributes.should.have.property('foo-event-attribute-key', 'foo-event-attribute-value'); + done(); + }); + it('should add customFlags to logCheckout events', function (done) { + mParticle.eCommerce.logCheckout(1, {}, {}, { + interactionEvent: true + }); + var checkoutEvent = findEventFromRequest$3(client._calls, 'checkout'); + checkoutEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + it('should add customFlags to logProductAction events', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); + mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Unknown, product, { + price: 5 + }, { + interactionEvent: true + }); + var unknownEvent = findEventFromRequest$3(client._calls, 'unknown'); + unknownEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + it('should add customFlags to logPurchase events', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('id1', 'affil1', 'couponCode1'); + mParticle.eCommerce.logPurchase(transactionAttributes, product, true, { + shipping: 5 + }, { + interactionEvent: true + }); + var purchaseEvent = findEventFromRequest$3(client._calls, 'purchase'); + purchaseEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + it('should add customFlags to logPromotion events', function (done) { + var promotion = mParticle.eCommerce.createPromotion('id', 'creative', 'name'); + mParticle.eCommerce.logPromotion(mParticle.PromotionType.Unknown, promotion, { + shipping: 5 + }, { + interactionEvent: true + }); + var promotionEvent = findEventFromRequest$3(client._calls, 'click'); + promotionEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + it('should add customFlags to logImpression events', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); + var impression = mParticle.eCommerce.createImpression('iphoneImpressionName', product); + mParticle.eCommerce.logImpression(impression, { + shipping: 5 + }, { + interactionEvent: true + }); + var impressionEvent = findEventFromRequest$3(client._calls, 'impression'); + impressionEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + it('should add customFlags to logRefund events', function (done) { + var product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('id1', 'affil1', 'couponCode1'); + mParticle.eCommerce.logRefund(transactionAttributes, product, true, { + shipping: 5 + }, { + interactionEvent: true + }); + var refundEvent = findEventFromRequest$3(client._calls, 'refund'); + refundEvent.data.custom_flags.interactionEvent.should.equal(true); + done(); + }); + describe('Cart', function () { + afterEach(function () { + sinon$1.restore(); + }); + it('should deprecate add', function () { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.Cart.add(product, true); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql('Deprecated function eCommerce.Cart.add() will be removed in future releases'); + }); + it('should deprecate remove', function () { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + var product = mParticle.eCommerce.createProduct('iPhone', '12345', 400); + mParticle.eCommerce.Cart.remove(product, true); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql('Deprecated function eCommerce.Cart.remove() will be removed in future releases'); + }); + it('should deprecate clear', function () { + var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); + mParticle.eCommerce.Cart.clear(); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql('Deprecated function eCommerce.Cart.clear() will be removed in future releases'); + }); + it('should be empty when transactionAttributes is empty', function () { + var mparticle = mParticle.getInstance(); + var productAction = {}; + mparticle._Ecommerce.convertTransactionAttributesToProductAction({}, productAction); + Object.keys(productAction).length.should.equal(0); + }); + it('should sanitize certain ecommerce amounts from strings to 0', function () { + mParticle.getInstance()._Ecommerce.sanitizeAmount('$42', 'Price').should.equal(0); + mParticle.getInstance()._Ecommerce.sanitizeAmount('$100', 'TotalAmount').should.equal(0); + mParticle.getInstance()._Ecommerce.sanitizeAmount('first', 'Position').should.equal(0); + mParticle.getInstance()._Ecommerce.sanitizeAmount('two', 'Quantity').should.equal(0); + mParticle.getInstance()._Ecommerce.sanitizeAmount('string', 'Shipping').should.equal(0); + mParticle.getInstance()._Ecommerce.sanitizeAmount('$5.80', 'Tax').should.equal(0); + }); + it('should convert transactionAttributes strings to numbers or zero', function () { + var mparticle = mParticle.getInstance(); + var transactionAttributes = { + Id: "id", + Affiliation: "affiliation", + CouponCode: "couponCode", + Revenue: "revenue", + Shipping: "shipping", + Tax: "tax" + }; + var productAction = {}; + mparticle._Ecommerce.convertTransactionAttributesToProductAction(transactionAttributes, productAction); + productAction.TransactionId.should.equal("id"); + productAction.Affiliation.should.equal("affiliation"); + productAction.CouponCode.should.equal("couponCode"); + + // convert strings to 0 + productAction.TotalAmount.should.equal(0); + productAction.ShippingAmount.should.equal(0); + productAction.TaxAmount.should.equal(0); + }); + }); + }); - /* ! Speed optimisation - * Pre: - * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) - * Post: - * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) - */ - if (obj === null) { - return 'null'; - } + var setLocalStorage = TestsCore.setLocalStorage, + MockForwarder$2 = TestsCore.MockForwarder, + getLocalStorage$2 = TestsCore.getLocalStorage; + var pixelSettings = { + name: 'TestPixel', + moduleId: 5, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }; + var mockServer$7; + describe('cookie syncing', function () { + var timeout = 25; + // Have a reference to createElement function to reset after all cookie sync + // tests have run + var originalCreateElementFunction = window.document.createElement; + before(function () { + // Mock the img create onload method + // https://raminmousavi.medium.com/mock-img-element-in-jest-3341c495ca8b + window.document.createElement = function (create) { + return function () { + var element = create.apply(this, arguments); + if (element.tagName === 'IMG') { + setTimeout(function () { + element.onload(new Event('load')); + }, 10); + } + return element; + }; + }(document.createElement); + }); + after(function () { + // Reset the mock + window.document.createElement = originalCreateElementFunction; + }); + beforeEach(function () { + mockServer$7 = sinon$1.createFakeServer(); + mockServer$7.respondImmediately = true; + mockServer$7.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); - /* ! Spec Conformance - * Test: `Object.prototype.toString.call(window)`` - * - Node === "[object global]" - * - Chrome === "[object global]" - * - Firefox === "[object Window]" - * - PhantomJS === "[object Window]" - * - Safari === "[object Window]" - * - IE 11 === "[object Window]" - * - IE Edge === "[object Window]" - * Test: `Object.prototype.toString.call(this)`` - * - Chrome Worker === "[object global]" - * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" - * - Safari Worker === "[object DedicatedWorkerGlobalScope]" - * - IE 11 Worker === "[object WorkerGlobalScope]" - * - IE Edge Worker === "[object WorkerGlobalScope]" - */ - if (obj === globalObject) { - return 'global'; - } + // fetchMock.post(urls.events, 200); - /* ! Speed optimisation - * Pre: - * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) - * Post: - * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) - */ - if ( - Array.isArray(obj) && - (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) - ) { - return 'Array'; - } + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$7.restore(); + mParticle._resetForTests(MPConfig); + }); + it('should sync cookies when there was not a previous cookie-sync', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1); + var data = mParticle.getInstance()._Persistence.getLocalStorage(); + data[testMPID].csd.should.have.property('5'); + done(); + }, timeout); + }); + it('should sync cookies when current date is beyond the frequency cap and the MPID has not changed', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.pixelConfigs = [pixelSettings]; + setLocalStorage(v4LSKey, { + cu: testMPID, + testMPID: { + csd: { + 5: new Date(500).getTime() + } + }, + ie: true + }); + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1); + var data = mParticle.getInstance()._Persistence.getLocalStorage(); + var updated = data[testMPID].csd['5'] > 500; + Should(updated).be.ok(); + done(); + }, timeout); + }); + it('should not sync cookies when last date is within frequencyCap', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.pixelConfigs = [pixelSettings]; + setLocalStorage(); + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + mockServer$7.requests = []; + var data = mParticle.getInstance()._Persistence.getLocalStorage(); + data[testMPID].csd.should.have.property(5, mParticle.getInstance()._Persistence.getLocalStorage().testMPID.csd['5']); + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1); + done(); + }, timeout); + }); + it('should sync cookies when mpid changes', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var data1 = mParticle.getInstance()._Persistence.getLocalStorage(); + mockServer$7.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'otherMPID', + is_logged_in: false + })]); + mParticle.Identity.login(); + setTimeout(function () { + var data2 = mParticle.getInstance()._Persistence.getLocalStorage(); + data1[testMPID].csd[5].should.be.ok(); + data2['otherMPID'].csd[5].should.be.ok(); + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1); + done(); + }, timeout); + }, timeout); + }); + it('should not sync cookies when pixelSettings.isDebug is false, pixelSettings.isProduction is true, and mParticle.config.isDevelopmentMode is true', function (done) { + var pixelSettings = { + name: 'TestPixel', + moduleId: 5, + esId: 24053, + isDebug: false, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = true; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var data1 = mParticle.getInstance()._Persistence.getLocalStorage(); + Object.keys(data1[testMPID]).should.not.have.property('csd'); + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(0); + done(); + }, 500); + }); + it('should not sync cookies when pixelSettings.isDebug is true, pixelSettings.isProduction is false, and mParticle.config.isDevelopmentMode is false', function (done) { + var pixelSettings = { + name: 'TestPixel', + moduleId: 5, + esId: 24053, + isDebug: true, + isProduction: false, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var data1 = mParticle.getInstance()._Persistence.getLocalStorage(); + data1[testMPID].should.not.have.property('csd'); + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(0); + done(); + }, timeout); + }); + it('should replace mpID properly', function (done) { + var result = mParticle.getInstance()._CookieSyncManager.replaceMPID('www.google.com?mpid=%%mpid%%?foo=bar', 123); + result.should.equal('www.google.com?mpid=123?foo=bar'); + done(); + }); + it("should remove 'amp;' from the URLs", function (done) { + var result = mParticle.getInstance()._CookieSyncManager.replaceAmp('www.google.com?mpid=%%mpid%%&foo=bar'); + result.should.equal('www.google.com?mpid=%%mpid%%&foo=bar'); + done(); + }); + it('parse and capture pixel settings properly from backend', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.requestConfig = true; + // create some cookies + mParticle.init(apiKey, window.mParticle.config); + var mockForwarder = new MockForwarder$2('DynamicYield', 128); + var mockForwarder2 = new MockForwarder$2('Adobe', 124); + mockForwarder.register(window.mParticle.config); + mockForwarder2.register(window.mParticle.config); + var forwarderConfigurationResult = { + pixelConfigs: [{ + name: 'TestPixel', + moduleId: 5, + esId: 24053, + isDebug: false, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }] + }; + mockServer$7.respondWith(urls.config, [200, {}, JSON.stringify(forwarderConfigurationResult)]); + mockServer$7.requests = []; + // add pixels to preInitConfig + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + mParticle.getInstance()._Store.pixelConfigurations.length.should.equal(1); + mockServer$7.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'MPID1', + is_logged_in: false + })]); + + // force the preInit cookie configurations to fire + mParticle.Identity.login({ + userIdentities: { + customerid: 'abc' + } + }); + setTimeout(function () { + var cookies = getLocalStorage$2(); + Object.keys(cookies['MPID1'].csd).length.should.equal(1); + done(); + }, timeout); + }, timeout); + }); + var MockUser = function MockUser() { + var consentState = null; + return { + setConsentState: function setConsentState(state) { + consentState = state; + }, + getConsentState: function getConsentState() { + return consentState; + } + }; + }; + it('should perform a cookiesync when consent is not configured on the cookiesync setting', function (done) { + mParticle._resetForTests(MPConfig); + pixelSettings.filteringConsentRuleValues = {}; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + Should(mParticle.getInstance()._Store.pixelConfigurations.length).equal(1); + var data = mParticle.getInstance()._Persistence.getLocalStorage(); + data[testMPID].csd.should.have.property('5'); + done(); + }, timeout); + }); + it('should return false for isEnabledForUserConsent when consent is configured but no user is passed', function (done) { + mParticle._resetForTests(MPConfig); + var enableCookieSync = true; + var consented = false; + var filteringConsentRuleValues = { + includeOnMatch: enableCookieSync, + values: [{ + consentPurpose: '123', + hasConsented: consented + }] + }; + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, null); + enabled.should.not.be.ok(); + done(); + }); + it("should disable cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is rejected", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should disable cookie sync if 'Do Not Forward' when 'Consent Accepted' is selected and user consent is given", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should enable cookie sync if 'Only Forward' when 'Consent Rejected' is selected and user consent is rejected", function (done) { + var includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should enable cookie sync if 'Only Forward' when 'Consent Given'is selected and user consent is given", function (done) { + var includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should disable cookie sync if 'Only Forward' on 'Consent Given' is selected and user consent is not given", function (done) { + var includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsented = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsented)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is given", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsented = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsented)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Do Not Forward' when 'Consent Given' is selected and user consent is rejected", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var userConsented = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsented)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Do Not Forward' when 'Consent Rejected' is selected and user consent is given", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var userConsented = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(userConsented)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should not perform a cookie sync if 'Do Not Forward' if CCPA is 'Not Present' is selected and user CCPA is not present", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var ccpaPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should not perform a cookie sync if 'Do Not Forward' if CCPA is 'Present' is selected and user CCPA is present", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var ccpaPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Only Forward' if CCPA is 'Not Present' is selected and user CCPA is not present", function (done) { + var includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var ccpaPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Only Forward' when CCPA is 'Present' is selected and user CCPA is present", function (done) { + var includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var ccpaPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should not perform a cookie sync if 'Only Forward' when CCPA is 'Present' is selected and CCPA is not present", function (done) { + var includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var ccpaPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.not.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Do Not Forward' if CCPA is 'Present' is selected and user CCPA is not present", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + var ccpaPresent = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it("should perform a cookie sync if 'Do Not Forward' if CCPA is 'Not Present' is selected and user CCPA is present", function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + var ccpaPresent = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + var filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + var consentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(ccpaPresent)); + var user = MockUser(); + user.setConsentState(consentState); + var enabled = mParticle.getInstance()._Consent.isEnabledForUserConsent(filteringConsentRuleValues, user); + enabled.should.be.ok(); + done(); + }); + it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when accepting consent is required', function (done) { + var includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + pixelSettings.filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.testMPID.should.not.have.property('csd'); + var falseConsentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(false)); + mParticle.Identity.getCurrentUser().setConsentState(falseConsentState); + setTimeout(function () { + var noCookieSyncLS = mParticle.getInstance()._Persistence.getLocalStorage(); + noCookieSyncLS.testMPID.should.not.have.property('csd'); + var trueConsentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(trueConsentState); + setTimeout(function () { + var cookieSyncLS = mParticle.getInstance()._Persistence.getLocalStorage(); + cookieSyncLS.testMPID.should.have.property('csd'); + cookieSyncLS.testMPID.csd.should.have.property(5); + done(); + }, timeout); + }, timeout); + }, timeout); + }); + it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when consent is rejected', function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + pixelSettings.filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('1' + 'foo purpose 1'), + hasConsented: consented + }] + }; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.testMPID.should.not.have.property('csd'); + var falseConsentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(false)); + mParticle.Identity.getCurrentUser().setConsentState(falseConsentState); + setTimeout(function () { + var newLocalStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + newLocalStorage.testMPID.should.not.have.property('csd'); + var trueConsentState = mParticle.getInstance().Consent.createConsentState().addGDPRConsentState('foo purpose 1', mParticle.getInstance().Consent.createGDPRConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(trueConsentState); + setTimeout(function () { + newLocalStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + newLocalStorage.testMPID.should.have.property('csd'); + newLocalStorage.testMPID.csd.should.have.property(5); + done(); + }, timeout); + }, timeout); + }, timeout); + }); + it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when accepting consent is required', function (done) { + var includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + pixelSettings.filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.testMPID.should.not.have.property('csd'); + var falseConsentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState( + // false to show that it doesn't perform a cookie sync + mParticle.getInstance().Consent.createCCPAConsent(false)); + mParticle.Identity.getCurrentUser().setConsentState(falseConsentState); + setTimeout(function () { + var noCookieSyncLS = mParticle.getInstance()._Persistence.getLocalStorage(); + noCookieSyncLS.testMPID.should.not.have.property('csd'); + var trueConsentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState( + // false to show that it doesn't perform a cookie sync + mParticle.getInstance().Consent.createCCPAConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(trueConsentState); + setTimeout(function () { + var cookieSyncLS = mParticle.getInstance()._Persistence.getLocalStorage(); + cookieSyncLS.testMPID.should.have.property('csd'); + cookieSyncLS.testMPID.csd.should.have.property(5); + done(); + }, timeout); + }, timeout); + }, timeout); + }); + it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when consent is rejected', function (done) { + var includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config + var consented = false; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + pixelSettings.filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; + window.mParticle.config.pixelConfigs = [pixelSettings]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.testMPID.should.not.have.property('csd'); + var falseConsentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(false)); + mParticle.Identity.getCurrentUser().setConsentState(falseConsentState); + setTimeout(function () { + var newLocalStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + newLocalStorage.testMPID.should.not.have.property('csd'); + var trueConsentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(trueConsentState); + setTimeout(function () { + newLocalStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + newLocalStorage.testMPID.should.have.property('csd'); + newLocalStorage.testMPID.csd.should.have.property(5); + done(); + }, timeout); + }, timeout); + }, timeout); + }); + it('should allow some cookie syncs to occur and others to not occur if there are multiple pixels with varying consent levels', function (done) { + // This test has 2 pixelSettings. pixelSettings1 requires consent pixelSettings2 does not. When mparticle initializes, the pixelSettings2 should fire and pixelSettings1 shouldn't. + // After the appropriate consent is saved to the huser, pixelSettings1 will fire. + + var includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config + var consented = true; + mParticle._resetForTests(MPConfig); + mParticle.config.isDevelopmentMode = false; + + // pixelSetting1 has consent required, and so should only perform a cookiesync after consent is saved to the user + var pixelSettings1 = { + name: 'TestPixel', + moduleId: 1, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }; + pixelSettings1.filteringConsentRuleValues = { + includeOnMatch: includeOnMatch, + values: [{ + consentPurpose: mParticle.generateHash('2' + 'data_sale_opt_out'), + hasConsented: consented + }] + }; - // Not caching existence of `window` and related properties due to potential - // for `window` to be unset before tests in quasi-browser environments. - if (typeof window === 'object' && window !== null) { - /* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/browsers.html#location) - * WhatWG HTML$7.7.3 - The `Location` interface - * Test: `Object.prototype.toString.call(window.location)`` - * - IE <=11 === "[object Object]" - * - IE Edge <=13 === "[object Object]" - */ - if (typeof window.location === 'object' && obj === window.location) { - return 'Location'; - } + // pixelSetting2 does not have any consent required, and so should always perform a cookiesync + var pixelSettings2 = { + name: 'TestPixel2', + moduleId: 2, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: '', + redirectUrl: '' + }; + window.mParticle.config.pixelConfigs = [pixelSettings1, pixelSettings2]; + mParticle.init(apiKey, window.mParticle.config); + setTimeout(function () { + var localStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + localStorage.testMPID.should.have.property('csd'); + + // Performs a cookie sync for 2 but not 1 + localStorage.testMPID.csd.should.not.have.property(1); + localStorage.testMPID.csd.should.have.property(2); + var trueConsentState = mParticle.getInstance().Consent.createConsentState().setCCPAConsentState(mParticle.getInstance().Consent.createCCPAConsent(true)); + mParticle.Identity.getCurrentUser().setConsentState(trueConsentState); + setTimeout(function () { + var newLocalStorage = mParticle.getInstance()._Persistence.getLocalStorage(); + newLocalStorage.testMPID.should.have.property('csd'); + // Now has both cookie syncs because the appropriate consent was added + newLocalStorage.testMPID.csd.should.have.property(2); + newLocalStorage.testMPID.csd.should.have.property(1); + done(); + }, timeout); + }, timeout); + }); + }); - /* ! Spec Conformance - * (https://html.spec.whatwg.org/#document) - * WhatWG HTML$3.1.1 - The `Document` object - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * WhatWG HTML states: - * > For historical reasons, Window objects must also have a - * > writable, configurable, non-enumerable property named - * > HTMLDocument whose value is the Document interface object. - * Test: `Object.prototype.toString.call(document)`` - * - Chrome === "[object HTMLDocument]" - * - Firefox === "[object HTMLDocument]" - * - Safari === "[object HTMLDocument]" - * - IE <=10 === "[object Document]" - * - IE 11 === "[object HTMLDocument]" - * - IE Edge <=13 === "[object HTMLDocument]" - */ - if (typeof window.document === 'object' && obj === window.document) { - return 'Document'; - } + var findEventFromRequest$2 = TestsCore.findEventFromRequest, + findBatch$2 = TestsCore.findBatch, + getLocalStorage$1 = TestsCore.getLocalStorage, + MockForwarder$1 = TestsCore.MockForwarder; + var mockServer$6; + describe('identities and attributes', function () { + beforeEach(function () { + mockServer$6 = sinon$1.createFakeServer(); + mockServer$6.respondImmediately = true; + client.post(urls.events, 200); + mockServer$6.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$6.restore(); + client.restore(); + }); + it('should set user attribute', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$1(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('gender', 'male'); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('gender', 'male'); + done(); + }); + it('should set user attribute be case insensitive', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$1(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'female'); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('gender', 'female'); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('gender', 'female'); + event.user_attributes.should.not.have.property('Gender'); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'male'); + mParticle.logEvent('test user attributes2'); + var event2 = findBatch$2(client._calls, 'test user attributes2'); + event2.user_attributes.should.have.property('Gender', 'male'); + event2.user_attributes.should.not.have.property('gender'); + cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('Gender', 'male'); + done(); + }); + it('should set multiple user attributes with setUserAttributes', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$1(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributes({ + gender: 'male', + age: 21 + }); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('gender', 'male'); + cookies[testMPID].ua.should.have.property('age', 21); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('gender', 'male'); + event.user_attributes.should.have.property('age', 21); + done(); + }); + it('should remove user attribute', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$1(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().removeUserAttribute('gender'); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + event.user_attributes.should.not.have.property('gender'); + var cookies = getLocalStorage$1(); + Should(cookies[testMPID].ua).not.be.ok(); + done(); + }); + it('should remove user attribute case insensitive', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder$1(); + mockForwarder.register(window.mParticle.config); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'male'); + mParticle.Identity.getCurrentUser().removeUserAttribute('gender'); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + event.user_attributes.should.not.have.property('Gender'); + var cookies = getLocalStorage$1(); + Should(cookies[testMPID].ua).not.be.ok(); + done(); + }); + it('should set session attribute', function (done) { + mParticle.setSessionAttribute('name', 'test'); + mParticle.logEvent('test event'); + var event = findEventFromRequest$2(client._calls, 'test event'); + Should(event.data.custom_attributes).equal(null); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$2(client._calls, 'session_end'); + sessionEndEvent.data.custom_attributes.should.have.property('name', 'test'); + done(); + }); + it('should set session attribute case insensitive', function (done) { + mParticle.setSessionAttribute('name', 'test'); + mParticle.setSessionAttribute('Name', 'test1'); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$2(client._calls, 'session_end'); + sessionEndEvent.data.custom_attributes.should.have.property('name', 'test1'); + sessionEndEvent.data.custom_attributes.should.not.have.property('Name'); + done(); + }); + it("should not set a session attribute's key as an object or array)", function (done) { + mParticle.setSessionAttribute({ + key: 'value' + }, 'test'); + mParticle.endSession(); + var sessionEndEvent1 = findEventFromRequest$2(client._calls, 'session_end'); + mParticle.startNewSession(); + client._calls = []; + mParticle.setSessionAttribute(['test'], 'test'); + mParticle.endSession(); + var sessionEndEvent2 = findEventFromRequest$2(client._calls, 'session_end'); + Object.keys(sessionEndEvent1.data.custom_attributes).length.should.equal(0); + Object.keys(sessionEndEvent2.data.custom_attributes).length.should.equal(0); + done(); + }); + it('should remove session attributes when session ends', function (done) { + mParticle.startNewSession(); + mParticle.setSessionAttribute('name', 'test'); + mParticle.endSession(); + client._calls = []; + mParticle.startNewSession(); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$2(client._calls, 'session_end'); + sessionEndEvent.data.custom_attributes.should.not.have.property('name'); + done(); + }); + it('should set and log position', function (done) { + mParticle.setPosition(34.134103, -118.321694); + mParticle.logEvent('Test Event'); + var event = findEventFromRequest$2(client._calls, 'Test Event'); + event.data.should.have.property('location'); + event.data.location.should.have.property('latitude', 34.134103); + event.data.location.should.have.property('longitude', -118.321694); + done(); + }); + it('should set user tag', function (done) { + mParticle.Identity.getCurrentUser().setUserTag('test'); + mParticle.logEvent('Test Event'); + var event = findBatch$2(client._calls, 'Test Event'); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('test', null); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('test'); + done(); + }); + it('should set user tag case insensitive', function (done) { + mParticle.Identity.getCurrentUser().setUserTag('Test'); + mParticle.Identity.getCurrentUser().setUserTag('test'); + mParticle.logEvent('Test Event'); + var event = findBatch$2(client._calls, 'Test Event'); + event.should.have.property('user_attributes'); + event.user_attributes.should.not.have.property('Test'); + event.user_attributes.should.have.property('test'); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.should.have.property('test'); + done(); + }); + it('should remove user tag', function (done) { + mParticle.Identity.getCurrentUser().setUserTag('test'); + mParticle.Identity.getCurrentUser().removeUserTag('test'); + mParticle.logEvent('test event'); + var event = findBatch$2(client._calls, 'test event'); + event.should.have.property('user_attributes'); + event.user_attributes.should.not.have.property('test'); + var cookies = getLocalStorage$1(); + Should(cookies[testMPID].ua).not.be.ok(); + done(); + }); + it('should remove user tag case insensitive', function (done) { + mParticle.Identity.getCurrentUser().setUserTag('Test'); + mParticle.Identity.getCurrentUser().removeUserTag('test'); + mParticle.logEvent('test event'); + var event = findBatch$2(client._calls, 'test event'); + event.should.have.property('user_attributes'); + event.user_attributes.should.not.have.property('Test'); + var cookies = getLocalStorage$1(); + Should(cookies[testMPID].ua).not.be.ok(); + done(); + }); + it('should set user attribute list', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('numbers', [1, 2, 3, 4, 5]); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.numbers.length.should.equal(5); + done(); + }); + it('should set user attribute list case insensitive', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + mParticle.Identity.getCurrentUser().setUserAttributeList('Numbers', [1, 2, 3, 4, 5, 6]); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + var cookies = getLocalStorage$1(); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('Numbers', [1, 2, 3, 4, 5, 6]); + event.user_attributes.should.not.have.property('numbers'); + cookies[testMPID].ua.Numbers.length.should.equal(6); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + mParticle.logEvent('test user attributes2'); + var event2 = findBatch$2(client._calls, 'test user attributes2'); + var cookies3 = getLocalStorage$1(); + event2.user_attributes.should.have.property('numbers', [1, 2, 3, 4, 5]); + event2.user_attributes.should.not.have.property('Numbers'); + cookies3[testMPID].ua.numbers.length.should.equal(5); + done(); + }); + it('should make a copy of user attribute list', function (done) { + var list = [1, 2, 3, 4, 5]; + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', list); + list.push(6); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + var cookies = getLocalStorage$1(); + cookies[testMPID].ua.numbers.length.should.equal(5); + event.should.have.property('user_attributes'); + event.user_attributes.should.have.property('numbers')["with"].lengthOf(5); + done(); + }); + it('should remove all user attributes', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + mParticle.Identity.getCurrentUser().removeAllUserAttributes(); + mParticle.logEvent('test user attributes'); + var event = findBatch$2(client._calls, 'test user attributes'); + var cookies = getLocalStorage$1(); + event.should.have.property('user_attributes', {}); + Should(cookies[testMPID].ua).not.be.ok(); + done(); + }); + it('should get user attribute lists', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + var userAttributes = mParticle.Identity.getCurrentUser().getUserAttributesLists(); + userAttributes.should.have.property('numbers'); + userAttributes.should.not.have.property('gender'); + done(); + }); + it('should copy when calling get user attribute lists', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + var userAttributes = mParticle.Identity.getCurrentUser().getUserAttributesLists(); + userAttributes['numbers'].push(6); + var userAttributes1 = mParticle.Identity.getCurrentUser().getUserAttributesLists(); + userAttributes1['numbers'].should.have.lengthOf(5); + done(); + }); + it('should copy when calling get user attributes', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [1, 2, 3, 4, 5]); + var userAttributes = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + userAttributes.blah = 'test'; + userAttributes['numbers'].push(6); + var userAttributes1 = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + userAttributes1['numbers'].should.have.lengthOf(5); + userAttributes1.should.not.have.property('blah'); + done(); + }); + it('should get all user attributes', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('test', '123'); + mParticle.Identity.getCurrentUser().setUserAttribute('another test', 'blah'); + var attrs = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + attrs.should.have.property('test', '123'); + attrs.should.have.property('another test', 'blah'); + done(); + }); + it('should not set user attribute list if value is not array', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttributeList('mykey', 1234); + var attrs = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + attrs.should.not.have.property('mykey'); + done(); + }); + it('should not set bad session attribute value', function (done) { + mParticle.setSessionAttribute('name', { + bad: 'bad' + }); + mParticle.endSession(); + var sessionEndEvent = findEventFromRequest$2(client._calls, 'session_end'); + sessionEndEvent.data.custom_attributes.should.not.have.property('name'); + done(); + }); + it('should not set a bad user attribute key or value', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('gender', { + bad: 'bad' + }); + mParticle.logEvent('test bad user attributes1'); + var event1 = findBatch$2(client._calls, 'test bad user attributes1'); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', ['bad', 'bad', 'bad']); + mParticle.logEvent('test bad user attributes2'); + var event2 = findBatch$2(client._calls, 'test bad user attributes2'); + mParticle.Identity.getCurrentUser().setUserAttribute({ + bad: 'bad' + }, 'male'); + mParticle.logEvent('test bad user attributes3'); + var event3 = findBatch$2(client._calls, 'test bad user attributes3'); + mParticle.Identity.getCurrentUser().setUserAttribute(['bad', 'bad', 'bad'], 'female'); + mParticle.logEvent('test bad user attributes4'); + var event4 = findBatch$2(client._calls, 'test bad user attributes4'); + mParticle.Identity.getCurrentUser().setUserAttribute(null, 'female'); + mParticle.logEvent('test bad user attributes5'); + var event5 = findBatch$2(client._calls, 'test bad user attributes5'); + mParticle.Identity.getCurrentUser().setUserAttribute(undefined, 'female'); + mParticle.logEvent('test bad user attributes6'); + var event6 = findBatch$2(client._calls, 'test bad user attributes6'); + event1.should.have.property('user_attributes'); + event1.user_attributes.should.not.have.property('gender'); + event2.should.have.property('user_attributes'); + event2.user_attributes.should.not.have.property('gender'); + event3.should.have.property('user_attributes'); + event3.user_attributes.should.not.have.property('gender'); + event4.should.have.property('user_attributes'); + event4.user_attributes.should.not.have.property('gender'); + event5.should.have.property('user_attributes'); + event5.user_attributes.should.not.have.property('gender'); + event6.should.have.property('user_attributes'); + event6.user_attributes.should.not.have.property('gender'); + done(); + }); + it('should get cart products', function (done) { + var product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), + product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1); + mParticle.eCommerce.Cart.add([product1, product2]); + var cartProducts = mParticle.Identity.getCurrentUser().getCart().getCartProducts(); + cartProducts.length.should.equal(2); + JSON.stringify(cartProducts[0]).should.equal(JSON.stringify(product1)); + JSON.stringify(cartProducts[1]).should.equal(JSON.stringify(product2)); + done(); + }); + it('should send user attribute change requests when setting new attributes', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); - if (typeof window.navigator === 'object') { - /* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) - * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray - * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` - * - IE <=10 === "[object MSMimeTypesCollection]" - */ - if (typeof window.navigator.mimeTypes === 'object' && - obj === window.navigator.mimeTypes) { - return 'MimeTypeArray'; + // set a new attribute, age + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); + var body = JSON.parse(client.lastOptions().body); + body.user_attributes.should.have.property('age', '25'); + var event = body.events[0]; + event.should.be.ok(); + event.event_type.should.equal('user_attribute_change'); + event.data["new"].should.equal('25'); + (event.data.old === null).should.equal(true); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(true); + + // change age attribute + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('age', '30'); + body = JSON.parse(client.lastOptions().body); + body.user_attributes.should.have.property('age', '30'); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + event.data["new"].should.equal('30'); + event.data.old.should.equal('25'); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(false); + + // removes age attribute + client._calls = []; + mParticle.Identity.getCurrentUser().removeUserAttribute('age'); + body = JSON.parse(client.lastOptions().body); + body.user_attributes.should.not.have.property('age'); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + (event.data["new"] === null).should.equal(true); + event.data.old.should.equal('30'); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(true); + event.data.is_new_attribute.should.equal(false); + + // set a user attribute list + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttributeList('age', ['test1', 'test2']); + body = JSON.parse(client.lastOptions().body); + body.user_attributes.age[0].should.equal('test1'); + body.user_attributes.age[1].should.equal('test2'); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + var obj = { + test1: true, + test2: true + }; + event.data["new"].forEach(function (userAttr) { + obj[userAttr].should.equal(true); + }); + (event.data.old === null).should.equal(true); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(true); + + // changes ordering of above attribute list + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttributeList('age', ['test2', 'test1']); + body = JSON.parse(client.lastOptions().body); + body.user_attributes.age[0].should.equal('test2'); + body.user_attributes.age[1].should.equal('test1'); + event = JSON.parse(client.lastOptions().body).events[0]; + event.event_type.should.equal('user_attribute_change'); + obj = { + test1: true, + test2: true + }; + event.data["new"].forEach(function (userAttr) { + obj[userAttr].should.equal(true); + }); + (event.data.old[0] === 'test1').should.equal(true); + (event.data.old[1] === 'test2').should.equal(true); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(false); + delete window.mParticle.config.flags; + done(); + }); + it('should send user attribute change requests for the MPID it is being set on', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, window.mParticle.config); + mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); + var testMPID = mParticle.Identity.getCurrentUser().getMPID(); + var body = JSON.parse(client.lastOptions().body); + body.mpid.should.equal(testMPID); + var event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + event.data["new"].should.equal('25'); + Should(event.data.old).equal(null); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(true); + + // new user logs in + var loginUser = { + userIdentities: { + customerid: 'customerid1' } - - /* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) - * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray - * Test: `Object.prototype.toString.call(navigator.plugins)`` - * - IE <=10 === "[object MSPluginsCollection]" - */ - if (typeof window.navigator.plugins === 'object' && - obj === window.navigator.plugins) { - return 'PluginArray'; + }; + mockServer$6.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'anotherMPID', + is_logged_in: true + })]); + mParticle.Identity.login(loginUser); + var users = mParticle.Identity.getUsers(); + users.length.should.equal(2); + var anotherMPIDUser = users[0]; + var testMPIDUser = users[1]; + anotherMPIDUser.getMPID().should.equal('anotherMPID'); + testMPIDUser.getMPID().should.equal('testMPID'); + anotherMPIDUser.setUserAttribute('age', '30'); + body = JSON.parse(client.lastOptions().body); + event = body.events[0]; + body.mpid.should.equal(anotherMPIDUser.getMPID()); + event.event_type.should.equal('user_attribute_change'); + event.data["new"].should.equal('30'); + Should(event.data.old).equal(null); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(true); + testMPIDUser.setUserAttribute('age', '20'); + body = JSON.parse(client.lastOptions().body); + body.mpid.should.equal(testMPIDUser.getMPID()); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + event.data["new"].should.equal('20'); + event.data.old.should.equal('25'); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(false); + event.data.is_new_attribute.should.equal(false); + + // remove user attribute + anotherMPIDUser.removeUserAttribute('age'); + body = JSON.parse(client.lastOptions().body); + body.mpid.should.equal(anotherMPIDUser.getMPID()); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + Should(event.data["new"]).equal(null); + event.data.old.should.equal('30'); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(true); + event.data.is_new_attribute.should.equal(false); + testMPIDUser.removeUserAttribute('age'); + body = JSON.parse(client.lastOptions().body); + body.mpid.should.equal(testMPIDUser.getMPID()); + event = body.events[0]; + event.event_type.should.equal('user_attribute_change'); + Should(event.data["new"]).equal(null); + event.data.old.should.equal('20'); + event.data.user_attribute_name.should.equal('age'); + event.data.deleted.should.equal(true); + event.data.is_new_attribute.should.equal(false); + delete window.mParticle.config.flags; + done(); + }); + it('should send user identity change requests when setting new identities on new users', function (done) { + mParticle._resetForTests(MPConfig); + client._calls = []; + window.mParticle.config.identifyRequest = { + userIdentities: { + email: 'initial@gmail.com' } - } - - if ((typeof window.HTMLElement === 'function' || - typeof window.HTMLElement === 'object') && - obj instanceof window.HTMLElement) { - /* ! Spec Conformance - * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) - * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` - * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` - * - IE <=10 === "[object HTMLBlockElement]" - */ - if (obj.tagName === 'BLOCKQUOTE') { - return 'HTMLQuoteElement'; + }; + mParticle.init(apiKey, window.mParticle.config); + JSON.parse(client.lastOptions().body).user_identities.should.have.property('email', 'initial@gmail.com'); + mParticle.logEvent('testAfterInit'); + JSON.parse(client.lastOptions().body).user_identities.should.have.property('email', 'initial@gmail.com'); + client.calls().forEach(function (call) { + JSON.parse(call[1].body).user_identities.should.have.property('email', 'initial@gmail.com'); + }); + mockServer$6.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'anotherMPID', + is_logged_in: true + })]); + client._calls = []; + + // anonymous user is in storage, new user logs in + var loginUser = { + userIdentities: { + customerid: 'customerid1' } - - /* ! Spec Conformance - * (https://html.spec.whatwg.org/#htmltabledatacellelement) - * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * Test: Object.prototype.toString.call(document.createElement('td')) - * - Chrome === "[object HTMLTableCellElement]" - * - Firefox === "[object HTMLTableCellElement]" - * - Safari === "[object HTMLTableCellElement]" - */ - if (obj.tagName === 'TD') { - return 'HTMLTableDataCellElement'; + }; + mParticle.Identity.login(loginUser); + var body = JSON.parse(client.lastOptions().body); + // should be the new MPID + + body.mpid.should.equal('anotherMPID'); + body.user_identities.should.have.property('customer_id', 'customerid1'); + body.user_identities.should.not.have.property('email'); + var event = body.events[0]; + event.should.be.ok(); + event.event_type.should.equal('user_identity_change'); + event.data["new"].identity_type.should.equal('customer_id'); + event.data["new"].identity.should.equal('customerid1'); + _typeof(event.data["new"].timestamp_unixtime_ms).should.equal('number'); + event.data["new"].created_this_batch.should.equal(true); + event.data.old.identity_type.should.equal('customer_id'); + (event.data.old.identity === null).should.equal(true); + _typeof(event.data.old.timestamp_unixtime_ms).should.equal('number'); + event.data.old.created_this_batch.should.equal(false); + mParticle.logEvent('testAfterLogin'); + body = JSON.parse(client.lastOptions().body); + body.user_identities.should.have.property('customer_id', 'customerid1'); + body.user_identities.should.not.have.property('email'); + + // change customerid creates an identity change event + var modifyUser = { + userIdentities: { + customerid: 'customerid2' + } + }; + mockServer$6.respondWith('https://identity.mparticle.com/v1/anotherMPID/modify', [200, {}, JSON.stringify({ + mpid: 'anotherMPID', + is_logged_in: true + })]); + mParticle.Identity.modify(modifyUser); + var body2 = JSON.parse(client.lastOptions().body); + body2.mpid.should.equal('anotherMPID'); + body2.user_identities.should.have.property('customer_id', 'customerid2'); + body2.user_identities.should.not.have.property('email'); + var event2 = body2.events[0]; + event2.should.be.ok(); + event2.event_type.should.equal('user_identity_change'); + event2.data["new"].identity_type.should.equal('customer_id'); + event2.data["new"].identity.should.equal('customerid2'); + _typeof(event2.data["new"].timestamp_unixtime_ms).should.equal('number'); + event2.data["new"].created_this_batch.should.equal(false); + event2.data.old.identity_type.should.equal('customer_id'); + event2.data.old.identity.should.equal('customerid1'); + _typeof(event2.data.old.timestamp_unixtime_ms).should.equal('number'); + event2.data.old.created_this_batch.should.equal(false); + + // Adding a new identity to the current user will create an identity change event + var modifyUser2 = { + userIdentities: { + customerid: 'customerid2', + email: 'test@test.com' + } + }; + client._calls = []; + mParticle.Identity.modify(modifyUser2); + var body3 = JSON.parse(client.lastOptions().body); + body3.mpid.should.equal('anotherMPID'); + var event3 = body3.events[0]; + event3.should.be.ok(); + event3.event_type.should.equal('user_identity_change'); + event3.data["new"].identity_type.should.equal('email'); + event3.data["new"].identity.should.equal('test@test.com'); + _typeof(event3.data["new"].timestamp_unixtime_ms).should.equal('number'); + event3.data["new"].created_this_batch.should.equal(true); + event3.data.old.identity_type.should.equal('email'); + (event3.data.old.identity === null).should.equal(true); + _typeof(event3.data.old.timestamp_unixtime_ms).should.equal('number'); + event3.data.old.created_this_batch.should.equal(false); + + // logout with an other will create only a change event for the other + var logoutUser = { + userIdentities: { + other: 'other1' } - - /* ! Spec Conformance - * (https://html.spec.whatwg.org/#htmltableheadercellelement) - * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` - * Note: Most browsers currently adher to the W3C DOM Level 2 spec - * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) - * which suggests that browsers should use HTMLTableCellElement for - * both TD and TH elements. WhatWG separates these. - * Test: Object.prototype.toString.call(document.createElement('th')) - * - Chrome === "[object HTMLTableCellElement]" - * - Firefox === "[object HTMLTableCellElement]" - * - Safari === "[object HTMLTableCellElement]" - */ - if (obj.tagName === 'TH') { - return 'HTMLTableHeaderCellElement'; + }; + client._calls = []; + mockServer$6.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle.Identity.logout(logoutUser); + //only call is for `other` change event, not for previous ID types of email and customerid + client._calls.length.should.equal(1); + var body4 = JSON.parse(client.lastOptions().body); + body4.mpid.should.equal('mpid2'); + var event4 = body4.events[0]; + event4.should.be.ok(); + event4.event_type.should.equal('user_identity_change'); + event4.data["new"].identity_type.should.equal('other'); + event4.data["new"].identity.should.equal('other1'); + _typeof(event4.data["new"].timestamp_unixtime_ms).should.equal('number'); + event4.data["new"].created_this_batch.should.equal(true); + event4.data.old.identity_type.should.equal('other'); + (event4.data.old.identity === null).should.equal(true); + _typeof(event4.data.old.timestamp_unixtime_ms).should.equal('number'); + event4.data.old.created_this_batch.should.equal(false); + mParticle.logEvent('testAfterLogout'); + var body5 = JSON.parse(client.lastOptions().body); + body5.mpid.should.equal('mpid2'); + Object.keys(body5.user_identities).length.should.equal(1); + body5.user_identities.should.have.property('other', 'other1'); + done(); + }); + it('should send historical UIs on batches when MPID changes', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.identifyRequest = { + userIdentities: { + email: 'initial@gmail.com' } - } - } - - /* ! Speed optimisation - * Pre: - * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) - * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) - * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) - * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) - * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) - * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) - * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) - * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) - * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) - * Post: - * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) - * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) - * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) - * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) - * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) - * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) - * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) - * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) - * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) - */ - var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); - if (typeof stringTag === 'string') { - return stringTag; - } - - var objPrototype = Object.getPrototypeOf(obj); - /* ! Speed optimisation - * Pre: - * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) - * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) - * Post: - * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) - * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) - */ - if (objPrototype === RegExp.prototype) { - return 'RegExp'; - } - - /* ! Speed optimisation - * Pre: - * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) - * Post: - * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) - */ - if (objPrototype === Date.prototype) { - return 'Date'; - } - - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) - * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": - * Test: `Object.prototype.toString.call(Promise.resolve())`` - * - Chrome <=47 === "[object Object]" - * - Edge <=20 === "[object Object]" - * - Firefox 29-Latest === "[object Promise]" - * - Safari 7.1-Latest === "[object Promise]" - */ - if (promiseExists && objPrototype === Promise.prototype) { - return 'Promise'; - } + }; + window.mParticle.config.flags = { + EventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, window.mParticle.config); + mockServer$6.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: true + })]); - /* ! Speed optimisation - * Pre: - * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) - * Post: - * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) - */ - if (setExists && objPrototype === Set.prototype) { - return 'Set'; - } + // on identity strategy where MPID remains the same from anonymous to login + var loginUser = { + userIdentities: { + customerid: 'customerid1' + } + }; + mParticle.Identity.login(loginUser); + var batch = JSON.parse(client.lastOptions().body); + batch.mpid.should.equal(testMPID); + batch.user_identities.should.have.property('email', 'initial@gmail.com'); + batch.user_identities.should.have.property('customer_id', 'customerid1'); + var logoutUser = { + userIdentities: { + other: 'other1' + } + }; + mockServer$6.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'mpid2', + is_logged_in: false + })]); + mParticle.Identity.logout(logoutUser); + batch = JSON.parse(client.lastOptions().body); + batch.mpid.should.equal('mpid2'); + batch.user_identities.should.have.property('other', 'other1'); + batch.user_identities.should.not.have.property('email'); + batch.user_identities.should.not.have.property('customer_id'); + client._calls = []; + // log back in with previous MPID, but with only a single UI, all UIs should be on batch + mockServer$6.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: true + })]); + mParticle.Identity.login(loginUser); + + // switching back to logged in user shoudl not result in any UIC events + Should(client.lastOptions()).not.be.ok(); + mParticle.logEvent('event after logging back in'); + batch = JSON.parse(client.lastOptions().body); + batch.mpid.should.equal(testMPID); + batch.user_identities.should.have.property('email', 'initial@gmail.com'); + batch.user_identities.should.have.property('customer_id', 'customerid1'); + done(); + }); + it('should not send user attribute change requests when user attribute already set with same value with false values', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.flags = { + EventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, window.mParticle.config); - /* ! Speed optimisation - * Pre: - * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) - * Post: - * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) - */ - if (mapExists && objPrototype === Map.prototype) { - return 'Map'; - } + // set a new attribute, age + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); + var body1 = JSON.parse(client.lastOptions().body); + body1.user_attributes.should.have.property('age', '25'); + var event1 = body1.events[0]; + event1.should.be.ok(); + event1.event_type.should.equal('user_attribute_change'); + event1.data["new"].should.equal('25'); + (event1.data.old === null).should.equal(true); + event1.data.user_attribute_name.should.equal('age'); + event1.data.deleted.should.equal(false); + event1.data.is_new_attribute.should.equal(true); + + // test setting attributes with 'false' values (i.e false, 0 and '') + + // check for UAC event for testFalse: fasle when set for first time + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testFalse', false); + var body2 = JSON.parse(client.lastOptions().body); + body2.user_attributes.should.have.property('testFalse', false); + var event2 = body2.events[0]; + event2.should.be.ok(); + event2.event_type.should.equal('user_attribute_change'); + event2.data["new"].should.equal(false); + (event2.data.old === null).should.equal(true); + event2.data.user_attribute_name.should.equal('testFalse'); + event2.data.deleted.should.equal(false); + event2.data.is_new_attribute.should.equal(true); + + // check for UAC event for testEmptyString: '' when set for first time + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString', ''); + var body3 = JSON.parse(client.lastOptions().body); + body3.user_attributes.should.have.property('testEmptyString', ''); + var event3 = body3.events[0]; + event3.should.be.ok(); + event3.event_type.should.equal('user_attribute_change'); + event3.data["new"].should.equal(''); + (event3.data.old === null).should.equal(true); + event3.data.user_attribute_name.should.equal('testEmptyString'); + event3.data.deleted.should.equal(false); + event3.data.is_new_attribute.should.equal(true); + + // check for UAC event for testZero: 0 when set for first time + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testZero', 0); + var body4 = JSON.parse(client.lastOptions().body); + body4.user_attributes.should.have.property('testZero', 0); + var event4 = body4.events[0]; + event4.should.be.ok(); + event4.event_type.should.equal('user_attribute_change'); + event4.data["new"].should.equal(0); + (event4.data.old === null).should.equal(true); + event4.data.user_attribute_name.should.equal('testZero'); + event4.data.deleted.should.equal(false); + event4.data.is_new_attribute.should.equal(true); + + // confirm user attributes previously set already exist for user + var userAttributes = mParticle.Identity.getCurrentUser().getAllUserAttributes(); + userAttributes.should.have.property('age'); + userAttributes.should.have.property('testFalse'); + userAttributes.should.have.property('testEmptyString'); + userAttributes.should.have.property('testZero'); + + // re-set all previous attributes with the same values + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); + mParticle.Identity.getCurrentUser().setUserAttribute('testFalse', false); + mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString', ''); + mParticle.Identity.getCurrentUser().setUserAttribute('testZero', 0); + (client.lastOptions() === undefined).should.equal(true); + (client._calls.length === 0).should.equal(true); + done(); + }); + it('should send user attribute change event when setting different falsey values', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.flags = { + EventBatchingIntervalMillis: 0 + }; + mParticle.init(apiKey, window.mParticle.config); - /* ! Speed optimisation - * Pre: - * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) - * Post: - * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) - */ - if (weakSetExists && objPrototype === WeakSet.prototype) { - return 'WeakSet'; - } + // set initial test attribute with 'falsey' value to 0 + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', 0); + var body1 = JSON.parse(client.lastOptions().body); + body1.user_attributes.should.have.property('testFalsey', 0); + var event1 = body1.events[0]; + event1.should.be.ok(); + event1.event_type.should.equal('user_attribute_change'); + event1.data["new"].should.equal(0); + (event1.data.old === null).should.equal(true); + event1.data.user_attribute_name.should.equal('testFalsey'); + event1.data.deleted.should.equal(false); + event1.data.is_new_attribute.should.equal(true); + + // re-set same test attribute with 'falsey' value to '' + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', ''); + var body2 = JSON.parse(client.lastOptions().body); + body2.user_attributes.should.have.property('testFalsey', ''); + var event2 = body2.events[0]; + event2.should.be.ok(); + event2.event_type.should.equal('user_attribute_change'); + event2.data["new"].should.equal(''); + event2.data.old.should.equal(0); + event2.data.user_attribute_name.should.equal('testFalsey'); + event2.data.deleted.should.equal(false); + event2.data.is_new_attribute.should.equal(false); + + // re-set same test attribute with 'falsey' value to false + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', false); + var body3 = JSON.parse(client.lastOptions().body); + body3.user_attributes.should.have.property('testFalsey', false); + var event3 = body3.events[0]; + event3.should.be.ok(); + event3.event_type.should.equal('user_attribute_change'); + event3.data["new"].should.equal(false); + event3.data.old.should.equal(''); + event3.data.user_attribute_name.should.equal('testFalsey'); + event3.data.deleted.should.equal(false); + event3.data.is_new_attribute.should.equal(false); + + // re-set same test attribute with 'falsey' value to original value 0 + client._calls = []; + mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', 0); + var body4 = JSON.parse(client.lastOptions().body); + body4.user_attributes.should.have.property('testFalsey', 0); + var event4 = body4.events[0]; + event4.should.be.ok(); + event4.event_type.should.equal('user_attribute_change'); + event4.data["new"].should.equal(0); + event4.data.old.should.equal(false); + event4.data.user_attribute_name.should.equal('testFalsey'); + event4.data.deleted.should.equal(false); + event4.data.is_new_attribute.should.equal(false); + done(); + }); + }); - /* ! Speed optimisation - * Pre: - * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) - * Post: - * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) - */ - if (weakMapExists && objPrototype === WeakMap.prototype) { - return 'WeakMap'; - } + var getLocalStorage = TestsCore.getLocalStorage, + mParticleIOS = TestsCore.mParticleIOS, + mParticleAndroid = TestsCore.mParticleAndroid, + HTTPCodes = Constants.HTTPCodes; + describe('native-sdk methods', function () { + describe('Helper methods', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + delete window.mParticleAndroid_bridgeName_v2; + delete window.webkit; + delete window.mParticle.uiwebviewBridgeName; + delete mParticle.requiredWebviewBridgeName; + delete mParticle.minWebviewBridgeVersion; + delete mParticle.isIOS; + mParticle.init(apiKey, window.mParticle.config); + mParticle.config = {}; + window.mParticleAndroid = null; + window.mParticle.isIOS = null; + }); + after(function () { + delete window.mParticleAndroid_bridgeName_v2; + delete window.webkit; + delete window.mParticle.uiwebviewBridgeName; + delete mParticle.requiredWebviewBridgeName; + delete mParticle.minWebviewBridgeVersion; + delete mParticle.isIOS; + }); + it('isBridgeV2Available returns false if no bridges exist on window', function (done) { + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false); + done(); + }); + it('isBridgeV2Available returns true if iOS bridge messageHandler bridge exists on window', function (done) { + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false); + window.webkit = { + messageHandlers: { + mParticle_bridgeName_v2: { + postMessage: null + } + } + }; + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true); + delete window.webkit; + done(); + }); + it('isBridgeV2Available returns true if iOS bridge nonMessageHandler bridge exists on window', function (done) { + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false); + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true); + delete window.webkit; + done(); + }); + it('isBridgeV2Available returns true if Android bridge exists on window', function (done) { + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(false); + window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); + mParticle.getInstance()._NativeSdkHelpers.isBridgeV2Available('bridgeName').should.equal(true); + delete window.mParticleAndroid_bridgeName_v2; + done(); + }); + it('isWebviewEnabled returns true if there is no v2Bridge, and minWebviewBridgeVersion is 1, and v1 bridge is available', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 1; + mParticle.config.isIOS = true; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', window.mParticle.config.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is an Android bridge, minWebviewBridgeVersion is 2', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + mParticle.init(apiKey, window.mParticle.config); + + // window.mParticle.config.minWebviewBridgeVersion = 2; + window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', window.mParticle.config.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is an iOS bridge, minWebviewBridgeVersion is 2', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + window.webkit = { + messageHandlers: { + mParticle_bridgeName_v2: { + postMessage: null + } + } + }; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', window.mParticle.config.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', function (done) { + mParticle.minWebviewBridgeVersion = 2; + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', function (done) { + mParticle.minWebviewBridgeVersion = 2; + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns false if there is a v1 Android bridge, and minWebviewBridgeVersion is 2', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + mParticle.init(apiKey, window.mParticle.config); + window.mParticleAndroid = new mParticleAndroid(); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', window.mParticle.config.minWebviewBridgeVersion).should.equal(false); + done(); + }); + it('isWebviewEnabled returns false if there is a v1 iOS bridge, and minWebviewBridgeVersion is 2', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + mParticle.init(apiKey, window.mParticle.config); + mParticle.isIOS = true; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', window.mParticle.config.minWebviewBridgeVersion).should.equal(false); + delete mParticle.isIOS; + done(); + }); + it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.webkit = { + messageHandlers: { + mParticle_bridgeName_v2: { + postMessage: null + } + } + }; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + delete mParticle.isIOS; + done(); + }); + it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.webkit = { + messageHandlers: { + mParticle_bridgeName_v2: { + postMessage: null + } + } + }; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function (done) { + mParticle.minWebviewBridgeVersion = 1; + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled('bridgeName', mParticle.minWebviewBridgeVersion).should.equal(true); + done(); + }); + it('isWebviewEnabled returns false if there is an unmatched requiredWebviewBridgeName, even if bridge 1 exists and min version is 1', function (done) { + mParticle.minWebviewBridgeVersion = 1; + mParticle.requiredWebviewBridgeName = 'nonmatching'; + window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; + mParticle.isIOS = true; + mParticle.getInstance()._NativeSdkHelpers.isWebviewEnabled(mParticle.requiredWebviewBridgeName, mParticle.minWebviewBridgeVersion).should.equal(false); + delete mParticle.isIOS; + done(); + }); + }); + describe('bridge version 1', function () { + beforeEach(function () { + mParticle._resetForTests(MPConfig); + window.mParticleAndroid = null; + window.mParticle.isIOS = null; + window.mParticleAndroid = new mParticleAndroid(); + window.mParticle.config.minWebviewBridgeVersion = 1; + mParticle.init(apiKey, window.mParticle.config); + }); + it('should set mParitcle._Store.SDKConfig.isIOS to true when mParticle.isIOS is true', function (done) { + mParticle._resetForTests(MPConfig); + mParticle.isIOS = true; + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._Store.SDKConfig.isIOS.should.equal(true); + done(); + }); + it('invoke setSessionAttributes of $src_key/$src_env of apikey/\'webview\' to the Android\'s on init if apiKey is available', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticleAndroid = new mParticleAndroid(); + window.mParticle.init(apiKey, window.mParticle.config); + window.mParticleAndroid.sessionAttrData.length.should.equal(2); + JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('key', '$src_env'); + JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('value', 'webview'); + JSON.parse(window.mParticleAndroid.sessionAttrData[1]).should.have.property('key', '$src_key'); + JSON.parse(window.mParticleAndroid.sessionAttrData[1]).should.have.property('value', apiKey); + done(); + }); + it('invoke only setSessionAttributes of $src_key/$src_env if apikey is missing from webview', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticleAndroid = new mParticleAndroid(); + window.mParticle.init(null, window.mParticle.config); + window.mParticleAndroid.sessionAttrData.length.should.equal(1); + JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('key', '$src_env'); + JSON.parse(window.mParticleAndroid.sessionAttrData[0]).should.have.property('value', 'webview'); + done(); + }); + it('should invoke setSessionAttributes on Android and pass through proper data', function (done) { + window.mParticleAndroid.resetSessionAttrData(); + mParticle.setSessionAttribute('key', 'value'); + window.mParticleAndroid.setSessionAttributeCalled.should.equal(true); + window.mParticleAndroid.sessionAttrData[0].should.equal(JSON.stringify({ + key: 'key', + value: 'value' + })); + done(); + }); + it('should invoke logEvent on Android and pass through proper event', function (done) { + mParticle.logEvent('testEvent'); + window.mParticleAndroid.logEventCalled.should.equal(true); + _typeof(window.mParticleAndroid.event).should.equal('string'); + JSON.parse(window.mParticleAndroid.event).should.have.properties(['EventName', 'EventCategory', 'EventAttributes', 'EventDataType', 'OptOut']); + done(); + }); + it('should invoke setAttribute on Android and pass through proper data', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + window.mParticleAndroid.setUserAttributeCalled.should.equal(true); + window.mParticleAndroid.userAttrData[0].should.equal(JSON.stringify({ + key: 'key', + value: 'value' + })); + window.mParticleAndroid.resetUserAttributes(); + done(); + }); + it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', function (done) { + mParticle.Identity.getCurrentUser().setUserAttributes({ + gender: 'male', + age: 21 + }); + window.mParticleAndroid.setUserAttributeCalled.should.equal(true); + window.mParticleAndroid.userAttrData[0].should.equal(JSON.stringify({ + key: 'gender', + value: 'male' + })); + window.mParticleAndroid.userAttrData[1].should.equal(JSON.stringify({ + key: 'age', + value: 21 + })); + done(); + }); + it('should invoke removeAttributes on native SDK', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + mParticle.Identity.getCurrentUser().removeUserAttribute('key'); + window.mParticleAndroid.setUserAttributeCalled.should.equal(true); + window.mParticleAndroid.removeUserAttributeCalled.should.equal(true); + done(); + }); - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) - * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": - * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` - * - Edge <=13 === "[object Object]" - */ - if (dataViewExists && objPrototype === DataView.prototype) { - return 'DataView'; - } + // TBD _ ask will/peter about add to cart array vs product? + it('should invoke native sdk method addToCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + var product2 = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.add(product); + window.mParticleAndroid.should.have.property('addToCartCalled', true); + window.mParticleAndroid.addedToCartItem.should.equal(JSON.stringify([product])); + window.mParticleAndroid.clearCart(); + mParticle.eCommerce.Cart.add([product, product2]); + window.mParticleAndroid.addedToCartItem.should.equal(JSON.stringify([product, product2])); + done(); + }); + it('should invoke native sdk method removeFromCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.add(product); + mParticle.eCommerce.Cart.remove(product); + window.mParticleAndroid.should.have.property('removeFromCartCalled', true); + window.mParticleAndroid.removedFromCartItem.should.equal(JSON.stringify(product)); + done(); + }); + it('should invoke native sdk method clearCart', function (done) { + mParticle.eCommerce.Cart.clear(); + window.mParticleAndroid.should.have.property('clearCartCalled', true); + done(); + }); + it('should not sync cookies when in a mobile web view for Android', function (done) { + var pixelSettings = { + name: 'AdobeEventForwarder', + moduleId: 5, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: 'http://www.yahoo.com', + redirectUrl: '' + }; + mParticle.configurePixel(pixelSettings); + mParticle.init(apiKey, window.mParticle.config); + var data = getLocalStorage(); + Should(data).not.be.ok(); + done(); + }); + it('should send a JSON object to the native SDK\'s Identity methods', function (done) { + var result, + identityAPIRequest = { + userIdentities: { + customerid: '123', + email: 'test@gmail.com' + } + }; + var callback = function callback(resp) { + result = resp; + }; + mParticle.Identity.login(identityAPIRequest, callback); + result.body.should.equal('Login request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.logout(identityAPIRequest, callback); + result.body.should.equal('Logout request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.modify(identityAPIRequest, callback); + result.body.should.equal('Modify request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.identify(identityAPIRequest, callback); + result.body.should.equal('Identify request sent to native sdk'); + result.httpCode.should.equal(-5); + var JSONData = JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest)); + window.mParticleAndroid.loginData.should.equal(JSONData); + window.mParticleAndroid.logoutData.should.equal(JSONData); + window.mParticleAndroid.modifyData.should.equal(JSONData); + done(); + }); + it('should send events via the mParticle.ready method ', function (done) { + mParticle.ready(function () { + mParticle.logEvent('test'); + }); + window.mParticleAndroid.logEventCalled.should.equal(true); + JSON.parse(window.mParticleAndroid.event).EventName.should.equal('test'); + done(); + }); + }); + describe('bridge version 2', function () { + describe('android', function () { + var mParticleAndroidV2Bridge; + beforeEach(function () { + window.mParticleAndroid = null; + window.mParticle.isIOS = null; + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + window.mParticle.config.requiredWebviewBridgeName = 'bridgeName'; + window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); + mParticleAndroidV2Bridge = window.mParticleAndroid_bridgeName_v2; + window.mParticle.init(apiKey, window.mParticle.config); + mParticle.config = {}; + }); + afterEach(function () { + delete window.mParticle.config; + delete window.mParticleAndroid_bridgeName_v2; + }); + it('should invoke logEvent on Android and pass through proper event', function (done) { + mParticle.logEvent('testEvent'); + mParticleAndroidV2Bridge.logEventCalled.should.equal(true); + _typeof(mParticleAndroidV2Bridge.event).should.equal('string'); + JSON.parse(mParticleAndroidV2Bridge.event).should.have.properties(['EventName', 'EventCategory', 'EventAttributes', 'EventDataType', 'OptOut']); + done(); + }); + it('should invoke setAttribute on Android and pass through proper data', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true); + mParticleAndroidV2Bridge.userAttrData[0].should.equal(JSON.stringify({ + key: 'key', + value: 'value' + })); + mParticleAndroidV2Bridge.resetUserAttributes(); + done(); + }); + it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', function (done) { + mParticle.Identity.getCurrentUser().setUserAttributes({ + gender: 'male', + age: 21 + }); + mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true); + mParticleAndroidV2Bridge.userAttrData[0].should.equal(JSON.stringify({ + key: 'gender', + value: 'male' + })); + mParticleAndroidV2Bridge.userAttrData[1].should.equal(JSON.stringify({ + key: 'age', + value: 21 + })); + mParticleAndroidV2Bridge.resetUserAttributes(); + done(); + }); + it('should invoke removeAttributes on Android', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + mParticle.Identity.getCurrentUser().removeUserAttribute('key'); + mParticleAndroidV2Bridge.setUserAttributeCalled.should.equal(true); + mParticleAndroidV2Bridge.removeUserAttributeCalled.should.equal(true); + done(); + }); + it('should invoke setSessionAttributes on Android and pass through proper data', function (done) { + mParticle.setSessionAttribute('key', 'value'); + mParticleAndroidV2Bridge.setSessionAttributeCalled.should.equal(true); + mParticleAndroidV2Bridge.sessionAttrData[2].should.equal(JSON.stringify({ + key: 'key', + value: 'value' + })); + done(); + }); + it('should invoke Android method addToCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + var product2 = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.add(product); + mParticleAndroidV2Bridge.should.have.property('addToCartCalled', true); + mParticleAndroidV2Bridge.addedToCartItem.should.equal(JSON.stringify([product])); + mParticleAndroidV2Bridge.clearCart(); + mParticle.eCommerce.Cart.add([product, product2]); + mParticleAndroidV2Bridge.addedToCartItem.should.equal(JSON.stringify([product, product2])); + done(); + }); + it('should invoke Android method removeFromCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.add(product); + mParticle.eCommerce.Cart.remove(product); + mParticleAndroidV2Bridge.should.have.property('removeFromCartCalled', true); + mParticleAndroidV2Bridge.removedFromCartItem.should.equal(JSON.stringify(product)); + mParticleAndroidV2Bridge.should.have.property('removeFromCartCalled', true); + done(); + }); + it('should invoke Android method clearCart', function (done) { + mParticle.eCommerce.Cart.clear(); + mParticleAndroidV2Bridge.should.have.property('clearCartCalled', true); + done(); + }); + it('should not sync cookies when in a mobile web view for Android', function (done) { + var pixelSettings = { + name: 'AdobeEventForwarder', + moduleId: 5, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: 'http://www.yahoo.com', + redirectUrl: '' + }; + mParticle.configurePixel(pixelSettings); + var data = getLocalStorage(); + Should(data).not.be.ok(); + done(); + }); + it('should send a JSON object to the Android\'s Identity methods', function (done) { + var result, + identityAPIRequest = { + userIdentities: { + customerid: '123', + email: 'test@gmail.com' + } + }; + var callback = function callback(resp) { + result = resp; + }; + mParticle.Identity.login(identityAPIRequest, callback); + result.body.should.equal('Login request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.logout(identityAPIRequest, callback); + result.body.should.equal('Logout request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.modify(identityAPIRequest, callback); + result.body.should.equal('Modify request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + mParticle.Identity.identify(identityAPIRequest, callback); + result.body.should.equal('Identify request sent to native sdk'); + result.httpCode.should.equal(-5); + var JSONData = JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest)); + mParticleAndroidV2Bridge.loginData.should.equal(JSONData); + mParticleAndroidV2Bridge.logoutData.should.equal(JSONData); + mParticleAndroidV2Bridge.modifyData.should.equal(JSONData); + done(); + }); + it('should send a JSON object to the Android\'s Alias method', function (done) { + var callbackResult; + var aliasRequest = { + destinationMpid: '101', + sourceMpid: '202', + startTime: 300, + endTime: 400 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + mParticleAndroidV2Bridge.aliasUsers.should.equal('{"DestinationMpid":"101","SourceMpid":"202","StartUnixtimeMs":300,"EndUnixtimeMs":400}'); + callbackResult.httpCode.should.equal(HTTPCodes.nativeIdentityRequest); + callbackResult.message.should.equal('Alias request sent to native sdk'); + done(); + }); + it('should send events via the mParticle.ready method ', function (done) { + mParticle.ready(function () { + mParticle.logEvent('test'); + }); + mParticleAndroidV2Bridge.logEventCalled.should.equal(true); + JSON.parse(mParticleAndroidV2Bridge.event).EventName.should.equal('test'); + done(); + }); + it('should send an event with a product list when calling logPurchase', function (done) { + var product = mParticle.eCommerce.createProduct('product1', 'sku', 10, 1); + var product2 = mParticle.eCommerce.createProduct('product2', 'sku', 10, 1); + mParticle.eCommerce.Cart.add([product, product2]); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('TAid1', 'aff1', 'coupon', 1798, 10, 5); + var clearCartBoolean = true; + var customAttributes = { + value: 10 + }; + var customFlags = { + foo: 'bar' + }; + mParticleAndroidV2Bridge.data = []; + mParticle.eCommerce.logPurchase(transactionAttributes, [product, product2], clearCartBoolean, customAttributes, customFlags); + JSON.parse(mParticleAndroidV2Bridge.event).ProductAction.ProductList[0].Name.should.equal('product1'); + JSON.parse(mParticleAndroidV2Bridge.event).ProductAction.ProductList[1].Name.should.equal('product2'); + done(); + }); + it('should invoke upload on native SDK', function (done) { + mParticle.upload(); + mParticleAndroidV2Bridge.uploadCalled.should.equal(true); + done(); + }); + }); + describe('iOS', function () { + var mParticleIOSV2Bridge; + beforeEach(function () { + window.mParticleAndroid = null; + window.mParticle.isIOS = null; + mParticle._resetForTests(MPConfig); + window.mParticle.config.minWebviewBridgeVersion = 2; + window.mParticle.config.requiredWebviewBridgeName = 'bridgeName'; + window.webkit = { + messageHandlers: { + mParticle_bridgeName_v2: new mParticleIOS() + } + }; + mParticleIOSV2Bridge = window.webkit.messageHandlers.mParticle_bridgeName_v2; + mParticle.enableWebviewBridge = true; + window.mParticle.init(apiKey, window.mParticle.config); + mParticle.config = {}; + mParticleIOSV2Bridge.reset(); + }); + afterEach(function () { + delete window.webkit; + delete mParticle.requiredWebviewBridgeName; + delete mParticle.enableWebviewBridge; + }); + it('should invoke logEvent on iOS SDK and pass through proper event', function (done) { + mParticle.logEvent('testEvent'); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('logEvent'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.properties(['EventName', 'EventCategory', 'EventAttributes', 'EventDataType', 'OptOut']); + done(); + }); + it('should invoke setAttribute on iOS SDK and pass through proper data', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key', 'key'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value', 'value'); + done(); + }); + it('should invoke setAttribute on iOS SDK and pass through proper data when invoking setUserAttributes', function (done) { + mParticle.Identity.getCurrentUser().setUserAttributes({ + gender: 'male', + age: 21 + }); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key', 'gender'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value', 'male'); + JSON.parse(mParticleIOSV2Bridge.data[1]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[1]).path.should.equal('setUserAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('key', 'age'); + JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('value', 21); + done(); + }); + it('should invoke removeAttributes on iOS SDK', function (done) { + mParticle.Identity.getCurrentUser().setUserAttribute('key', 'value'); + mParticle.Identity.getCurrentUser().removeUserAttribute('key'); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setUserAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key', 'key'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value', 'value'); + JSON.parse(mParticleIOSV2Bridge.data[1]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[1]).path.should.equal('removeUserAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('key', 'key'); + JSON.parse(mParticleIOSV2Bridge.data[1]).value.should.have.property('value', null); + done(); + }); + it('should invoke setSessionAttributes on ios SDK and pass through proper data', function (done) { + mParticle.setSessionAttribute('key', 'value'); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('setSessionAttribute'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('key', 'key'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('value', 'value'); + done(); + }); + it('should invoke ios sdk method addToCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + var product2 = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.add(product); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart'); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product])); + mParticleIOSV2Bridge.reset(); + mParticle.eCommerce.Cart.add([product, product2]); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart'); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product, product2])); + done(); + }); + it('should invoke ios sdk method removeFromCart', function (done) { + var product = mParticle.eCommerce.createProduct('name', 'sku', 10, 1); + mParticle.eCommerce.Cart.remove(product); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('removeFromCart'); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify(product)); + done(); + }); + it('should invoke ios sdk method clearCart', function (done) { + mParticle.eCommerce.Cart.clear(); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('clearCart'); + done(); + }); + it('should not sync cookies when in a mobile web view', function (done) { + var pixelSettings = { + name: 'AdobeEventForwarder', + moduleId: 5, + esId: 24053, + isDebug: true, + isProduction: true, + settings: {}, + frequencyCap: 14, + pixelUrl: 'http://www.yahoo.com', + redirectUrl: '' + }; + mParticle.configurePixel(pixelSettings); + var data = getLocalStorage(); + Should(data).not.be.ok(); + done(); + }); + it('should send a JSON object to the ios SDK\'s Identity methods', function (done) { + var result, + identityAPIRequest = { + userIdentities: { + customerid: '123', + email: 'test@gmail.com' + } + }; + var callback = function callback(resp) { + result = resp; + }; + var JSONData = JSON.stringify(mParticle.getInstance()._Identity.IdentityRequest.convertToNative(identityAPIRequest)); + mParticle.Identity.login(identityAPIRequest, callback); + result.body.should.equal('Login request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData); + mParticleIOSV2Bridge.reset(); + mParticle.Identity.logout(identityAPIRequest, callback); + result.body.should.equal('Logout request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData); + mParticleIOSV2Bridge.reset(); + mParticle.Identity.modify(identityAPIRequest, callback); + result.body.should.equal('Modify request sent to native sdk'); + result.httpCode.should.equal(-5); + result = null; + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData); + mParticleIOSV2Bridge.reset(); + mParticle.Identity.identify(identityAPIRequest, callback); + result.body.should.equal('Identify request sent to native sdk'); + result.httpCode.should.equal(-5); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSONData); + mParticleIOSV2Bridge.reset(); + done(); + }); + it('should send a JSON object to the iOS SDK\'s Alias method', function (done) { + var callbackResult; + var aliasRequest = { + destinationMpid: '101', + sourceMpid: '202', + startTime: 300, + endTime: 400 + }; + mParticle.Identity.aliasUsers(aliasRequest, function (callback) { + callbackResult = callback; + }); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('aliasUsers'); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal('{"DestinationMpid":"101","SourceMpid":"202","StartUnixtimeMs":300,"EndUnixtimeMs":400}'); + mParticleIOSV2Bridge.reset(); + callbackResult.httpCode.should.equal(HTTPCodes.nativeIdentityRequest); + callbackResult.message.should.equal('Alias request sent to native sdk'); + done(); + }); + it('should send events via the mParticle.ready method ', function (done) { + mParticle.ready(function () { + mParticle.logEvent('test'); + }); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.should.have.property('EventName', 'test'); + done(); + }); + it('should send an event with a product list when calling logPurchase', function (done) { + var product = mParticle.eCommerce.createProduct('product1', 'sku', 10, 1); + var product2 = mParticle.eCommerce.createProduct('product2', 'sku', 10, 1); + mParticle.eCommerce.Cart.add([product, product2]); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('addToCart'); + JSON.stringify(JSON.parse(mParticleIOSV2Bridge.data[0]).value).should.equal(JSON.stringify([product, product2])); + var transactionAttributes = mParticle.eCommerce.createTransactionAttributes('TAid1', 'aff1', 'coupon', 1798, 10, 5); + var clearCartBoolean = true; + var customAttributes = { + value: 10 + }; + var customFlags = { + foo: 'bar' + }; + mParticleIOSV2Bridge.data = []; + mParticle.eCommerce.logPurchase(transactionAttributes, [product, product2], clearCartBoolean, customAttributes, customFlags); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('logEvent'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList.length.should.equal(2); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList[0].Name.should.equal('product1'); + JSON.parse(mParticleIOSV2Bridge.data[0]).value.ProductAction.ProductList[1].Name.should.equal('product2'); + done(); + }); + it('should invoke upload on iOS SDK', function (done) { + mParticle.upload(); + JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties(['path', 'value']); + JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal('upload'); + (JSON.parse(mParticleIOSV2Bridge.data[0]).value === null).should.equal(true); + done(); + }); + }); + }); + }); - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) - * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": - * Test: `Object.prototype.toString.call(new Map().entries())`` - * - Edge <=13 === "[object Object]" - */ - if (mapExists && objPrototype === mapIteratorPrototype) { - return 'Map Iterator'; - } + var BadBoolean = 0; + var BadNumberAsString = 10; + var BadStringBoolean = 'foo bar'; + var EmptyObjectAsPrivacyConsentState = {}; + var EmptyStringAsPrivacyConsentState = ''; + var findBatch$1 = TestsCore.findBatch; + var mockServer$5; + var mParticle$4 = window.mParticle; + describe('Consent', function () { + beforeEach(function () { + client.post(urls.events, 200); + mockServer$5 = sinon$1.createFakeServer(); + mockServer$5.respondImmediately = true; + mockServer$5.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle$4.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + mockServer$5.restore(); + client.restore(); + mParticle$4._resetForTests(MPConfig); + }); + it('Should not create consent object without consented boolean', function (done) { + var consent = mParticle$4.Consent.createGDPRConsent(null); + expect(consent === null).to.be.ok; + consent = mParticle$4.Consent.createGDPRConsent(BadBoolean); + consent = mParticle$4.Consent.createGDPRConsent(BadStringBoolean); + expect(consent === null).to.be.ok; + done(); + }); + it('Should create basic consent object with only consented boolean', function (done) { + var consent = mParticle$4.Consent.createGDPRConsent(true); + expect(consent).to.be.ok; + consent.Consented.should.equal(true); + consent = mParticle$4.Consent.createGDPRConsent(false); + expect(consent).to.be.ok; + consent.Consented.should.equal(false); + done(); + }); + it('Should not create consent object with invalid document', function (done) { + var badDocument = 123; + var consent = mParticle$4.getInstance().Consent.createGDPRConsent(true, 123, badDocument); + expect(consent === null).to.be.ok; + done(); + }); + it('Should not create consent object with invalid location', function (done) { + var badLocation = 123; + var consent = mParticle$4.getInstance().Consent.createGDPRConsent(true, 123, 'foo document', badLocation); + expect(consent === null).to.be.ok; + done(); + }); + it('Should not create consent object with invalid hardware id', function (done) { + var badHardwareId = 123; + var consent = mParticle$4.getInstance().Consent.createGDPRConsent(true, 123, 'foo document', 'foo location', badHardwareId); + expect(consent === null).to.be.ok; + done(); + }); + it('Should set current timestamp if none given', function (done) { + var date = Date.now(); + var consent = mParticle$4.Consent.createGDPRConsent(true); + expect(consent.Timestamp).to.be.greaterThanOrEqual(date); + done(); + }); + it('Should create complete object', function (done) { + var consent = mParticle$4.getInstance().Consent.createGDPRConsent(true, 10, 'foo document', 'foo location', 'foo hardware id'); + expect(consent).to.be.ok; + consent.should.have.property('Consented', true); + consent.should.have.property('Timestamp', 10); + consent.should.have.property('ConsentDocument', 'foo document'); + consent.should.have.property('Location', 'foo location'); + consent.should.have.property('HardwareId', 'foo hardware id'); + done(); + }); + it('Should create basic ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + done(); + }); + it('Should add GDPR ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar', mParticle$4.Consent.createGDPRConsent(false)); + expect(consentState.getGDPRConsentState()).to.have.property('foo'); + // FIXME: getGDPRConsentState should return a dictionary of consent states + // rather than a consent state + expect(consentState.getGDPRConsentState().foo).to.have.property('Consented', true); + // Test is verifying that attribute GDPR does not exist in ConsentState + // but this makes TypeScript mad. + expect(consentState.GDPR === undefined).to.be.ok; + expect(consentState.getGDPRConsentState()).to.have.property('bar'); + expect(consentState.getGDPRConsentState().bar).to.have.property('Consented', false); + done(); + }); + it('Should replace GDPR ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + var consentState2 = mParticle$4.getInstance().Consent.createConsentState(); + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)); + consentState2.addGDPRConsentState('bar', mParticle$4.Consent.createGDPRConsent(false)); + consentState2.addGDPRConsentState('baz', mParticle$4.Consent.createGDPRConsent(false)); + consentState.getGDPRConsentState().should.have.property('foo'); + consentState2.getGDPRConsentState().should.have.property('bar'); + consentState2.getGDPRConsentState().should.have.property('baz'); + consentState.setGDPRConsentState(consentState2.getGDPRConsentState()); + consentState.getGDPRConsentState().should.not.have.property('foo'); + consentState.getGDPRConsentState().should.have.property('bar'); + consentState.getGDPRConsentState().should.have.property('baz'); + done(); + }); + it('should not be able to modify GDPR ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar', mParticle$4.Consent.createGDPRConsent(false)); + consentState.getGDPRConsentState().should.have.property('foo'); + delete consentState.getGDPRConsentState().foo; + consentState.getGDPRConsentState().should.have.property('foo'); + done(); + }); + it('Should copy GDPR ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar', mParticle$4.Consent.createGDPRConsent(false)); + var consentState2 = mParticle$4.getInstance().Consent.createConsentState(consentState); + consentState2.addGDPRConsentState('baz', mParticle$4.Consent.createGDPRConsent(false)); + expect(consentState.getGDPRConsentState()).to.have.property('foo'); + expect(consentState.getGDPRConsentState().foo).to.have.property('Consented', true); + consentState.getGDPRConsentState().should.have.property('bar'); + expect(consentState.getGDPRConsentState().bar).to.have.property('Consented', false); + consentState.getGDPRConsentState().should.not.have.property('baz'); + consentState2.getGDPRConsentState().should.have.property('foo'); + expect(consentState2.getGDPRConsentState().foo).to.have.property('Consented', true); + consentState2.getGDPRConsentState().should.have.property('bar'); + expect(consentState2.getGDPRConsentState().bar).to.have.property('Consented', false); + consentState2.getGDPRConsentState().should.have.property('baz'); + expect(consentState2.getGDPRConsentState().baz).to.have.property('Consented', false); + done(); + }); + it('Should remove GDPR ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar', mParticle$4.Consent.createGDPRConsent(false)); + consentState.getGDPRConsentState().should.have.property('foo'); + consentState.getGDPRConsentState().should.have.property('bar'); + consentState.removeGDPRConsentState('bar'); + consentState.getGDPRConsentState().should.not.have.property('bar'); + consentState.getGDPRConsentState().should.have.property('foo'); + done(); + }); + it('Should normalize GDPR consent purposes on add', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true, 1)).addGDPRConsentState('bar ', mParticle$4.Consent.createGDPRConsent(true, 2)).addGDPRConsentState('BAZ ', mParticle$4.Consent.createGDPRConsent(false, 3)).addGDPRConsentState(' ', mParticle$4.Consent.createGDPRConsent(false, 4)); + var gdprConsentState = consentState.getGDPRConsentState(); + expect(gdprConsentState).to.have.property('foo'); + expect(gdprConsentState).to.have.property('bar'); + expect(gdprConsentState).to.have.property('baz'); + expect(gdprConsentState).to.not.have.property(' '); + expect(gdprConsentState.foo).to.have.property('Timestamp', 1); + expect(gdprConsentState).to.not.have.property('bar '); + expect(gdprConsentState.bar).to.have.property('Timestamp', 2); + expect(gdprConsentState).to.not.have.property('BAZ '); + expect(gdprConsentState.baz).to.have.property('Timestamp', 3); + done(); + }); + it('Should normalize GDPR consent purposes on remove', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true, 1)).addGDPRConsentState('bar ', mParticle$4.Consent.createGDPRConsent(true, 2)).addGDPRConsentState('BAZ ', mParticle$4.Consent.createGDPRConsent(false, 3)); + var gdprConsentState = consentState.getGDPRConsentState(); + expect(gdprConsentState).to.have.property('foo'); + expect(gdprConsentState).to.have.property('bar'); + expect(gdprConsentState).to.have.property('baz'); + consentState.removeGDPRConsentState('FOO'); + consentState.removeGDPRConsentState('bAr '); + consentState.removeGDPRConsentState(' bAz '); + // Fetch an updated version of the consent state to verify attributes were removed + var gdprConsentStateUpdate = consentState.getGDPRConsentState(); + expect(gdprConsentStateUpdate).to.not.have.property('foo'); + expect(gdprConsentStateUpdate).to.not.have.property('bar'); + expect(gdprConsentStateUpdate).to.not.have.property('baz'); + done(); + }); + it('Should not set junk GDPR object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.addGDPRConsentState('foo', mParticle$4.Consent.createGDPRConsent(true)).addGDPRConsentState('bar', EmptyObjectAsPrivacyConsentState).addGDPRConsentState('baz', EmptyStringAsPrivacyConsentState).addGDPRConsentState(BadNumberAsString, EmptyObjectAsPrivacyConsentState); + expect(consentState.getGDPRConsentState()).to.have.property('foo'); + expect(consentState.getGDPRConsentState()).to.not.have.property('bar'); + expect(consentState.getGDPRConsentState()).to.not.have.property('baz'); + expect(consentState.getGDPRConsentState()).to.not.have.property(10); + done(); + }); + it('Should toJson/fromJson complete Consent State object', function (done) { + var consent1 = mParticle$4.getInstance().Consent.createGDPRConsent(true, 10, 'foo document', 'foo location', 'foo hardware id'); + var consent2 = mParticle$4.getInstance().Consent.createGDPRConsent(false, 5, 'foo document 2', 'foo location 2', 'foo hardware id 2'); + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + consentState.addGDPRConsentState('foo', consent1); + consentState.addGDPRConsentState('bar', consent2); + var consentStateCopy = mParticle$4.getInstance()._Consent.ConsentSerialization.fromMinifiedJsonObject(mParticle$4.getInstance()._Consent.ConsentSerialization.toMinifiedJsonObject(consentState)); + consentStateCopy.getGDPRConsentState().should.have.property('foo'); + var consentCopy1 = consentStateCopy.getGDPRConsentState().foo; + consentCopy1.should.have.property('Consented', true); + consentCopy1.should.have.property('Timestamp', 10); + consentCopy1.should.have.property('ConsentDocument', 'foo document'); + consentCopy1.should.have.property('Location', 'foo location'); + consentCopy1.should.have.property('HardwareId', 'foo hardware id'); + consentStateCopy.getGDPRConsentState().should.have.property('bar'); + var consentCopy2 = consentStateCopy.getGDPRConsentState().bar; + consentCopy2.should.have.property('Consented', false); + consentCopy2.should.have.property('Timestamp', 5); + consentCopy2.should.have.property('ConsentDocument', 'foo document 2'); + consentCopy2.should.have.property('Location', 'foo location 2'); + consentCopy2.should.have.property('HardwareId', 'foo hardware id 2'); + done(); + }); + it('Should not create a CCPA consent object without consented boolean', function (done) { + var consent = mParticle$4.Consent.createCCPAConsent(null); + expect(consent === null).to.be.ok; + consent = mParticle$4.Consent.createCCPAConsent(BadBoolean); + consent = mParticle$4.Consent.createCCPAConsent(BadStringBoolean); + expect(consent === null).to.be.ok; + done(); + }); + it('Should create basic consent object with only consented boolean', function (done) { + var consent = mParticle$4.Consent.createCCPAConsent(true); + expect(consent).to.be.ok; + consent.Consented.should.equal(true); + consent = mParticle$4.Consent.createCCPAConsent(false); + expect(consent).to.be.ok; + consent.Consented.should.equal(false); + done(); + }); + it('Should not create consent object with invalid document', function (done) { + var badDocument = 123; + var consent = mParticle$4.getInstance().Consent.createCCPAConsent(true, 123, badDocument); + expect(consent === null).to.be.ok; + done(); + }); + it('Should not create consent object with invalid location', function (done) { + var badLocation = 123; + var consent = mParticle$4.getInstance().Consent.createCCPAConsent(true, 123, 'foo document', badLocation); + expect(consent === null).to.be.ok; + done(); + }); + it('Should not create consent object with invalid hardware id', function (done) { + var badHardwareId = 123; + var consent = mParticle$4.getInstance().Consent.createCCPAConsent(true, 123, 'foo document', 'foo location', badHardwareId); + expect(consent === null).to.be.ok; + done(); + }); + it('Should set current timestamp if none given', function (done) { + var date = Date.now(); + var consent = mParticle$4.Consent.createCCPAConsent(true); + expect(consent.Timestamp).to.be.greaterThanOrEqual(date); + done(); + }); + it('Should create complete CCPA consent object', function (done) { + var consent = mParticle$4.getInstance().Consent.createCCPAConsent(true, 10, 'foo document', 'foo location', 'foo hardware id'); + expect(consent).to.be.ok; + consent.should.have.property('Consented', true); + consent.should.have.property('Timestamp', 10); + consent.should.have.property('ConsentDocument', 'foo document'); + consent.should.have.property('Location', 'foo location'); + consent.should.have.property('HardwareId', 'foo hardware id'); + done(); + }); + it('Should set CCPA ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false)); + expect(consentState.getCCPAConsentState()).to.have.property('Consented'); + expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument'); + expect(consentState.getCCPAConsentState()).to.have.property('HardwareId'); + expect(consentState.getCCPAConsentState()).to.have.property('Location'); + expect(consentState.getCCPAConsentState()).to.have.property('Timestamp'); + done(); + }); + it('Should remove CCPA ConsentState object', function (done) { + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false)); + expect(consentState.getCCPAConsentState()).to.have.property('Consented'); + expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument'); + expect(consentState.getCCPAConsentState()).to.have.property('HardwareId'); + expect(consentState.getCCPAConsentState()).to.have.property('Location'); + expect(consentState.getCCPAConsentState()).to.have.property('Timestamp'); + consentState.removeCCPAConsentState(); + expect(consentState.getCCPAConsentState() === undefined).to.equal(true); + done(); + }); + it('should have CCPA in payload', function (done) { + var consentState = mParticle$4.Consent.createConsentState(); + var timestamp = new Date().getTime(); + var ccpaConsent = mParticle$4.Consent.createCCPAConsent(true, timestamp, 'consentDoc', 'location', 'hardware'); + consentState.setCCPAConsentState(ccpaConsent); + var user = mParticle$4.Identity.getCurrentUser(); + user.setConsentState(consentState); + mParticle$4.logEvent('Test Event'); + var testEvent = findBatch$1(client._calls, 'Test Event'); + testEvent.should.have.property('consent_state'); + testEvent.consent_state.should.have.property('ccpa'); + testEvent.consent_state.ccpa.should.have.property('data_sale_opt_out'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('consented', true); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('timestamp_unixtime_ms', timestamp); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('document', 'consentDoc'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('location', 'location'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('hardware_id', 'hardware'); + done(); + }); + it('should have CCPA and GDPR in payload', function (done) { + var consentState = mParticle$4.Consent.createConsentState(); + var timestamp = new Date().getTime(); + var ccpaConsent = mParticle$4.Consent.createCCPAConsent(true, timestamp, 'consentDoc', 'location', 'hardware'); + var gdprConsent = mParticle$4.Consent.createGDPRConsent(false, timestamp, 'consentDoc', 'location', 'hardware'); + consentState.setCCPAConsentState(ccpaConsent); + consentState.addGDPRConsentState('test purpose', gdprConsent); + var user = mParticle$4.Identity.getCurrentUser(); + user.setConsentState(consentState); + mParticle$4.logEvent('Test Event'); + var testEvent = findBatch$1(client._calls, 'Test Event'); + testEvent.should.have.property('consent_state'); + testEvent.consent_state.should.have.property('ccpa'); + testEvent.consent_state.ccpa.should.have.property('data_sale_opt_out'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('consented', true); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('timestamp_unixtime_ms', timestamp); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('document', 'consentDoc'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('location', 'location'); + testEvent.consent_state.ccpa.data_sale_opt_out.should.have.property('hardware_id', 'hardware'); + testEvent.consent_state.should.have.property('gdpr'); + testEvent.consent_state.gdpr.should.have.property('test purpose'); + testEvent.consent_state.gdpr['test purpose'].should.have.property('consented', false); + testEvent.consent_state.gdpr['test purpose'].should.have.property('timestamp_unixtime_ms', timestamp); + testEvent.consent_state.gdpr['test purpose'].should.have.property('document', 'consentDoc'); + testEvent.consent_state.gdpr['test purpose'].should.have.property('location', 'location'); + testEvent.consent_state.gdpr['test purpose'].should.have.property('hardware_id', 'hardware'); + done(); + }); + // TODO: Deprecate in next major version + it('Should log deprecated message when using removeCCPAState', function (done) { + var bond = sinon$1.spy(mParticle$4.getInstance().Logger, 'warning'); + var consentState = mParticle$4.getInstance().Consent.createConsentState(); + expect(consentState).to.be.ok; + consentState.setCCPAConsentState(mParticle$4.Consent.createCCPAConsent(false)); + expect(consentState.getCCPAConsentState()).to.have.property('Consented'); + expect(consentState.getCCPAConsentState()).to.have.property('ConsentDocument'); + expect(consentState.getCCPAConsentState()).to.have.property('HardwareId'); + expect(consentState.getCCPAConsentState()).to.have.property('Location'); + expect(consentState.getCCPAConsentState()).to.have.property('Timestamp'); + // FIXME: Remove when deprecating removeCCPAState + consentState.removeCCPAState(); + (consentState.getCCPAConsentState() === undefined).should.equal(true); + bond.called.should.eql(true); + bond.getCalls()[0].args[0].should.eql('removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead'); + done(); + }); + }); - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) - * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": - * Test: `Object.prototype.toString.call(new Set().entries())`` - * - Edge <=13 === "[object Object]" - */ - if (setExists && objPrototype === setIteratorPrototype) { - return 'Set Iterator'; - } + var mockServer$4; + var mParticle$3 = window.mParticle; + var ServerModel = mParticle$3.getInstance()._ServerModel; + describe('ServerModel', function () { + beforeEach(function () { + }); + describe('#appendUserInfo', function () { + it('should append User Identities and Attributes to event', function () { + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return { + gdpr: { + 'test-purpose': { + consented: true, + timestamp: 11111, + consent_document: 'gdpr-doc', + location: 'test-gdpr-location', + hardwareId: 'test-gdpr-hardware' + } + }, + ccpa: { + data_sale_opt_out: { + consented: false, + timestamp: 22222, + consent_document: 'ccpa-doc', + location: 'test-ccpa-location', + hardwareId: 'test-ccpa-hardware' + } + } + }; + } + }; + // TODO: We should move some of the event samples into a reusable module + // or set up an event factory + var event = { + EventName: 'Test Event', + MPID: '', + IsFirstRun: true, + DeviceId: 'test-device', + EventCategory: 0, + SourceMessageId: 'test-source-message-id', + SDKVersion: 'test-version', + SessionId: 'test-session-id', + SessionStartDate: 0, + Timestamp: 0, + EventDataType: 0, + Debug: true, + CurrencyCode: 'USD' + }; + ServerModel.appendUserInfo(user, event); + expect(event.MPID).to.equal('98765'); + expect(event.ConsentState).to.eql({ + gdpr: { + 'test-purpose': { + consented: true, + timestamp: 11111, + consent_document: 'gdpr-doc', + location: 'test-gdpr-location', + hardwareId: 'test-gdpr-hardware' + } + }, + ccpa: { + data_sale_opt_out: { + consented: false, + timestamp: 22222, + consent_document: 'ccpa-doc', + location: 'test-ccpa-location', + hardwareId: 'test-ccpa-hardware' + } + } + }); + expect(event.UserAttributes).to.eql({ + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }); + expect(event.UserIdentities).to.eql([{ + Identity: 'foo-other', + Type: 0 + }, { + Identity: '1234567', + Type: 1 + }, { + Identity: 'foo-email', + Type: 7 + }, { + Identity: 'foo-other2', + Type: 10 + }, { + Identity: 'foo-other3', + Type: 11 + }, { + Identity: 'foo-other4', + Type: 12 + }]); + }); + it('sets User Attributes and Identities to null if user is empty', function () { + var event = {}; + ServerModel.appendUserInfo(null, event); + expect(event.MPID).to.eql(null); + expect(event.ConsentState).to.eql(null); + expect(event.UserIdentities).to.eql(null); + expect(event.UserAttributes).to.eql(null); + }); + it('returns undefined if event is empty', function () { + expect(ServerModel.appendUserInfo({}, null)).to.be.undefined; + }); + it('returns early if event MPID matches User MPID', function () { + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: {} + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return null; + }, + getMPID: function getMPID() { + return '123456'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + var event = { + MPID: '123456' + }; + ServerModel.appendUserInfo(user, event); + expect(event.MPID).to.equal('123456'); + // Verify to make sure we didn't add anything unnecessary to the event + expect(Object.keys(event).length).to.equal(1); + }); + it('updates event MPID with User MPID', function () { + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: {} + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return null; + }, + getMPID: function getMPID() { + return '123456'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + var event = { + MPID: '555666777' + }; + ServerModel.appendUserInfo(user, event); + expect(event.MPID).to.equal('123456'); + }); + it('returns early if event and user are not valid', function () { + expect(ServerModel.appendUserInfo(null, null)).to.be.undefined; + }); + }); + describe('#convertToConsentStateDTO', function () { + it('should convert Consent State with GDPR to a DTO', function () { + var consentState = { + getGDPRConsentState: function getGDPRConsentState() { + return { + 'test-gdpr-purpose': { + Consented: true, + Timestamp: 12345, + ConsentDocument: 'gdpr-doc', + Location: 'test-gdpr-location', + HardwareId: 'test-gdpr-hardware-id' + } + }; + }, + getCCPAConsentState: function getCCPAConsentState() {} + }; + var expectedDTO = { + gdpr: { + 'test-gdpr-purpose': { + c: true, + d: 'gdpr-doc', + h: 'test-gdpr-hardware-id', + l: 'test-gdpr-location', + ts: 12345 + } + } + }; + expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO); + }); + it('should convert Consent State with CCPA to a DTO', function () { + var consentState = { + getGDPRConsentState: function getGDPRConsentState() {}, + getCCPAConsentState: function getCCPAConsentState() { + return { + Consented: false, + Timestamp: 67890, + ConsentDocument: 'ccpa-doc', + Location: 'test-ccpa-location', + HardwareId: 'test-ccpa-hardware-id' + }; + } + }; + var expectedDTO = { + ccpa: { + data_sale_opt_out: { + c: false, + d: 'ccpa-doc', + h: 'test-ccpa-hardware-id', + l: 'test-ccpa-location', + ts: 67890 + } + } + }; + expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO); + }); + it('should convert Consent State with both GDPR and CCPA to a DTO', function () { + var consentState = { + getGDPRConsentState: function getGDPRConsentState() { + return { + 'test-gdpr-purpose': { + Consented: true, + Timestamp: 12345, + ConsentDocument: 'gdpr-doc', + Location: 'test-gdpr-location', + HardwareId: 'test-gdpr-hardware-id' + } + }; + }, + getCCPAConsentState: function getCCPAConsentState() { + return { + Consented: false, + Timestamp: 67890, + ConsentDocument: 'ccpa-doc', + Location: 'test-ccpa-location', + HardwareId: 'test-ccpa-hardware-id' + }; + } + }; + var expectedDTO = { + gdpr: { + 'test-gdpr-purpose': { + c: true, + d: 'gdpr-doc', + h: 'test-gdpr-hardware-id', + l: 'test-gdpr-location', + ts: 12345 + } + }, + ccpa: { + data_sale_opt_out: { + c: false, + d: 'ccpa-doc', + h: 'test-ccpa-hardware-id', + l: 'test-ccpa-location', + ts: 67890 + } + } + }; + expect(ServerModel.convertToConsentStateV2DTO(consentState)).to.eql(expectedDTO); + }); + it('returns null if Consent State is null', function () { + expect(ServerModel.convertToConsentStateV2DTO(null)).to.eql(null); + }); + }); + describe('#createEventObject', function () { + beforeEach(function () { + // TODO: Create Event Object is tightly coupled with mp Init and Store + // This should be refactored to make the function more pure + mockServer$4 = sinon$1.createFakeServer(); + mockServer$4.respondImmediately = true; + mockServer$4.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle$3.init(apiKey, mParticle$3.config); + }); + afterEach(function () { + mockServer$4.restore(); + }); + it('should create an event object without a user', function () { + var mPStore = mParticle$3.getInstance()._Store; + var event = { + name: 'Test Event', + messageType: Types.MessageType.PageEvent, + eventType: Types.EventType.Navigation, + data: { + foo: 'bar', + bizz: 'bazz' + }, + sourceMessageId: 'test-source-message-id', + customFlags: { + custom: 'flag' + }, + userAttributeChanges: { + UserAttributeName: '$Age', + New: '42', + Old: '37', + Deleted: false, + IsNewAttribute: false + }, + userIdentityChanges: { + New: { + IdentityType: Types.IdentityType.Other2, + Identity: 'new_identity', + Timestamp: 1668194307, + CreatedThisBatch: false + }, + Old: { + IdentityType: Types.IdentityType.Other, + Identity: 'old_identity', + Timestamp: 1668193307, + CreatedThisBatch: false + } + } + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject.EventName, 'EventName').to.equal('Test Event'); + expect(actualEventObject.EventCategory, 'EventCategory').to.equal(Types.EventType.Navigation); + expect(actualEventObject.EventAttributes, 'EventCategory').to.eql({ + foo: 'bar', + bizz: 'bazz' + }); + expect(actualEventObject.EventDataType, 'EventDataType').to.equal(Types.MessageType.PageEvent); + expect(actualEventObject.CustomFlags, 'CustomFlags').to.eql({ + custom: 'flag' + }); + expect(actualEventObject.UserAttributeChanges, 'UserAttributeChanges').to.eql({ + UserAttributeName: '$Age', + New: '42', + Old: '37', + Deleted: false, + IsNewAttribute: false + }); + expect(actualEventObject.UserIdentityChanges, 'UserrIdentityChanges').to.eql({ + New: { + IdentityType: Types.IdentityType.Other2, + Identity: 'new_identity', + Timestamp: 1668194307, + CreatedThisBatch: false + }, + Old: { + IdentityType: Types.IdentityType.Other, + Identity: 'old_identity', + Timestamp: 1668193307, + CreatedThisBatch: false + } + }); + expect(actualEventObject.Store, 'Store').to.eql({}); + expect(actualEventObject.SDKVersion, 'SDKVersion').to.equal(Constants.sdkVersion); + expect(actualEventObject.SessionId, 'SessionId').to.equal(mPStore.sessionId); + expect(actualEventObject.SessionStartDate, 'SessionStartDate').to.equal(mPStore.sessionStartDate.getTime()); + expect(actualEventObject.Debug, 'Debug').to.equal(false); + expect(actualEventObject.Location, 'Location').to.equal(null); + expect(actualEventObject.OptOut, 'OptOut').to.equal(null); + expect(actualEventObject.ExpandedEventCount, 'ExpandedEventCount').to.equal(0); + expect(actualEventObject.AppVersion, 'AppVersion').to.equal(undefined); + expect(actualEventObject.AppName, 'AppName').to.equal(undefined); + expect(actualEventObject.Package, 'Package').to.equal(undefined); + expect(actualEventObject.ClientGeneratedId, 'ClientGeneratedId').to.equal(mPStore.clientId); + expect(actualEventObject.DeviceId, 'DeviceId').to.equal(mPStore.deviceId); + expect(actualEventObject.IntegrationAttributes, 'IntegrationAttributes').to.eql({}); + // TODO: Should this default to USD? + expect(actualEventObject.CurrencyCode, 'CurrencyCode').to.equal(null); + expect(actualEventObject.DataPlan, 'DataPlan').to.eql({}); + expect(actualEventObject.Timestamp, 'Timestamp').to.equal(mPStore.dateLastEventSent.getTime()); + }); + it('should create an event object with a user', function () { + var event = { + name: 'Test Event', + messageType: Types.MessageType.PageEvent, + eventType: Types.EventType.Navigation, + data: { + foo: 'bar', + bizz: 'bazz' + }, + sourceMessageId: 'test-source-message-id', + customFlags: { + custom: 'flag' + }, + userAttributeChanges: { + UserAttributeName: '$Age', + New: '42', + Old: '37', + Deleted: false, + IsNewAttribute: false + }, + userIdentityChanges: { + New: { + IdentityType: Types.IdentityType.Other2, + Identity: 'new_identity', + Timestamp: 1668194307, + CreatedThisBatch: false + }, + Old: { + IdentityType: Types.IdentityType.Other, + Identity: 'old_identity', + Timestamp: 1668193307, + CreatedThisBatch: false + } + } + }; + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return { + gdpr: { + 'test-purpose': { + consented: true, + timestamp: 11111, + consent_document: 'gdpr-doc', + location: 'test-gdpr-location', + hardwareId: 'test-gdpr-hardware' + } + }, + ccpa: { + data_sale_opt_out: { + consented: false, + timestamp: 22222, + consent_document: 'ccpa-doc', + location: 'test-ccpa-location', + hardwareId: 'test-ccpa-hardware' + } + } + }; + } + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event, user); + expect(actualEventObject.MPID, 'MPID').to.equal('98765'); + expect(actualEventObject.ConsentState, 'ConsentState').to.eql({ + gdpr: { + 'test-purpose': { + consented: true, + timestamp: 11111, + consent_document: 'gdpr-doc', + location: 'test-gdpr-location', + hardwareId: 'test-gdpr-hardware' + } + }, + ccpa: { + data_sale_opt_out: { + consented: false, + timestamp: 22222, + consent_document: 'ccpa-doc', + location: 'test-ccpa-location', + hardwareId: 'test-ccpa-hardware' + } + } + }); + expect(actualEventObject.UserAttributes).to.eql({ + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }); + expect(actualEventObject.UserIdentities).to.eql([{ + Identity: 'foo-other', + Type: 0 + }, { + Identity: '1234567', + Type: 1 + }, { + Identity: 'foo-email', + Type: 7 + }, { + Identity: 'foo-other2', + Type: 10 + }, { + Identity: 'foo-other3', + Type: 11 + }, { + Identity: 'foo-other4', + Type: 12 + }]); + }); + it('should set necessary attributes if MessageType is SessionEnd', function () { + var mPStore = mParticle$3.getInstance()._Store; + mPStore.sessionAttributes = { + fooSessionAttr: 'session-foo', + barSessionAttr: 'session-bar' + }; + var event = { + name: 'Test Event', + messageType: Types.MessageType.SessionEnd, + eventType: Types.EventType.Other, + data: { + fooEventAttr: 'bar', + barEventAttr: 'bazz' + } + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject.currentSessionMPIDs, 'currentSessionMPIDs').to.eql(['testMPID']); + // A SessionEnd event appends SessionLength + expect(actualEventObject).to.have.property('SessionLength'); + // A SessionEnd event should ignore Event Attributes and use Session Attributes instead + expect(actualEventObject.EventAttributes, 'EventAttributes').to.eql({ + fooSessionAttr: 'session-foo', + barSessionAttr: 'session-bar' + }); + expect(actualEventObject.EventAttributes, 'EventAttributes').to.not.have.property('fooEventAttr'); + expect(actualEventObject.EventAttributes, 'EventAttributes').to.not.have.property('barEventAttr'); + // A SessionEnd event resets currentSessionMPIDs and sessionStartDate. When a new session starts, these are filled again + expect(mPStore.currentSessionMPIDs).to.eql([]); + expect(mPStore.sessionStartDate).to.eql(null); + }); + it('should set necessary attributes if MessageType is AppStateTransition', function () { + var event = { + name: 'Test Event', + messageType: Types.MessageType.AppStateTransition, + eventType: Types.EventType.Other + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject.IsFirstRun, 'IsFirstRun').to.eql(false); + expect(actualEventObject.LaunchReferral, 'LaunchRefferral').to.eql(window.location.href); + }); + it('should generate a sourceMessageId if one is not provided', function () { + var event = { + name: 'Test Event', + sourceMessageId: null, + messageType: Types.MessageType.CustomEvent, + eventType: Types.EventType.Other + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject.SourceMessageId, 'SourceMessageId').to.not.equal(null); + }); + it('returns null if _Store does not have a sessionId', function () { + var mPStore = mParticle$3.getInstance()._Store; + mPStore.sessionId = null; + var event = { + name: 'Test Opt Out Event', + messageType: Types.MessageType.CustomEvent + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject).to.equal(null); + }); + it('returns null if _Store has Webview Bridge Disabled', function () { + var mPStore = mParticle$3.getInstance()._Store; + mPStore.sessionId = null; + mPStore.webviewBridgeEnabled = false; + var event = { + name: 'Test Opt Out Event', + messageType: Types.MessageType.CustomEvent + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject).to.equal(null); + }); + it('returns null if event is invalid', function () { + var event = {}; + expect(ServerModel.createEventObject(event)).to.eql(null); + }); + it('should support toEventAPIObject', function () { + var eventAPIObject = { + EventName: 'Test Event Object Override', + EventCategory: Types.EventType.Media, + EventDataType: Types.MessageType.Media + }; + var event = { + name: 'Test Event Object', + messageType: Types.MessageType.PageEvent, + eventType: Types.EventType.Other, + toEventAPIObject: function toEventAPIObject() { + return eventAPIObject; + } + }; + var actualEventObject = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(actualEventObject.EventName, 'EventName').to.equal('Test Event Object Override'); + expect(actualEventObject.EventCategory, 'EventCategory').to.equal(Types.EventType.Media); + expect(actualEventObject.EventDataType, 'EventDataType').to.equal(Types.MessageType.Media); + }); + }); + describe('#convertEventToDTO', function () { + it('should convert an event to a DTO', function () { + var uploadObject = { + EventName: 'test-name', + EventCategory: Types.EventType.Navigation, + EventAttributes: {}, + UserAttributes: {}, + UserIdentities: [], + IntegrationAttributes: [], + Store: {}, + SDKVersion: '1.2.3', + SessionId: 'test-session-id', + SessionLength: 33000, + SessionStartDate: 11111, + EventDataType: Types.MessageType.PageEvent, + Debug: true, + Timestamp: 22222, + Location: { + lat: 123445, + lng: 323232 + }, + OptOut: false, + AppVersion: 'test-app.1235', + ClientGeneratedId: 'test-client-id', + DeviceId: 'test-device', + MPID: 'test-mpid', + ExpandedEventCount: 0, + currentSessionMPIDs: ['test-mpids'] + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.n, 'event.EventName (n)').to.equal('test-name'); + expect(actualDTO.et, 'event.EventType (et)').to.equal(Types.EventType.Navigation); + expect(actualDTO.ua, 'event.UserAttributes (ua)').to.eql({}); + expect(actualDTO.ui, 'event.UserIdentities (ui)').to.eql([]); + expect(actualDTO.ia, 'event.IntegrationAttributes (ia)').to.eql([]); + expect(actualDTO.str, 'event.Store (str)').to.eql({}); + expect(actualDTO.attrs, 'event.EventAttributes (attrs)').to.eql({}); + expect(actualDTO.sdk, 'event.SDKVersion (sdk)').to.equal('1.2.3'); + expect(actualDTO.sid, 'event.SessionId (sid)').to.equal('test-session-id'); + expect(actualDTO.sl, 'event.SessionLength (sl)').to.equal(33000); + expect(actualDTO.ssd, 'event.SessionStartDate (ssd)').to.equal(11111); + expect(actualDTO.dt, 'event.EventDataType (dt)').to.equal(Types.MessageType.PageEvent); + expect(actualDTO.dbg, 'event.Debug (dbg)').to.equal(true); + expect(actualDTO.ct, 'event.TimeStamp (ct)').to.equal(22222); + expect(actualDTO.lc, 'event.Location (lc)').to.eql({ + lat: 123445, + lng: 323232 + }); + expect(actualDTO.o, 'event.OptOut (o)').to.equal(false); + expect(actualDTO.eec, 'event.ExpandedEventCount (eec)').to.equal(0); + expect(actualDTO.av, 'event.AppVersion (av)').to.equal('test-app.1235'); + expect(actualDTO.cgid, 'event.ClientGeneratedId (cgid)').to.equal('test-client-id'); + expect(actualDTO.das, 'event.DeviceId (das)').to.equal('test-device'); + expect(actualDTO.mpid, 'event.MPID (mpid)').to.equal('test-mpid'); + expect(actualDTO.smpids, 'event.currentSessionMPIDs (smpids)').to.eql(['test-mpids']); + }); + it('should add data plan id and version to DTO', function () { + var uploadObject = { + DataPlan: { + PlanId: 'test-data-plan', + PlanVersion: 3 + } + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.dp_id, 'event.DataPlan.PlanId (dp_id)').to.equal('test-data-plan'); + expect(actualDTO.dp_v, 'event.DataPlan.PlanVersion (dp_v)').to.equal(3); + }); + it('should add consent state to DTO', function () { + var uploadObject = { + ConsentState: { + getGDPRConsentState: function getGDPRConsentState() { + return { + 'test-gdpr-purpose': { + Consented: true, + Timestamp: 12345, + ConsentDocument: 'gdpr-doc', + Location: 'test-gdpr-location', + HardwareId: 'test-gdpr-hardware-id' + } + }; + }, + getCCPAConsentState: function getCCPAConsentState() { + return { + Consented: false, + Timestamp: 67890, + ConsentDocument: 'ccpa-doc', + Location: 'test-ccpa-location', + HardwareId: 'test-ccpa-hardware-id' + }; + } + } + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.con, 'event.ConsentState (con)').to.eql({ + gdpr: { + 'test-gdpr-purpose': { + c: true, + d: 'gdpr-doc', + h: 'test-gdpr-hardware-id', + l: 'test-gdpr-location', + ts: 12345 + } + }, + ccpa: { + data_sale_opt_out: { + c: false, + d: 'ccpa-doc', + h: 'test-ccpa-hardware-id', + l: 'test-ccpa-location', + ts: 67890 + } + } + }); + }); + it('should add AST data to DTO', function () { + var uploadObject = { + EventDataType: Types.MessageType.AppStateTransition, + IsFirstRun: true, + LaunchReferral: 'https://mparticle.com/test-referral', + EventAttributes: { + foo: 'bar' // TODO: test will nullify these + } + }; + + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.fr, 'event.IsFirstRun (fr)').to.equal(true); + expect(actualDTO.iu, 'event.isUpgrade').to.equal(false); + expect(actualDTO.at, 'event.ApplicationTransitionType.AppInit (at)').to.equal(Types.ApplicationTransitionType.AppInit); + expect(actualDTO.lr, 'event.LaunchReferral (lr)').to.equal('https://mparticle.com/test-referral'); + expect(actualDTO.attrs, 'event.EventAttributes (attrs)').to.eql(null); + }); + it('should add custom flags to DTO', function () { + var uploadObject = { + CustomFlags: { + foo: 'bar', + fizz: ['bizz', 'buzz', 37, true], + answer: 42, + isCustom: false + } + }; + var expectedFlags = { + foo: ['bar'], + fizz: ['bizz', 'buzz', '37', 'true'], + answer: ['42'], + isCustom: ['false'] + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.flags).to.eql(expectedFlags); + }); + it('should add shopping cart to DTO', function () { + var uploadObject = { + CurrencyCode: 'USD', + EventDataType: Types.MessageType.Commerce, + ShoppingCart: { + ProductList: [{ + Sku: 'SKU-12345', + Name: 'Some Item', + Price: '42', + Quantity: '3', + Brand: 'mParticle', + Variant: 'blue', + Category: 'product', + Position: 1, + CouponCode: 'FIDDY', + TotalAmount: '41.50', + Attributes: { + foo: 'bar', + fizz: 'bizz' + } + }, { + Sku: 'SKU-67890', + Name: 'Some Other Item', + Price: '37', + Quantity: '5', + Brand: 'mParticle', + Variant: 'red', + Category: 'not-product', + Position: 2, + CouponCode: 'FIDDY', + TotalAmount: '36.50', + Attributes: { + fizz: 'buzz' + } + }] + } + }; + var expectedShoppingCart = { + pl: [{ + id: 'SKU-12345', + nm: 'Some Item', + pr: 42, + qt: 3, + br: 'mParticle', + va: 'blue', + ca: 'product', + ps: 1, + cc: 'FIDDY', + tpa: 41.5, + attrs: { + foo: 'bar', + fizz: 'bizz' + } + }, { + id: 'SKU-67890', + nm: 'Some Other Item', + pr: 37, + qt: 5, + br: 'mParticle', + va: 'red', + ca: 'not-product', + ps: 2, + cc: 'FIDDY', + tpa: 36.5, + attrs: { + fizz: 'buzz' + } + }] + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.cu).to.equal('USD'); + expect(actualDTO.sc).to.eql(expectedShoppingCart); + }); + it('should add empty array to DTO if shopping cart is empty', function () { + var uploadObject = { + CurrencyCode: 'USD', + EventDataType: Types.MessageType.Commerce, + ShoppingCart: {} + }; + var expectedShoppingCart = { + pl: [] + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.cu).to.equal('USD'); + expect(actualDTO.sc).to.eql(expectedShoppingCart); + }); + it('should add product action to DTO', function () { + var uploadObject = { + CurrencyCode: 'USD', + EventDataType: Types.MessageType.Commerce, + ProductAction: { + ProductActionType: Types.ProductActionType.AddToCart, + CheckoutStep: 42, + CheckoutOptions: 'test-checkout-option', + TransactionId: 'id', + Affiliation: 'affiliation', + CouponCode: 'couponCode', + Revenue: 'revenue', + Shipping: 'shipping', + Tax: 'tax', + TotalAmount: '350.42', + ShippingAmount: '40.42', + TaxAmount: '3.50', + ProductList: [{ + Sku: 'SKU-12345', + Name: 'Some Item', + Price: '42', + Quantity: '3', + Brand: 'mParticle', + Variant: 'blue', + Category: 'product', + Position: 1, + CouponCode: 'FIDDY', + TotalAmount: '41.50', + Attributes: { + foo: 'bar', + fizz: 'bizz' + } + }, { + Sku: 'SKU-67890', + Name: 'Some Other Item', + Price: '37', + Quantity: '5', + Brand: 'mParticle', + Variant: 'red', + Category: 'not-product', + Position: 2, + CouponCode: 'FIDDY', + TotalAmount: '36.50', + Attributes: { + fizz: 'buzz' + } + }] + } + }; + var expectedProducts = [{ + id: 'SKU-12345', + nm: 'Some Item', + pr: 42, + qt: 3, + br: 'mParticle', + va: 'blue', + ca: 'product', + ps: 1, + cc: 'FIDDY', + tpa: 41.5, + attrs: { + foo: 'bar', + fizz: 'bizz' + } + }, { + id: 'SKU-67890', + nm: 'Some Other Item', + pr: 37, + qt: 5, + br: 'mParticle', + va: 'red', + ca: 'not-product', + ps: 2, + cc: 'FIDDY', + tpa: 36.5, + attrs: { + fizz: 'buzz' + } + }]; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.cu).to.equal('USD'); + expect(actualDTO.pd.an, 'ActionName').to.equal(Types.ProductActionType.AddToCart); + expect(actualDTO.pd.cs, 'CheckoutStep').to.equal(42); + expect(actualDTO.pd.co, 'CheckoutOptions').to.equal('test-checkout-option'); + expect(actualDTO.pd.ti, 'TransactionId').to.equal('id'); + expect(actualDTO.pd.ta, 'Affiliation').to.equal('affiliation'); + expect(actualDTO.pd.tcc, 'CouponCode').to.equal('couponCode'); + expect(actualDTO.pd.tr, 'TotalAmount').to.equal(350.42); + expect(actualDTO.pd.ts, 'ShippingAmount').to.equal(40.42); + expect(actualDTO.pd.tt, 'TaxAmount').to.equal(3.5); + expect(actualDTO.pd.pl, 'ProductList').to.eql(expectedProducts); + }); + it('should add promotion action to DTO', function () { + var uploadObject = { + CurrencyCode: 'USD', + EventDataType: Types.MessageType.Commerce, + PromotionAction: { + PromotionActionType: Types.PromotionActionType.PromotionView, + PromotionList: [{ + Id: '12345', + Name: 'Some Item', + Creative: 'this-thing', + Position: 1 + }, { + Id: '67890', + Name: 'Some Other Item', + Creative: 'that-thing', + Position: 2 + }] + } + }; + var expectedPromotion = [{ + id: '12345', + nm: 'Some Item', + cr: 'this-thing', + ps: 1 + }, { + id: '67890', + nm: 'Some Other Item', + cr: 'that-thing', + ps: 2 + }]; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.cu).to.equal('USD'); + expect(actualDTO.pm.an, 'ActionName').to.equal(Types.PromotionActionType.PromotionView); + expect(actualDTO.pm.pl, 'ProductList').to.eql(expectedPromotion); + }); + it('should add product impression to DTO', function () { + var uploadObject = { + CurrencyCode: 'USD', + EventDataType: Types.MessageType.Commerce, + ProductImpressions: [{ + ProductImpressionList: 'test-product-impression', + ProductList: [{ + Sku: 'SKU-12345', + Name: 'Some Item', + Price: '42', + Quantity: '3', + Brand: 'mParticle', + Variant: 'blue', + Category: 'product', + Position: 1, + CouponCode: 'FIDDY', + TotalAmount: '41.50', + Attributes: { + foo: 'bar', + fizz: 'bizz' + } + }, { + Sku: 'SKU-67890', + Name: 'Some Other Item', + Price: '37', + Quantity: '5', + Brand: 'mParticle', + Variant: 'red', + Category: 'not-product', + Position: 2, + CouponCode: 'FIDDY', + TotalAmount: '36.50', + Attributes: { + fizz: 'buzz' + } + }] + }] + }; + var expectedProducts = [{ + id: 'SKU-12345', + nm: 'Some Item', + pr: 42, + qt: 3, + br: 'mParticle', + va: 'blue', + ca: 'product', + ps: 1, + cc: 'FIDDY', + tpa: 41.5, + attrs: { + foo: 'bar', + fizz: 'bizz' + } + }, { + id: 'SKU-67890', + nm: 'Some Other Item', + pr: 37, + qt: 5, + br: 'mParticle', + va: 'red', + ca: 'not-product', + ps: 2, + cc: 'FIDDY', + tpa: 36.5, + attrs: { + fizz: 'buzz' + } + }]; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.cu).to.equal('USD'); + expect(actualDTO.pi[0].pil, 'ProductImpressionList').to.equal('test-product-impression'); + expect(actualDTO.pi[0].pl, 'ProductList').to.eql(expectedProducts); + }); + it('should add profile to DTO', function () { + var uploadObject = { + EventDataType: Types.MessageType.Profile, + ProfileMessageType: Types.ProfileMessageType.Logout + }; + var actualDTO = ServerModel.convertEventToV2DTO(uploadObject); + expect(actualDTO.pet).to.equal(Types.ProfileMessageType.Logout); + }); + }); + describe('Integration Tests', function () { + var event = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + beforeEach(function () { + mockServer$4 = sinon$1.createFakeServer(); + mockServer$4.respondImmediately = true; + mockServer$4.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + mParticle$3.init(apiKey, mParticle$3.config); + }); + afterEach(function () { + mockServer$4.restore(); + }); + it('Should not convert data plan object to server DTO when no id or version is set', function (done) { + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(event); + var upload = window.mParticle.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent); + upload.should.not.have.property('dp_id'); + upload.should.not.have.property('dp_v'); + done(); + }); + it('Should convert data plan id to server DTO', function (done) { + mParticle$3._resetForTests(); + mParticle$3.config.dataPlan = { + planId: 'plan-slug' + }; + mParticle$3.init('foo', mParticle$3.config); + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + var upload = mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent); + upload.should.have.property('dp_id', 'plan-slug'); + upload.should.not.have.property('dp_v'); + done(); + }); + it('Should not convert data plan object to server DTO when no id is set', function (done) { + mParticle$3._resetForTests(); + mParticle$3.config.dataPlan = { + planVersion: 5 + }; + mParticle$3.init('foo', mParticle$3.config); + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + var upload = mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent); + upload.should.not.have.property('dp_id'); + upload.should.not.have.property('dp_v'); + done(); + }); + it('Should convert entire data plan object to server DTO', function (done) { + mParticle$3._resetForTests(); + mParticle$3.config.dataPlan = { + planId: 'plan-slug', + planVersion: 10 + }; + mParticle$3.init('foo', mParticle$3.config); + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + var upload = mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(sdkEvent); + upload.should.have.property('dp_id', 'plan-slug'); + upload.should.have.property('dp_v', 10); + done(); + }); + it('Should convert complete consent object', function (done) { + var consentState = mParticle$3.getInstance()._Consent.createConsentState(); + consentState.addGDPRConsentState('foo', mParticle$3.getInstance()._Consent.createPrivacyConsent(true, 10, 'foo document', 'foo location', 'foo hardware id')); + // TODO: Resolve differences between SDKConsentState and ConsentState + // TODO: verify this tests passes + var consent = mParticle$3.getInstance()._ServerModel.convertToConsentStateV2DTO(consentState); + expect(consent).to.be.ok; + consent.should.have.property('gdpr'); + consent.gdpr.should.have.property('foo'); + consent.gdpr.foo.should.have.property('c', true); + consent.gdpr.foo.should.have.property('ts', 10); + consent.gdpr.foo.should.have.property('d', 'foo document'); + consent.gdpr.foo.should.have.property('l', 'foo location'); + consent.gdpr.foo.should.have.property('h', 'foo hardware id'); + done(); + }); + it('Should not append user info when no user exists', function (done) { + mParticle$3.getInstance()._Store.should.be.ok; + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + sdkEvent.should.be.ok; + expect(sdkEvent.UserIdentities).to.eql([]); + expect(sdkEvent.UserAttributes).to.eql({}); + expect(sdkEvent.ConsentState === null).to.eql(true); + done(); + }); + it('Should append all user info when user is present', function (done) { + mParticle$3.getInstance()._Store.should.be.ok; + var consentState = mParticle$3.getInstance()._Consent.createConsentState(); + consentState.addGDPRConsentState('foo', mParticle$3.getInstance()._Consent.createPrivacyConsent(true, 10, 'foo document', 'foo location', 'foo hardware id')); + var expectedUserIdentities = [{ + Identity: 'foo-other', + Type: 0 + }, { + Identity: '1234567', + Type: 1 + }, { + Identity: 'foo-email', + Type: 7 + }, { + Identity: 'foo-other2', + Type: 10 + }, { + Identity: 'foo-other3', + Type: 11 + }, { + Identity: 'foo-other4', + Type: 12 + }]; + var expectedUserAttributes = { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + window.mParticle.getInstance().Identity.getCurrentUser = function () { + return { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return consentState; + } + }; + }; + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + expect(sdkEvent).to.be.ok; + expect(sdkEvent.UserIdentities).to.eql(expectedUserIdentities); + expect(sdkEvent.MPID).to.equal('98765'); + expect(sdkEvent.UserAttributes).to.eql(expectedUserAttributes); + expect(sdkEvent.ConsentState).to.be.ok; + done(); + }); + it('Should append identities when user is present', function (done) { + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + sdkEvent.should.be.ok; + expect(sdkEvent.UserIdentities).to.eql([]); + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4', + not_a_valid_id: 'foo' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return null; + }, + getMPID: function getMPID() { + return null; + }, + getConsentState: function getConsentState() { + return null; + } + }; + var identityMapping = {}; + identityMapping[Types.IdentityType.CustomerId] = '1234567'; + identityMapping[Types.IdentityType.Email] = 'foo-email'; + identityMapping[Types.IdentityType.Other] = 'foo-other'; + identityMapping[Types.IdentityType.Other2] = 'foo-other2'; + identityMapping[Types.IdentityType.Other3] = 'foo-other3'; + identityMapping[Types.IdentityType.Other4] = 'foo-other4'; + mParticle$3.getInstance()._ServerModel.appendUserInfo(user, sdkEvent); + sdkEvent.UserIdentities.should.be.ok; + sdkEvent.UserIdentities.length.should.equal(6); + sdkEvent.UserIdentities.forEach(function (id) { + var type = id.Type; + var value = id.Identity; + identityMapping[type].should.equal(value); + }); + done(); + }); + it('Should append user attributes when user present', function (done) { + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + sdkEvent.should.be.ok; + expect(sdkEvent.UserAttributes).to.eql({}); + var attributes = { + foo: 'bar', + 'foo-arr': ['bar1', 'bar2'] + }; + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: {} + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return attributes; + }, + getMPID: function getMPID() { + return null; + }, + getConsentState: function getConsentState() { + return null; + } + }; + mParticle$3.getInstance()._ServerModel.appendUserInfo(user, sdkEvent); + expect(sdkEvent.UserAttributes).to.be.ok; + expect(sdkEvent.UserAttributes).to.eql(attributes); + done(); + }); + it('Should update mpid when user info is appended with a new mpid', function (done) { + var sdkEvent = mParticle$3.getInstance()._ServerModel.createEventObject(event); + sdkEvent.should.be.ok; + // By default, all tests instances have 'testMPID' + expect(sdkEvent.MPID).to.equal('testMPID'); + // TODO: this makes the compiler angry unless we make it hacky + var user = { + getUserIdentities: function getUserIdentities() { + return { + userIdentites: {} + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return null; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + mParticle$3.getInstance()._ServerModel.appendUserInfo(user, sdkEvent); + expect(sdkEvent.MPID).to.equal('98765'); + done(); + }); + it('convertEventToDTO should contain launch referral', function (done) { + var event = { + EventName: 10, + EventAttributes: null, + SourceMessageId: '7efa0811-c716-4a1d-b8bf-dae90242849c', + EventDataType: 10, + CustomFlags: {}, + IsFirstRun: false, + LaunchReferral: 'http://foo.bar/this/is/a/test', + CurrencyCode: null, + MPID: 'testMPID', + ConsentState: null, + UserAttributes: {}, + UserIdentities: [], + Store: {}, + SDKVersion: '2.14.0', + SessionId: '43E9CB7B-A533-48A0-9D34-A9D51A4986F1', + SessionStartDate: 1630528189521, + Debug: false, + Location: null, + OptOut: null, + ExpandedEventCount: 0, + ClientGeneratedId: 'abbaac60-6356-4cdb-88ab-ac63ffdc7b11', + DeviceId: 'f0164e59-ffe2-4c01-bd82-b1267096f8a1', + IntegrationAttributes: {}, + DataPlan: {}, + Timestamp: 1630528218899 + }; + var upload = mParticle$3.getInstance()._ServerModel.convertEventToV2DTO(event); + expect(upload.lr).to.equal('http://foo.bar/this/is/a/test'); + done(); + }); + }); + }); - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) - * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": - * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` - * - Edge <=13 === "[object Object]" - */ - if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { - return 'Array Iterator'; - } + describe('Create a batch from a base event', function () { + var batchValidator = new _BatchValidator(); + var baseEvent = { + messageType: 4, + name: 'testEvent' + }; + it('creates a batch with base event ', function (done) { + var batch = batchValidator.returnBatch(baseEvent); + expect(batch).to.have.property('environment').equal('production'); + expect(batch).to.have.property('source_request_id').equal('mockId'); + expect(batch).to.have.property('mpid').equal('0'); + expect(batch).to.have.property('timestamp_unixtime_ms'); + expect(batch).to.have.property('mp_deviceid'); + expect(batch).to.have.property('sdk_version'); + expect(batch).to.have.property('application_info'); + expect(batch).to.have.property('device_info'); + expect(batch).to.have.property('user_attributes'); + expect(batch).to.have.property('user_identities'); + expect(batch).to.have.property('consent_state'); + expect(batch).to.have.property('integration_attributes'); + expect(batch).to.have.property('events'); + expect(batch.events[0]).to.have.property('event_type', 'custom_event'); + expect(batch.events[0]).to.have.property('data'); + expect(batch.events[0].data).to.have.property('custom_event_type', 'unknown'); + expect(batch.events[0].data).to.have.property('custom_flags'); + expect(batch.events[0].data).to.have.property('event_name', 'testEvent'); + expect(batch.events[0].data).to.have.property('timestamp_unixtime_ms'); + expect(batch.events[0].data).to.have.property('session_uuid', 'mockSessionId'); + expect(batch.events[0].data).to.have.property('session_start_unixtime_ms'); + expect(batch.events[0].data).to.have.property('custom_attributes'); + expect(batch.events[0].data).to.have.property('location'); + baseEvent.eventType = 1; + batch = batchValidator.returnBatch(baseEvent); + expect(batch.events[0].data).to.have.property('custom_event_type', 'navigation'); + baseEvent.data = { + attrFoo: 'attrBar' + }; + batch = batchValidator.returnBatch(baseEvent); + expect(batch.events[0].data).to.have.property('custom_attributes'); + expect(batch.events[0].data.custom_attributes).to.have.property('attrFoo', 'attrBar'); + baseEvent.customFlags = { + flagFoo: 'flagBar' + }; + batch = batchValidator.returnBatch(baseEvent); + expect(batch.events[0].data).to.have.property('custom_flags'); + expect(batch.events[0].data.custom_flags).to.have.property('flagFoo', 'flagBar'); + done(); + }); + }); - /* ! Spec Conformance - * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) - * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": - * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` - * - Edge <=13 === "[object Object]" - */ - if (stringIteratorExists && objPrototype === stringIteratorPrototype) { - return 'String Iterator'; - } + var forwarderDefaultConfiguration = TestsCore.forwarderDefaultConfiguration, + MockForwarder = TestsCore.MockForwarder; + var mockServer$3; + describe('mParticleUser', function () { + beforeEach(function () { + // TODO - for some reason when these MPIDs are all testMPID, the following test breaks: + // onIdentifyComplete/onLoginComplete/onLogoutComplete/onModifyComplete + mockServer$3 = sinon$1.createFakeServer(); + mockServer$3.respondImmediately = true; + mockServer$3.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'testtest', + is_logged_in: false + })]); + mockServer$3.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'testtest', + is_logged_in: false + })]); + mockServer$3.respondWith(urls.logout, [200, {}, JSON.stringify({ + mpid: 'testtest', + is_logged_in: false + })]); + mockServer$3.respondWith('https://identity.mparticle.com/v1/testtest/modify', [200, {}, JSON.stringify({ + mpid: 'testtest', + is_logged_in: false + })]); + }); + afterEach(function () { + mockServer$3.restore(); + }); + it('should call forwarder onUserIdentified method with a filtered user identity list', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration('MockForwarder', 1); + config1.userIdentityFilters = [4], window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var userIdentityRequest = { + userIdentities: { + google: 'test', + customerid: 'id1', + other: 'id2' + } + }; + mParticle.Identity.login(userIdentityRequest); + window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.not.have.property('google'); + window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.have.property('customerid', 'id1'); + window.MockForwarder1.instance.onUserIdentifiedUser.getUserIdentities().userIdentities.should.have.property('other', 'id2'); + done(); + }); + it('should call forwarder onUserIdentified method with a filtered user attributes list', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration('MockForwarder', 1); + config1.userAttributeFilters = [mParticle.generateHash('gender')]; + window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var userIdentityRequest = { + userIdentities: { + google: 'test', + customerid: 'id1', + other: 'id2' + } + }; + mParticle.Identity.login(userIdentityRequest); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle.Identity.login(userIdentityRequest); + window.MockForwarder1.instance.onUserIdentifiedUser.getAllUserAttributes().should.not.have.property('gender'); + window.MockForwarder1.instance.onUserIdentifiedUser.getAllUserAttributes().should.have.property('color', 'blue'); + done(); + }); + it('should call forwarder onIdentifyComplete/onLoginComplete/onLogoutComplete/onModifyComplete method with the proper identity method passed through', function (done) { + mParticle._resetForTests(MPConfig); + var mockForwarder = new MockForwarder(); + mockForwarder.register(window.mParticle.config); + var config1 = forwarderDefaultConfiguration('MockForwarder', 1); + config1.userAttributeFilters = [mParticle.generateHash('gender')], window.mParticle.config.kitConfigs.push(config1); + mParticle.init(apiKey, window.mParticle.config); + var userIdentityRequest = { + userIdentities: { + google: 'test', + customerid: 'id1', + other: 'id2' + } + }; + mParticle.Identity.getCurrentUser().setUserAttribute('color', 'blue'); + mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); + mParticle.Identity.login(userIdentityRequest); + window.MockForwarder1.instance.onLoginCompleteCalled.should.equal(true); + window.MockForwarder1.instance.onLoginCompleteUser.getAllUserAttributes().should.not.have.property('gender'); + window.MockForwarder1.instance.onLoginCompleteUser.getAllUserAttributes().should.have.property('color', 'blue'); + mParticle.Identity.logout(userIdentityRequest); + window.MockForwarder1.instance.onLogoutCompleteCalled.should.equal(true); + window.MockForwarder1.instance.onLogoutCompleteUser.getAllUserAttributes().should.not.have.property('gender'); + window.MockForwarder1.instance.onLogoutCompleteUser.getAllUserAttributes().should.have.property('color', 'blue'); + mParticle.Identity.modify(userIdentityRequest); + window.MockForwarder1.instance.onModifyCompleteCalled.should.equal(true); + window.MockForwarder1.instance.onModifyCompleteUser.getAllUserAttributes().should.not.have.property('gender'); + window.MockForwarder1.instance.onModifyCompleteUser.getAllUserAttributes().should.have.property('color', 'blue'); + mParticle.Identity.identify(userIdentityRequest); + window.MockForwarder1.instance.onIdentifyCompleteCalled.should.equal(true); + window.MockForwarder1.instance.onIdentifyCompleteUser.getAllUserAttributes().should.not.have.property('gender'); + window.MockForwarder1.instance.onIdentifyCompleteUser.getAllUserAttributes().should.have.property('color', 'blue'); + done(); + }); + }); - /* ! Speed optimisation - * Pre: - * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) - * Post: - * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) - */ - if (objPrototype === null) { - return 'Object'; - } + var findEventFromRequest$1 = TestsCore.findEventFromRequest, + findBatch = TestsCore.findBatch; + var mockServer$2; - return Object - .prototype - .toString - .call(obj) - .slice(toStringLeftSliceLength, toStringRightSliceLength); - } + // Calls to /config are specific to only the self hosting environment + describe('/config self-hosting integration tests', function () { + beforeEach(function () { + client.post(urls.events, 200); + mockServer$2 = sinon$1.createFakeServer(); + }); + afterEach(function () { + client.restore(); + sinon$1.restore(); + }); + it('queues events in the eventQueue while /config is in flight, then processes them afterwards with correct MPID', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.requestConfig = true; + window.mParticle.config.identifyRequest = { + userIdentities: { + google: 'google123' + } + }; - return typeDetect; + // start fake timer and mock server in order to mock when certain events happen + var clock = sinon$1.useFakeTimers(); + mockServer$2.autoRespond = true; + mockServer$2.autoRespondAfter = 100; + mockServer$2.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'identifyMPID', + is_logged_in: false + })]); + mockServer$2.respondWith(urls.config, [200, {}, JSON.stringify({})]); + mParticle.init(apiKey, window.mParticle.config); - }))); + // log event before config and identify come back + mParticle.logEvent('Test'); + var event = findEventFromRequest$1(client._calls, 'Test'); + Should(event).not.be.ok(); + + // config and identify now get triggered, which runs through the event queue + clock.tick(300); + event = findBatch(client._calls, 'Test'); + event.should.be.ok(); + event.mpid.should.equal('identifyMPID'); + mockServer$2.restore(); + clock.restore(); + window.mParticle.config.requestConfig = false; + done(); + }); + it('queued events contain login mpid instead of identify mpid when calling login immediately after mParticle initializes', function (done) { + var messages = []; + mParticle._resetForTests(MPConfig); + window.mParticle.config.requestConfig = true; + window.mParticle.config.logLevel = 'verbose'; + delete window.mParticle.config.workspaceToken; + mParticle.config.logger = { + verbose: function verbose(msg) { + messages.push(msg); + } + }; + window.mParticle.config.identifyRequest = { + userIdentities: { + google: 'google123' + } + }; + window.mParticle.config.identityCallback = function () { + mParticle.logEvent('identify callback event'); + }; - },{}]},{},[1]); + // start fake timer and mock server + var clock = sinon$1.useFakeTimers(); + mockServer$2.autoRespond = true; + mockServer$2.autoRespondAfter = 100; + mockServer$2.respondWith(urls.config, [200, {}, JSON.stringify({ + workspaceToken: 'workspaceTokenTest' + })]); + mockServer$2.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'identifyMPID', + is_logged_in: false + })]); + mockServer$2.respondWith(urls.login, [200, {}, JSON.stringify({ + mpid: 'loginMPID', + is_logged_in: false + })]); + mParticle.init(apiKey, window.mParticle.config); + // call login before mParticle.identify is triggered, which happens after config returns + mParticle.Identity.login({ + userIdentities: { + customerid: 'abc123' + } + }); + mParticle.logEvent('Test'); + + // config triggers, login triggers immediately before identify + clock.tick(300); + var event1 = findBatch(client._calls, 'Test'); + event1.mpid.should.equal('loginMPID'); + messages.indexOf('Parsing "login" identity response from server').should.be.above(0); + + // when login is in flight, identify will not run, but callback still will + messages.indexOf('Parsing "identify" identity response from server').should.equal(-1); + var event2 = findBatch(client._calls, 'identify callback event', false, mockServer$2); + event2.mpid.should.equal('loginMPID'); + mockServer$2.restore(); + clock.restore(); + localStorage.removeItem('mprtcl-v4_workspaceTokenTest'); + window.mParticle.config.requestConfig = false; + done(); + }); + it('cookie name has workspace token in it in self hosting mode after config fetch', function (done) { + mParticle._resetForTests(MPConfig); + window.mParticle.config.requestConfig = true; + window.mParticle.config.logLevel = 'verbose'; + delete window.mParticle.config.workspaceToken; + + // start fake timer and mock server + var clock = sinon$1.useFakeTimers(); + mockServer$2.autoRespond = true; + mockServer$2.autoRespondAfter = 100; + mockServer$2.respondWith(urls.config, [200, {}, JSON.stringify({ + workspaceToken: 'wtTest' + })]); + mParticle.init(apiKey, window.mParticle.config); + clock.tick(300); + var data = window.localStorage.getItem('mprtcl-v4_wtTest'); + (typeof data === 'string').should.equal(true); + mockServer$2.restore(); + clock.restore(); + window.mParticle.config.requestConfig = false; + done(); + }); + }); - var sinon$1 = sinon; - sinon.leakThreshold; - sinon.assert; - sinon.serverPrototype; - sinon.getFakes; - sinon.createStubInstance; - sinon.inject; - sinon.mock; - sinon.reset; - sinon.resetBehavior; - sinon.resetHistory; - sinon.restore; - sinon.restoreContext; - sinon.replace; - sinon.define; - sinon.replaceGetter; - sinon.replaceSetter; - sinon.spy; - sinon.stub; - sinon.fake; - sinon.useFakeTimers; - sinon.verify; - sinon.verifyAndRestore; - sinon.useFakeServer; - sinon.useFakeXMLHttpRequest; - sinon.usingPromise; - sinon.createSandbox; - sinon.match; - sinon.restoreObject; - sinon.expectation; - sinon.defaultConfig; - sinon.timers; - sinon.xhr; - sinon.FakeXMLHttpRequest; - sinon.fakeServer; - sinon.fakeServerWithClock; - sinon.createFakeServer; - sinon.createFakeServerWithClock; - sinon.addBehavior; - sinon.promise; + describe('Old model to batch model conversion', function () { + beforeEach(function () { + window.mParticle.init(apiKey, window.mParticle.config); + }); + afterEach(function () { + window.mParticle._resetForTests(MPConfig); + }); + var batchDataTests = [{ + devmode: false + }, { + devmode: true + }]; + batchDataTests.forEach(function (params) { + it('Batch level conversion ' + params, function (done) { + window.mParticle._resetForTests(MPConfig); + window.mParticle.config.appVersion = 'a version'; + window.mParticle.config.appName = 'a name'; + window.mParticle.init(apiKey, window.mParticle.config); + var batch = convertEvents(null, null, window.mParticle.getInstance()); + expect(batch).to.be["null"]; + batch = convertEvents(null, [], window.mParticle.getInstance()); + expect(batch).to.be["null"]; + window.mParticle.getInstance()._Store.sessionId = 'foo-session-id'; + window.mParticle.getInstance()._Store.isFirstRun = false; + window.mParticle.getInstance()._Store.devToken = 'foo token'; + window.mParticle.getInstance()._Store.deviceId = 'a device id'; + window.mParticle.getInstance()._Store.SDKConfig.isDevelopmentMode = params.devmode; + window.mParticle.getInstance().Identity.getCurrentUser = function () { + return { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + }; + var publicEvent = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + console.log(sdkEvent); + expect(sdkEvent).to.be.ok; + batch = convertEvents('123', [sdkEvent, sdkEvent], window.mParticle.getInstance()); + expect(batch).to.be.ok; + expect(batch.mpid).to.equal('123'); + expect(batch.environment).to.equal(params.devmode ? 'development' : 'production'); + expect(batch.application_info).to.be.ok; + expect(batch.application_info.application_version).to.equal('a version'); + expect(batch.application_info.application_name).to.equal('a name'); + expect(batch.mp_deviceid).to.equal('a device id'); + expect(batch.user_attributes).to.be.ok; + expect(batch.user_identities).to.be.ok; + expect(batch.events).to.be.ok; + expect(batch.events.length).to.equal(2); + var batchEvent = batch.events[0]; + expect(batchEvent).to.be.ok; + expect(batchEvent.data.event_name).to.equal('foo page'); + expect(batchEvent.data.custom_attributes).to.deep.equal({ + 'foo-attr': 'foo-val' + }); + expect(batchEvent.data.custom_event_type).to.equal('navigation'); + expect(batchEvent.data.custom_flags).to.deep.equal({ + 'foo-flag': 'foo-flag-val' + }); + expect(batchEvent.data.session_uuid).to.equal('foo-session-id'); + done(); + }); + }); + it('User attribute conversion ', function (done) { + window.mParticle.getInstance().Identity.getCurrentUser = function () { + return { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: {} + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + }; + var publicEvent = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + expect(sdkEvent).to.be.ok; + var batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.user_attributes).to.be.ok; + expect(batch.user_attributes).to.deep.equal({ + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }); + done(); + }); + it('Data Plan Context conversion', function (done) { + var publicEvent = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation + }; + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + sdkEvent.DataPlan = null; + var batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.undefined; + sdkEvent.DataPlan = {}; + batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.undefined; + sdkEvent.DataPlan = { + PlanId: null + }; + batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.undefined; + sdkEvent.DataPlan = { + PlanId: null, + PlanVersion: 2 + }; + batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.undefined; + sdkEvent.DataPlan = { + PlanId: "foo", + PlanVersion: null + }; + batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.ok; + expect(batch.context.data_plan).to.be.ok; + expect(batch.context.data_plan.plan_id).to.equal("foo"); + expect(batch.context.data_plan.plan_version).be.undefined; + sdkEvent.DataPlan = { + PlanId: "foo", + PlanVersion: 4 + }; + batch = convertEvents('123', [sdkEvent], window.mParticle.getInstance()); + expect(batch.context).to.be.ok; + expect(batch.context.data_plan).to.be.ok; + expect(batch.context.data_plan.plan_id).to.equal("foo"); + expect(batch.context.data_plan.plan_version).be.equal(4); + done(); + }); + it('User identity conversion ', function (done) { + window.mParticle.getInstance().Identity.getCurrentUser = function () { + return { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return null; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return null; + } + }; + }; + var publicEvent = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + expect(sdkEvent).to.be.ok; + var batch = convertEvents('123', [sdkEvent, sdkEvent], window.mParticle.getInstance()); + expect(batch.user_identities).to.be.ok; + expect(batch.user_identities.customer_id).to.equal('1234567'); + expect(batch.user_identities.email).to.equal('foo-email'); + expect(batch.user_identities.other).to.equal('foo-other'); + expect(batch.user_identities.other_id_2).to.equal('foo-other2'); + expect(batch.user_identities.other_id_3).to.equal('foo-other3'); + expect(batch.user_identities.other_id_4).to.equal('foo-other4'); + done(); + }); + var baseEventConversion = { + 1: dist.EventTypeEnum.sessionStart, + 2: dist.EventTypeEnum.sessionEnd, + 3: dist.EventTypeEnum.screenView, + 4: dist.EventTypeEnum.customEvent, + 5: dist.EventTypeEnum.crashReport, + 6: dist.EventTypeEnum.optOut, + 10: dist.EventTypeEnum.applicationStateTransition, + 16: dist.EventTypeEnum.commerceEvent + }; + Object.keys(baseEventConversion).forEach(function (key) { + it('Base Event Conversion ' + baseEventConversion[key], function (done) { + var event = convertEvent(null); + expect(event).to.be["null"]; + var publicEvent = { + messageType: null, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + var sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + event = convertEvent(sdkEvent); + expect(event).to.be["null"]; + publicEvent = { + messageType: parseInt(key + '', 10), + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject(publicEvent); + expect(sdkEvent).to.be.ok; + event = convertEvent(sdkEvent); + expect(event).to.be.ok; + expect(event.event_type).to.equal(baseEventConversion[key]); + done(); + }); + }); + it('Commerce Event Product Action convertion', function (done) { + var sdkEvent = { + EventName: 'eCommerce - Purchase', + EventCategory: 16, + EventAttributes: null, + SDKVersion: '2.9.10', + SourceMessageId: 'testSMID', + SessionId: '391D4CCE-E7F9-473E-B5CD-8566DEB17425', + SessionStartDate: 1569453582333, + EventDataType: 16, + Debug: true, + Location: null, + OptOut: null, + DeviceId: '47f10c9d-f962-4f8a-b92a-8add36f86078', + CurrencyCode: null, + MPID: '1053073459916128825', + ConsentState: null, + Timestamp: 1569453613501, + ProductAction: { + ProductActionType: 7, + ProductList: [{ + Name: 'item 1', + Sku: 'econ-1', + Price: 321, + Quantity: 1, + Brand: 'foo-brand', + Variant: 'foo-variant', + Category: 'foo-category', + Position: 1, + CouponCode: 'foo-coupon', + TotalAmount: 222, + Attributes: { + foo: 'bar', + foo2: 'bar2' + } + }, { + Name: 'item 2', + Sku: 'econ-2', + Price: 123, + Quantity: 2, + Brand: 'foo-brand', + Variant: 'foo-variant', + Category: 'foo-category', + Position: 2, + CouponCode: 'foo-coupon', + TotalAmount: 111, + Attributes: { + foo3: 'bar3', + foo4: 'bar4' + } + }], + TransactionId: 'foo-transaction-id', + TotalAmount: 430.01, + TaxAmount: 31 + }, + IsFirstRun: false + }; + var batch = convertEvents('1053073459916128825', [sdkEvent], window.mParticle.getInstance()); + expect(batch).to.be.ok; + expect(batch.mpid).to.equal(sdkEvent.MPID); + expect(batch.events.length).to.equal(1); + var event = batch.events[0]; + expect(event).to.be.ok; + expect(event.event_type).to.equal('commerce_event'); + expect(event.data.timestamp_unixtime_ms).to.equal(sdkEvent.Timestamp); + expect(event.data.session_start_unixtime_ms).to.equal(sdkEvent.SessionStartDate); + expect(event.data.product_action.action).to.equal('purchase'); + expect(event.data.product_action.products.length).to.equal(2); + for (var i = 0; i < event.data.product_action.products.length; i++) { + var product = event.data.product_action.products[i]; + var sdkProduct = sdkEvent.ProductAction.ProductList[i]; + expect(product.name).to.equal(sdkProduct.Name); + expect(product.id).to.equal(sdkProduct.Sku); + expect(product.price).to.equal(sdkProduct.Price); + expect(product.quantity).to.equal(sdkProduct.Quantity); + expect(product.brand).to.equal(sdkProduct.Brand); + expect(product.variant).to.equal(sdkProduct.Variant); + expect(product.category).to.equal(sdkProduct.Category); + expect(product.position).to.equal(sdkProduct.Position); + expect(product.coupon_code).to.equal(sdkProduct.CouponCode); + expect(product.total_product_amount).to.equal(sdkProduct.TotalAmount); + expect(product.custom_attributes).to.deep.equal(sdkProduct.Attributes); + } + done(); + }); + it('Media Event Conversion', function (done) { + var sdkEvent = { + EventName: "Pause Event", + EventCategory: 9, + EventDataType: 4, + EventAttributes: { + content_duration: '120000', + content_id: "1234567", + content_title: "My sweet sweet media", + content_type: "Video", + media_session_id: "07be2e14-7e05-4053-bcb5-94950365822d", + playhead_position: '7023.335999999999', + stream_type: "OnDemand" + }, + ConsentState: null, + CurrencyCode: null, + CustomFlags: {}, + DataPlan: {}, + Debug: true, + DeviceId: "0edd580e-d887-44e4-89ae-cd65aa0ee933", + Location: null, + MPID: "-8433569646818451201", + OptOut: null, + SDKVersion: "2.11.15", + SourceMessageId: 'testSMID', + SessionId: "64102C03-592F-440D-8BCC-1D27AAA6B188", + SessionStartDate: 1603211322698, + Timestamp: 1603212299414, + UserAttributes: {}, + UserIdentities: [], + IsFirstRun: true + }; + var batch = convertEvents('-8433569646818451201', [sdkEvent], window.mParticle.getInstance()); + expect(batch).to.be.ok; + expect(batch.events.length).to.equal(1); + var event = batch.events[0]; + expect(event).to.be.ok; + expect(event.event_type).to.equal('custom_event'); + expect(event.data.custom_event_type).to.equal('media'); + done(); + }); + }); - describe('helpers', function () { + var mParticle$2 = window.mParticle; + describe('Api Client', function () { beforeEach(function () { - mParticle.init(apiKey, window.mParticle.config); + mParticle$2.init(apiKey, mParticle$2.config); }); - it('should correctly validate an attribute value', function (done) { - var validatedString = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue('testValue1'); - var validatedNumber = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(1); - var validatedNull = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(null); - var validatedObject = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue({}); - var validatedArray = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue([]); - var validatedUndefined = mParticle.getInstance()._Helpers.Validators.isValidAttributeValue(undefined); - validatedString.should.be.ok(); - validatedNumber.should.be.ok(); - validatedNull.should.be.ok(); - validatedObject.should.not.be.ok(); - validatedArray.should.not.be.ok(); - validatedUndefined.should.not.be.ok(); + afterEach(function () { + mParticle$2._resetForTests(MPConfig); + }); + it('should update queued events with latest user info', function (done) { + var event = { + messageType: Types.MessageType.PageEvent, + name: 'foo page', + data: { + 'foo-attr': 'foo-val' + }, + eventType: Types.EventType.Navigation, + customFlags: { + 'foo-flag': 'foo-flag-val' + } + }; + expect(mParticle$2.getInstance()._Store).to.be.ok; + var sdkEvent1 = mParticle$2.getInstance()._ServerModel.createEventObject(event); + expect(sdkEvent1).to.be.ok; + expect(sdkEvent1.MPID).equal(null); + expect(sdkEvent1.UserAttributes).equal(null); + expect(sdkEvent1.UserIdentities).equal(null); + expect(sdkEvent1.ConsentState).equal(null); + var sdkEvent2 = mParticle$2.getInstance()._ServerModel.createEventObject(event); + expect(sdkEvent2).to.be.ok; + expect(sdkEvent2.MPID).equal(null); + expect(sdkEvent2.UserAttributes).equal(null); + expect(sdkEvent2.UserIdentities).equal(null); + expect(sdkEvent2.ConsentState).equal(null); + var consentState = mParticle$2.getInstance().Consent.createConsentState(); + consentState.addGDPRConsentState('foo', mParticle$2.getInstance().Consent.createGDPRConsent(true, 10, 'foo document', 'foo location', 'foo hardware id')); + mParticle$2.getInstance().Identity.getCurrentUser = function () { + return { + getUserIdentities: function getUserIdentities() { + return { + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4' + } + }; + }, + getAllUserAttributes: function getAllUserAttributes() { + return { + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'] + }; + }, + getMPID: function getMPID() { + return '98765'; + }, + getConsentState: function getConsentState() { + return consentState; + } + }; + }; + mParticle$2.getInstance()._APIClient.appendUserInfoToEvents(mParticle$2.Identity.getCurrentUser(), [sdkEvent1, sdkEvent2]); + expect(sdkEvent1.UserIdentities.length).to.equal(6); + expect(Object.keys(sdkEvent2.UserAttributes).length).to.equal(2); + expect(sdkEvent1.MPID).to.equal('98765'); + expect(sdkEvent1.ConsentState).to.not.equal(null); + expect(sdkEvent2.UserIdentities.length).to.equal(6); + expect(Object.keys(sdkEvent2.UserAttributes).length).to.equal(2); + expect(sdkEvent2.MPID).to.equal('98765'); + expect(sdkEvent2.ConsentState).to.not.equal(null); done(); }); - it('should return event name in warning when sanitizing invalid attributes', function (done) { - var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); - mParticle.logEvent('eventName', mParticle.EventType.Location, { - invalidValue: {} - }); - bond.called.should.eql(true); - bond.callCount.should.equal(1); - bond.getCalls()[0].args[0].should.eql("For 'eventName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); + }); + + var findEventFromRequest = TestsCore.findEventFromRequest; + var mockServer$1; + function returnEventForMPInstance(calls, apiKey, eventName) { + var requestsPerApiKey = calls.filter(function (call) { + return call[0].includes(apiKey); + }); + return findEventFromRequest(requestsPerApiKey, eventName); + } + describe('mParticle instance manager', function () { + it('has all public apis on it', function (done) { + mParticle.ProductActionType.should.have.properties(['Unknown', 'AddToCart', 'RemoveFromCart', 'Checkout', 'CheckoutOption', 'Click', 'ViewDetail', 'Purchase', 'Refund', 'AddToWishlist', 'RemoveFromWishlist', 'getName', 'getExpansionName']); + mParticle.CommerceEventType.should.have.properties(['ProductAddToCart', 'ProductRemoveFromCart', 'ProductCheckout', 'ProductCheckoutOption', 'ProductClick', 'ProductViewDetail', 'ProductPurchase', 'ProductRefund', 'PromotionView', 'PromotionClick', 'ProductAddToWishlist', 'ProductRemoveFromWishlist', 'ProductImpression']); + mParticle.EventType.should.have.properties(['Unknown', 'Navigation', 'Location', 'Search', 'Transaction', 'UserContent', 'UserPreference', 'Social', 'Other', 'Media', 'getName']); + mParticle.PromotionType.should.have.properties(['Unknown', 'PromotionView', 'PromotionClick', 'getName', 'getExpansionName']); + mParticle.IdentityType.should.have.properties(['Other', 'CustomerId', 'Facebook', 'Twitter', 'Google', 'Microsoft', 'Yahoo', 'Email', 'FacebookCustomAudienceId', 'Other2', 'Other3', 'Other4', 'isValid', 'getName', 'getIdentityType', 'getIdentityName']); + mParticle.Identity.should.have.properties(['HTTPCodes', 'identify', 'logout', 'login', 'modify', 'getCurrentUser', 'getUser', 'getUsers', 'aliasUsers', 'createAliasRequest']); + mParticle.Identity.HTTPCodes.should.have.properties(['noHttpCoverage', 'activeIdentityRequest', 'activeSession', 'validationIssue', 'nativeIdentityRequest', 'loggingDisabledOrMissingAPIKey', 'tooManyRequests']); + mParticle.eCommerce.should.have.properties(['Cart', 'setCurrencyCode', 'createProduct', 'createPromotion', 'createImpression', 'createTransactionAttributes', 'logCheckout', 'logProductAction', 'logPurchase', 'logPromotion', 'logImpression', 'logRefund', 'expandCommerceEvent']); + mParticle.Consent.should.have.properties(['createGDPRConsent', 'createCCPAConsent', 'createConsentState']); + mParticle.sessionManager.should.have.property('getSession'); + mParticle.should.have.properties(['Store', 'getDeviceId', 'generateHash', 'sessionManager', 'isIOS', 'Identity', 'IdentityType', 'EventType', 'CommerceEventType', 'PromotionType', 'ProductActionType', 'init', 'setLogLevel', 'reset', '_resetForTests', 'ready', 'getVersion', 'setAppVersion', 'getAppName', 'setAppName', 'getAppVersion', 'stopTrackingLocation', 'startTrackingLocation', 'setPosition', 'startNewSession', 'endSession', 'logBaseEvent', 'logEvent', 'logError', 'logLink', 'logForm', 'logPageView', 'Consent', 'eCommerce', 'setSessionAttribute', 'setOptOut', 'setIntegrationAttribute', 'getIntegrationAttributes', 'addForwarder', 'configurePixel', '_getActiveForwarders', '_getIntegrationDelays', '_setIntegrationDelay']); done(); }); - it('should return product name in warning when sanitizing invalid attributes', function (done) { - var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); - mParticle.eCommerce.createProduct('productName', 'sku', 1, 1, 'variant', 'category', 'brand', 'position', 'couponCode', { - invalidValue: {} + describe('multiple instances testing', function () { + before(function () { + // default instance event mock + client.post('https://jssdks.mparticle.com/v3/JS/apiKey1/events', 200); + client.post('https://jssdks.mparticle.com/v3/JS/apiKey2/events', 200); + client.post('https://jssdks.mparticle.com/v3/JS/apiKey3/events', 200); + }); + beforeEach(function () { + //remove each of the instance's localStorage + localStorage.removeItem('mprtcl-v4_wtTest1'); + localStorage.removeItem('mprtcl-v4_wtTest2'); + localStorage.removeItem('mprtcl-v4_wtTest3'); + localStorage.removeItem('mprtcl-prodv4_wtTest1'); + localStorage.removeItem('mprtcl-prodv4_wtTest2'); + localStorage.removeItem('mprtcl-prodv4_wtTest3'); + mParticle._resetForTests(MPConfig); + mockServer$1 = sinon$1.createFakeServer(); + mockServer$1.respondImmediately = true; + + //config default instance + mockServer$1.respondWith('https://jssdkcdns.mparticle.com/JS/v2/apiKey1/config?env=0', [200, {}, JSON.stringify({ + workspaceToken: 'wtTest1' + })]); + //config instance 2 + mockServer$1.respondWith('https://jssdkcdns.mparticle.com/JS/v2/apiKey2/config?env=0', [200, {}, JSON.stringify({ + workspaceToken: 'wtTest2' + })]); + //config instance 3 + mockServer$1.respondWith('https://jssdkcdns.mparticle.com/JS/v2/apiKey3/config?env=0', [200, {}, JSON.stringify({ + workspaceToken: 'wtTest3' + })]); + + // identity mock + mockServer$1.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: 'testMPID', + is_logged_in: false + })]); + window.mParticle.config.requestConfig = true; + delete window.mParticle.config.workspaceToken; + mParticle.init('apiKey1', window.mParticle.config); + mParticle.init('apiKey2', window.mParticle.config, 'instance2'); + mParticle.init('apiKey3', window.mParticle.config, 'instance3'); + }); + afterEach(function () { + mockServer$1.restore(); + }); + it('creates multiple instances with their own cookies', function (done) { + var cookies1 = window.localStorage.getItem('mprtcl-v4_wtTest1'); + var cookies2 = window.localStorage.getItem('mprtcl-v4_wtTest2'); + var cookies3 = window.localStorage.getItem('mprtcl-v4_wtTest3'); + cookies1.includes('apiKey1').should.equal(true); + cookies2.includes('apiKey2').should.equal(true); + cookies3.includes('apiKey3').should.equal(true); + done(); + }); + it('logs events to their own instances', function (done) { + mParticle.getInstance('default_instance').logEvent('hi1'); + mParticle.getInstance('instance2').logEvent('hi2'); + mParticle.getInstance('instance3').logEvent('hi3'); + var instance1Event = returnEventForMPInstance(client._calls, 'apiKey1', 'hi1'); + instance1Event.should.be.ok(); + var instance2Event = returnEventForMPInstance(client._calls, 'apiKey2', 'hi2'); + instance2Event.should.be.ok(); + var instance3Event = returnEventForMPInstance(client._calls, 'apiKey3', 'hi3'); + instance3Event.should.be.ok(); + var instance1EventsFail1 = returnEventForMPInstance(client._calls, 'apiKey1', 'hi2'); + Should(instance1EventsFail1).not.be.ok(); + var instance1EventsFail2 = returnEventForMPInstance(client._calls, 'apiKey1', 'hi3'); + Should(instance1EventsFail2).not.be.ok(); + var instance2EventsFail1 = returnEventForMPInstance(client._calls, 'apiKey2', 'hi1'); + Should(instance2EventsFail1).not.be.ok(); + var instance2EventsFail2 = returnEventForMPInstance(client._calls, 'apiKey2', 'hi3'); + Should(instance2EventsFail2).not.be.ok(); + var instance3EventsFail1 = returnEventForMPInstance(client._calls, 'apiKey3', 'hi1'); + Should(instance3EventsFail1).not.be.ok(); + var instance3EventsFail2 = returnEventForMPInstance(client._calls, 'apiKey3', 'hi2'); + Should(instance3EventsFail2).not.be.ok(); + done(); + }); + it('logs purchase events to their own instances', function (done) { + var prodattr1 = { + journeyType: 'testjourneytype1', + eventMetric1: 'metric2' + }; + var prodattr2 = { + 'hit-att2': 'hit-att2-type', + prodMetric1: 'metric1' + }; + var product1 = mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999, 1, 'variant', 'category', 'brand', 1, 'coupon', prodattr1); + var product2 = mParticle.eCommerce.createProduct('galaxy', 'galaxySKU', 799, 1, 'variant', 'category', 'brand', 1, 'coupon', prodattr2); + var ta = mParticle.eCommerce.createTransactionAttributes('TAid1', 'aff1', 'coupon', 1798, 10, 5); + mParticle.getInstance().eCommerce.logPurchase(ta, [product1, product2]); + var instance1Event = returnEventForMPInstance(client._calls, 'apiKey1', 'purchase'); + var instance2Event = returnEventForMPInstance(client._calls, 'apiKey2', 'purchase'); + var instance3Event = returnEventForMPInstance(client._calls, 'apiKey3', 'purchase'); + instance1Event.should.be.ok(); + Should(instance2Event).not.be.ok(); + Should(instance3Event).not.be.ok(); + mParticle.getInstance('instance2').eCommerce.logPurchase(ta, [product1, product2]); + instance2Event = returnEventForMPInstance(client._calls, 'apiKey2', 'purchase'); + instance3Event = returnEventForMPInstance(client._calls, 'apiKey3', 'purchase'); + instance2Event.should.be.ok(); + Should(instance3Event).not.be.ok(); + mParticle.getInstance('instance3').eCommerce.logPurchase(ta, [product1, product2]); + instance3Event = returnEventForMPInstance(client._calls, 'apiKey3', 'purchase'); + instance3Event.should.be.ok(); + done(); }); - bond.called.should.eql(true); - bond.callCount.should.equal(1); - bond.getCalls()[0].args[0].should.eql("For 'productName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); - done(); }); - it('should return commerce event name in warning when sanitizing invalid attributes', function (done) { - var bond = sinon$1.spy(mParticle.getInstance().Logger, 'warning'); - var product1 = mParticle.eCommerce.createProduct('prod1', 'prod1sku', 999); - var product2 = mParticle.eCommerce.createProduct('prod2', 'prod2sku', 799); - var customAttributes = { - invalidValue: {} + }); + + describe('Queue Public Methods', function () { + var mockServer; + beforeEach(function () { + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + mockServer.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); + }); + afterEach(function () { + mockServer.reset(); + mParticle._resetForTests(MPConfig); + }); + describe('mParticle Core', function () { + describe('#isInitialized', function () { + it('should be a valid method on both mParticle and mParticle.getInstance() objects', function () { + mParticle.should.have.property('isInitialized'); + mParticle.getInstance().should.have.property('isInitialized'); + }); + it('should return false if not yet initialized, and true after initialization', function () { + mParticle.isInitialized().should.equal(false); + mParticle.getInstance().isInitialized().should.equal(false); + window.mParticle.init(apiKey, window.mParticle.config); + mParticle.isInitialized().should.equal(true); + mParticle.getInstance().isInitialized().should.equal(true); + }); + }); + describe('#setAppVersion', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setAppVersion('1.2.3'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setAppVersion('1.2.3'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#setAppName', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setAppName('Timmy'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setAppName('Timmy'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#ready', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.ready(function () { + console.log('fired ready function'); + }); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.ready(function () { + console.log('fired ready function'); + }); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#setPosition', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setPosition(10, 4); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setPosition(10, 4); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logBaseEvent', function () { + it('should queue if not initialized', function () { + var event = { + name: 'test event' + }; + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logBaseEvent(event); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + var event = { + name: 'test event' + }; + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logBaseEvent(event); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logEvent', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logEvent('Test Event'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logEvent('Test Event'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logError', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logError('test error', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logError('test error', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logPageView', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logPageView('test page view', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.logPageView('test page view', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#setOptOut', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setOptOut(true); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setOptOut(true); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#setIntegrationAttribute', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setIntegrationAttribute('12345', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setIntegrationAttribute('12345', {}); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#setSessionAttribute', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setSessionAttribute('foo', 'bar'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.setSessionAttribute('foo', 'bar'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#isInitialized', function () { + it('returns true when Store is initialized', function () { + mParticle.getInstance().isInitialized().should.be["false"](); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance().isInitialized().should.be["true"](); + }); + }); + }); + describe('mParticle.eCommerce', function () { + describe('#setCurrencyCode', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.setCurrencyCode('USD'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.setCurrencyCode('USD'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logProductAction', function () { + it('should queue if not initialized', function () { + var product = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logProductAction(SDKProductActionType.Purchase, product); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + var product = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logProductAction(SDKProductActionType.Purchase, product); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logPromotion', function () { + it('should queue if not initialized', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logPromotion('Test'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logPromotion('Test'); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + describe('#logImpression', function () { + it('should queue if not initialized', function () { + var product = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + var impression = window.mParticle.eCommerce.createImpression('iphone impression', product); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logImpression(impression); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + }); + it('should process queue after initialization', function () { + var product = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); + var impression = window.mParticle.eCommerce.createImpression('iphone impression', product); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + mParticle.eCommerce.logImpression(impression); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); + mParticle.init(apiKey, window.mParticle.config); + mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); + }); + }); + }); + }); + + var Validators = { + // From ./utils + // Utility Functions for backwards compatability + isNumber: isNumber, + isFunction: isFunction, + isStringOrNumber: isStringOrNumber, + // Validator Functions + isValidAttributeValue: function isValidAttributeValue(value) { + return value !== undefined && !isObject(value) && !Array.isArray(value); + }, + // Validator Functions + // Neither null nor undefined can be a valid Key + isValidKeyValue: function isValidKeyValue(key) { + return Boolean(key && !isObject(key) && !Array.isArray(key) && !this.isFunction(key)); + }, + validateIdentities: function validateIdentities(identityApiData, method) { + var validIdentityRequestKeys = { + userIdentities: 1, + onUserAlias: 1, + copyUserAttributes: 1 }; - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, [product1, product2], customAttributes); - bond.called.should.eql(true); - bond.callCount.should.equal(1); - bond.getCalls()[0].args[0].should.eql("For 'eCommerce - AddToCart', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null."); - done(); + if (identityApiData) { + if (method === 'modify') { + if (isObject(identityApiData.userIdentities) && !Object.keys(identityApiData.userIdentities).length || !isObject(identityApiData.userIdentities)) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.ModifyIdentityRequestUserIdentitiesPresent + }; + } + } + for (var key in identityApiData) { + if (identityApiData.hasOwnProperty(key)) { + if (!validIdentityRequestKeys[key]) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.IdentityRequesetInvalidKey + }; + } + if (key === 'onUserAlias' && !Validators.isFunction(identityApiData[key])) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.OnUserAliasType + }; + } + } + } + if (Object.keys(identityApiData).length === 0) { + return { + valid: true + }; + } else { + // identityApiData.userIdentities can't be undefined + if (identityApiData.userIdentities === undefined) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.UserIdentities + }; + // identityApiData.userIdentities can be null, but if it isn't null or undefined (above conditional), it must be an object + } else if (identityApiData.userIdentities !== null && !isObject(identityApiData.userIdentities)) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.UserIdentities + }; + } + if (isObject(identityApiData.userIdentities) && Object.keys(identityApiData.userIdentities).length) { + for (var identityType in identityApiData.userIdentities) { + if (identityApiData.userIdentities.hasOwnProperty(identityType)) { + if (Types.IdentityType.getIdentityType(identityType) === false) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidKey + }; + } + if (!(typeof identityApiData.userIdentities[identityType] === 'string' || identityApiData.userIdentities[identityType] === null)) { + return { + valid: false, + error: Constants.Messages.ValidationMessages.UserIdentitiesInvalidValues + }; + } + } + } + } + } + } + return { + valid: true + }; + } + }; + + describe('Validators', function () { + it('#isValidAttributeValue should correctly validate an attribute value', function () { + var validatedString = Validators.isValidAttributeValue('testValue1'); + var validatedNumber = Validators.isValidAttributeValue(1); + var validatedNull = Validators.isValidAttributeValue(null); + var validatedObject = Validators.isValidAttributeValue({}); + var validatedArray = Validators.isValidAttributeValue([]); + var validatedUndefined = Validators.isValidAttributeValue(undefined); + expect(validatedString).to.eq(true); + expect(validatedNumber).to.eq(true); + expect(validatedNull).to.eq(true); + expect(validatedObject).to.eq(false); + expect(validatedArray).to.eq(false); + expect(validatedUndefined).to.eq(false); + }); + it('#validateIdentities should properly validate identityApiRequest values', function () { + var badUserIdentitiesArray = { + userIdentities: { + customerid: [] + } + }; + var badUserIdentitiesObject = { + userIdentities: { + customerid: {} + } + }; + var badUserIdentitiesBoolean = { + userIdentities: { + customerid: false + } + }; + var badUserIdentitiesUndefined = { + userIdentities: { + customerid: undefined + } + }; + var validUserIdentitiesString = { + userIdentities: { + customerid: '123' + } + }; + var validUserIdentitiesNull = { + userIdentities: { + customerid: null + } + }; + var invalidUserIdentitiesCombo = { + userIdentities: { + customerid: '123', + email: undefined + } + }; + // Hiding from TS validation to make sure actual unit test works in JS + var badUserIdentitiesArrayResult = Validators.validateIdentities(badUserIdentitiesArray); + var badUserIdentitiesObjectResult = Validators.validateIdentities(badUserIdentitiesObject); + var badUserIdentitiesBooleanResult = Validators.validateIdentities(badUserIdentitiesBoolean); + var badUserIdentitiesUndefinedResult = Validators.validateIdentities(badUserIdentitiesUndefined); + var validUserIdentitiesNullResult = Validators.validateIdentities(validUserIdentitiesNull); + var validUserIdentitiesStringResult = Validators.validateIdentities(validUserIdentitiesString); + var invalidUserIdentitiesComboResult = Validators.validateIdentities(invalidUserIdentitiesCombo); + expect(badUserIdentitiesArrayResult.valid).to.eq(false); + expect(badUserIdentitiesObjectResult.valid).to.eq(false); + expect(badUserIdentitiesBooleanResult.valid).to.eq(false); + expect(badUserIdentitiesUndefinedResult.valid).to.eq(false); + expect(validUserIdentitiesNullResult.valid).to.eq(true); + expect(validUserIdentitiesStringResult.valid).to.eq(true); + expect(invalidUserIdentitiesComboResult.valid).to.eq(false); + }); + it('#isValidKeyValue should correctly validate a key value', function () { + expect(Validators.isValidKeyValue(42)).to.eq(true); + expect(Validators.isValidKeyValue('42')).to.eq(true); + expect(Validators.isValidKeyValue(null)).to.eq(false); + expect(Validators.isValidKeyValue(undefined)).to.eq(false); + expect(Validators.isValidKeyValue([])).to.eq(false); + expect(Validators.isValidKeyValue({})).to.eq(false); + expect(Validators.isValidKeyValue(function () {})).to.eq(false); + }); + it('#isStringOrNumber should correctly validate a string or number', function () { + expect(Validators.isStringOrNumber(42)).to.eq(true); + expect(Validators.isStringOrNumber('42')).to.eq(true); + expect(Validators.isStringOrNumber(null)).to.eq(false); + expect(Validators.isStringOrNumber(undefined)).to.eq(false); + expect(Validators.isStringOrNumber([])).to.eq(false); + expect(Validators.isStringOrNumber({})).to.eq(false); + expect(Validators.isStringOrNumber(function () {})).to.eq(false); + }); + it('#isNumber should correctly validate a number', function () { + expect(Validators.isNumber(42)).to.eq(true); + expect(Validators.isNumber('42')).to.eq(false); + expect(Validators.isNumber(null)).to.eq(false); + expect(Validators.isNumber(undefined)).to.eq(false); + expect(Validators.isNumber([])).to.eq(false); + expect(Validators.isNumber({})).to.eq(false); + expect(Validators.isNumber(function () {})).to.eq(false); + }); + it('#isFunction should correctly validate a function', function () { + expect(Validators.isFunction(42)).to.eq(false); + expect(Validators.isFunction('42')).to.eq(false); + expect(Validators.isFunction(null)).to.eq(false); + expect(Validators.isFunction(undefined)).to.eq(false); + expect(Validators.isFunction([])).to.eq(false); + expect(Validators.isFunction({})).to.eq(false); + expect(Validators.isFunction(function () {})).to.eq(true); + expect(Validators.isFunction(function () {})).to.eq(true); + }); + }); + + describe('Utils', function () { + describe('#createCookieString', function () { + it('should create a valid cookie string', function () { + var before = '{"cgid":"abc","das":"def","dt":"hij","ie":true,"les":1505932333024,"sid":"klm"}'; + var after = "{'cgid':'abc'|'das':'def'|'dt':'hij'|'ie':true|'les':1505932333024|'sid':'klm'}"; + expect(createCookieString(before)).to.equal(after); + }); + }); + describe('#revertCookieString', function () { + it('should create a revert cookie string', function () { + var before = '{"cgid":"abc","das":"def","dt":"hij","ie":true,"les":1505932333024,"sid":"klm"}'; + var after = "{'cgid':'abc'|'das':'def'|'dt':'hij'|'ie':true|'les':1505932333024|'sid':'klm'}"; + expect(revertCookieString(after)).to.equal(before); + }); + }); + describe('#generateHash', function () { + it('should a hash number with a valid input', function () { + expect(generateHash('A'), 'A').to.equal(97); + expect(generateHash('false')).to.equal(97196323); + expect(generateHash('3569038')).to.equal(-412991536); + expect(generateHash('TestHash')).to.equal(-1146196832); + expect(generateHash('mParticle'), 'mParticle String').to.equal(1744810483); + expect(generateHash('d71b49a6-4248-4581-afff-abb28dada53d')).to.equal(635757846); + }); + it('returns 0 when hashing undefined or null', function () { + expect(generateHash(null)).to.equal(0); + expect(generateHash(undefined)).to.equal(0); + // Use bad values to verify expected fail cases + expect(_typeof(generateHash(false))).to.equal('number'); + expect(generateHash(false)).to.not.equal(0); + }); + }); + describe('#generateUniqueId', function () { + it('generate a random value', function () { + expect(generateUniqueId()).to.be.ok; + expect(generateUniqueId().length).to.equal(36); + expect(_typeof(generateUniqueId())).to.equal('string'); + // Tests format to be broken up by 4 hyphens + expect(generateUniqueId().split('-').length).to.equal(5); + window.crypto.getRandomValues = undefined; + expect(generateUniqueId()).to.be.ok; + // old browsers may return undefined despite + // defining the getRandomValues API. + window.crypto.getRandomValues = function (a) { + a = undefined; + return a; + }; + expect(generateUniqueId()).to.be.ok; + }); + }); + describe('#getRampNumber', function () { + it('returns a ramp number', function () { + expect(getRampNumber()).to.equal(100); + expect(getRampNumber(null)).to.equal(100); + expect(getRampNumber('2b907d8b-cefe-4530-a6fe-60a381f2e066')).to.equal(60); + expect(getRampNumber('d71b49a6-4248-4581-afff-abb28dada53d')).to.equal(47); + var uniqueId = generateUniqueId(); + var result = getRampNumber(uniqueId); + expect(result).to.be.lessThan(101); + expect(result).to.be.greaterThan(0); + }); + }); + describe('#isObject', function () { + it('returns true if object is an object', function () { + var validObject = { + foo: 'bar', + fizz: 'buzz' + }; + expect(isObject(validObject)).to.eq(true); + }); + it('returns false if object is not an object', function () { + expect(isObject('not an object')).to.eq(false); + expect(isObject(42)).to.eq(false); + expect(isObject(null)).to.eq(false); + expect(isObject(undefined)).to.eq(false); + expect(isObject(false)).to.eq(false); + expect(isObject(true)).to.eq(false); + }); + }); + describe('#isStringOrNumber', function () { + it(' should correctly validate a string or number', function () { + expect(isStringOrNumber(42)).to.eq(true); + expect(isStringOrNumber('42')).to.eq(true); + expect(isStringOrNumber(null)).to.eq(false); + expect(isStringOrNumber(undefined)).to.eq(false); + expect(isStringOrNumber([])).to.eq(false); + expect(isStringOrNumber({})).to.eq(false); + expect(isStringOrNumber(function () {})).to.eq(false); + }); + }); + describe('#parseNumber', function () { + it('should parse a number into a number', function () { + expect(parseNumber('42')).to.eq(42); + expect(parseNumber('-42')).to.eq(-42); + expect(parseNumber('007')).to.eq(7); + expect(parseNumber(42)).to.eq(42); + expect(parseNumber(-42)).to.eq(-42); + expect(parseNumber('not an number')).to.eq(0); + expect(parseNumber('3.50')).to.eq(3.5); + }); + }); + describe('#parseStringOrNumber', function () { + it('should correctly parse string or number', function () { + expect(parseStringOrNumber('abc')).to.eq('abc'); + expect(parseStringOrNumber(123)).to.eq(123); + expect(parseStringOrNumber({})).to.eq(null); + expect(parseStringOrNumber([])).to.eq(null); + expect(parseStringOrNumber(null)).to.eq(null); + }); + }); + describe('#replaceCommasWithPipes', function () { + it('should replace commas with pipes', function () { + var pipes = '{"cgid":"abc"|"das":"def"|"dt":"hij"|"ie":true|"les":1505932333024|"sid":"klm"}'; + var commas = '{"cgid":"abc","das":"def","dt":"hij","ie":true,"les":1505932333024,"sid":"klm"}'; + expect(replaceCommasWithPipes(commas)).to.equal(pipes); + }); + }); + describe('#replacePipesWithCommas', function () { + it('should replace pipes with commas', function () { + var pipes = '{"cgid":"abc"|"das":"def"|"dt":"hij"|"ie":true|"les":1505932333024|"sid":"klm"}'; + var commas = '{"cgid":"abc","das":"def","dt":"hij","ie":true,"les":1505932333024,"sid":"klm"}'; + expect(replacePipesWithCommas(pipes)).to.equal(commas); + }); + }); + describe('#replaceApostrophesWithQuotes', function () { + it('should replace apostrophes with quotes', function () { + var quotes = '{"cgid":"abc"|"das":"def"|"dt":"hij"|"ie":true|"les":1505932333024|"sid":"klm"}'; + var apostrophes = "{'cgid':'abc'|'das':'def'|'dt':'hij'|'ie':true|'les':1505932333024|'sid':'klm'}"; + expect(replaceApostrophesWithQuotes(apostrophes)).to.equal(quotes); + }); + }); + describe('#replaceQuotesWithApostrophes', function () { + it('should replace quotes with apostrophes', function () { + var quotes = '{"cgid":"abc"|"das":"def"|"dt":"hij"|"ie":true|"les":1505932333024|"sid":"klm"}'; + var apostrophes = "{'cgid':'abc'|'das':'def'|'dt':'hij'|'ie':true|'les':1505932333024|'sid':'klm'}"; + expect(replaceQuotesWithApostrophes(quotes)).to.equal(apostrophes); + }); + }); + describe('#returnConvertedBoolean', function () { + it('returns expected boolean value when strings are passed', function () { + returnConvertedBoolean('false').should.equal(false); + returnConvertedBoolean(false).should.equal(false); + returnConvertedBoolean('true').should.equal(true); + returnConvertedBoolean('true').should.equal(true); + returnConvertedBoolean('randomstring').should.equal(true); + returnConvertedBoolean(0).should.equal(false); + returnConvertedBoolean(1).should.equal(true); + returnConvertedBoolean('0').should.equal(false); + returnConvertedBoolean('1').should.equal(true); + returnConvertedBoolean(null).should.equal(false); + returnConvertedBoolean(undefined).should.equal(false); + returnConvertedBoolean('').should.equal(false); + }); + }); + describe('#inArray', function () { + it('returns true if element is in the array', function () { + var things = ['people', 'places', 'things']; + expect(inArray(things, 'people')).to.eq(true); + }); + it('returns false if element is not in the array', function () { + var things = ['people', 'places', 'things']; + expect(inArray(things, 'cats')).to.eq(false); + }); + }); + describe('#findKeyInObject', function () { + it('returns the key if it exists in the object', function () { + var things = { + sunglasses: true, + suit: 'black', + music: 'blues' + }; + expect(findKeyInObject(things, 'music')).to.eq('music'); + }); + it('returns null if the key is not in the object', function () { + var things = { + sunglasses: true, + suit: 'black', + music: 'blues' + }; + expect(findKeyInObject(things, 'car')).to.be["null"]; + }); + }); + describe('#decoded', function () { + it('should replace pluses with spaces', function () { + expect(decoded$1('f++o+++o')).to.equal('f o o'); + }); + }); + describe('#converted', function () { + it('should convert cookie strings', function () { + var cookieString = "{'sid':'1992BDBB-AD74-49DB-9B20-5EC8037E72DE'|'ie':1|'ua':'eyJ0ZXN'0Ijoiwq7igJkifQ=='"; + expect(converted$1(cookieString)).to.eq("{\'sid\':\'1992BDBB-AD74-49DB-9B20-5EC8037E72DE\'|\'ie\':1|\'ua\':\'eyJ0ZXN\'0Ijoiwq7igJkifQ==\'"); + }); + }); + describe('#isDataPlanSlug', function () { + it('handles numbers', function () { + expect(isDataPlanSlug(35)).to.equal(false); + }); + it('handles spaces', function () { + expect(isDataPlanSlug('Slug with spaces in')).to.equal(false); + }); + it('handles PascalCase', function () { + // TODO: Remove support for kabob case once we remove slugify + expect(isDataPlanSlug('PascalSlug')).to.equal(true); + }); + it('handles kabob-case-slug', function () { + // TODO: Remove support for kabob case once we remove slugify + expect(isDataPlanSlug('kabob-case-slug')).to.equal(true); + }); + it('handles simple string', function () { + expect(isDataPlanSlug('slug')).to.equal(true); + }); + it('handles under_score_slug', function () { + expect(isDataPlanSlug('under_score_slug')).to.equal(true); + }); + it('handles numerical strings', function () { + expect(isDataPlanSlug('42')).to.equal(true); + }); + }); + describe('#isEmpty', function () { + it('returns true if array is empty', function () { + expect(isEmpty([])).to.equal(true); + }); + it('returns false if array is not empty', function () { + expect(isEmpty([1, 2, 3])).to.equal(false); + }); + it('returns true if object is empty', function () { + expect(isEmpty({})).to.equal(true); + }); + it('returns false if object is not empty', function () { + expect(isEmpty({ + 'foo': 'bar' + })).to.equal(false); + }); + it('returns true if object is null', function () { + expect(isEmpty(null)).to.equal(true); + }); + it('returns true if object is undefined', function () { + expect(isEmpty(undefined)).to.equal(true); + }); }); - it('should correctly validate an identity request with copyUserAttribute as a key using any identify method', function (done) { - var identityApiData = { - userIdentities: { - customerid: '123' - }, - copyUserAttributes: true - }; - var identifyResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'identify'); - var logoutResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'logout'); - var loginResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'login'); - var modifyResult = mParticle.getInstance()._Helpers.Validators.validateIdentities(identityApiData, 'modify'); - identifyResult.valid.should.equal(true); - logoutResult.valid.should.equal(true); - loginResult.valid.should.equal(true); - modifyResult.valid.should.equal(true); - done(); + }); + + var Messages = Constants.Messages; + var mockServer; + var mParticle$1 = window.mParticle; + describe('SessionManager', function () { + var now = new Date(); + var clock; + var sandbox; + beforeEach(function () { + sandbox = sinon$1.createSandbox(); + clock = sinon$1.useFakeTimers(now.getTime()); + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + mockServer.respondWith(urls.identify, [200, {}, JSON.stringify({ + mpid: testMPID, + is_logged_in: false + })]); }); - it('should correctly parse string or number', function (done) { - var string = 'abc'; - var number = 123; - var object = {}; - var array = []; - var stringResult = mParticle.getInstance()._Helpers.parseStringOrNumber(string); - var numberResult = mParticle.getInstance()._Helpers.parseStringOrNumber(number); - var objectResult = mParticle.getInstance()._Helpers.parseStringOrNumber(object); - var arrayResult = mParticle.getInstance()._Helpers.parseStringOrNumber(array); - var nullResult = mParticle.getInstance()._Helpers.parseStringOrNumber(null); - stringResult.should.equal(string); - numberResult.should.equal(number); - Should(objectResult).not.be.ok(); - Should(arrayResult).not.be.ok(); - Should(nullResult).not.be.ok(); - done(); + afterEach(function () { + sandbox.restore(); + clock.restore(); + mockServer.restore(); + mParticle$1._resetForTests(MPConfig); }); - it('should filterUserIdentities and include customerId as first in the array', function (done) { - var filterList = [2, 4, 6, 8]; - var userIdentitiesObject = { - email: 'test@gmail.com', - other: 'abc', - customerid: '123', - facebook: 'facebook123', - google: 'google123', - yahoo: 'yahoo123' - }; - var filteredIdentities = mParticle.getInstance()._Helpers.filterUserIdentities(userIdentitiesObject, filterList); - filteredIdentities.length.should.equal(3); - filteredIdentities[0].should.have.property('Identity', '123'); - filteredIdentities[0].should.have.property('Type', 1); - filteredIdentities[1].should.have.property('Identity', 'test@gmail.com'); - filteredIdentities[1].should.have.property('Type', 7); - filteredIdentities[2].should.have.property('Identity', 'abc'); - filteredIdentities[2].should.have.property('Type', 0); - done(); + describe('Unit Tests', function () { + describe('#initialize', function () { + beforeEach(function () { + // Change timeout to 10 minutes so we can make sure defaults are not in use + window.mParticle.config.sessionTimeout = 10; + }); + it('starts a new session if Store does not contain a sessionId', function () { + var generateUniqueIdSpy = sinon$1.stub(mParticle$1.getInstance()._Helpers, 'generateUniqueId'); + generateUniqueIdSpy.returns('test-unique-id'); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionId = ''; + expect(mpInstance._Store.sessionId).to.be.empty; + mpInstance._SessionManager.initialize(); + expect(mpInstance._Store.sessionId).to.equal('TEST-UNIQUE-ID'); + }); + it('ends the previous session and creates a new session if Store contains a sessionId and dateLastEventSent beyond the timeout window', function () { + var timePassed = 11 * MILLISECONDS_IN_ONE_MINUTE; + var generateUniqueIdSpy = sinon$1.stub(mParticle$1.getInstance()._Helpers, 'generateUniqueId'); + generateUniqueIdSpy.returns('test-unique-id'); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionId = 'OLD-ID'; + var timeLastEventSent = mpInstance._Store.dateLastEventSent.getTime(); + mpInstance._Store.dateLastEventSent = new Date(timeLastEventSent - timePassed); + mpInstance._SessionManager.initialize(); + expect(mpInstance._Store.sessionId).to.equal('TEST-UNIQUE-ID'); + }); + it('resumes the previous session if session ID exists and dateLastSent is within the timeout window', function () { + var timePassed = 8 * MILLISECONDS_IN_ONE_MINUTE; + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mParticle$1.getInstance()._Store.sessionId = 'OLD-ID'; + var timeLastEventSent = mpInstance._Store.dateLastEventSent.getTime(); + mpInstance._Store.dateLastEventSent = new Date(timeLastEventSent - timePassed); + mParticle$1.getInstance()._SessionManager.initialize(); + expect(mParticle$1.getInstance()._Store.sessionId).to.equal('OLD-ID'); + }); + }); + describe('#getSession', function () { + it('returns a Session ID from the Store', function () { + mParticle$1.init(apiKey, window.mParticle.config); + mParticle$1.getInstance()._Store.sessionId = 'foo'; + var sessionId = mParticle$1.getInstance()._SessionManager.getSession(); + expect(sessionId).to.equal('foo'); + }); + it('should log a deprecation message', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'warning'); + mpInstance._SessionManager.getSession(); + expect(consoleSpy.lastCall.firstArg).to.equal('SessionManager.getSession() is a deprecated method and will be removed in future releases SessionManager.getSessionId() is a deprecated method and will be removed in future releases'); + }); + }); + describe('#getSessionId', function () { + it('returns a Session ID from the Store', function () { + mParticle$1.init(apiKey, window.mParticle.config); + mParticle$1.getInstance()._Store.sessionId = 'foo'; + var sessionId = mParticle$1.getInstance()._SessionManager.getSessionId(); + expect(sessionId).to.equal('foo'); + }); + }); + describe('#startNewSession', function () { + it('should create a new session', function () { + var generateUniqueIdSpy = sinon$1.stub(mParticle$1.getInstance()._Helpers, 'generateUniqueId'); + generateUniqueIdSpy.returns('new-session-id'); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._SessionManager.startNewSession(); + expect(mpInstance._Store.sessionId).to.equal('NEW-SESSION-ID'); + expect(mpInstance._Store.sessionStartDate).to.eql(now); + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + }); + it('should log a session start event', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var eventSpy = sinon$1.spy(mpInstance._Events, 'logEvent'); + mpInstance._SessionManager.startNewSession(); + expect(eventSpy.getCalls().length).to.equal(1); + expect(eventSpy.getCall(0).firstArg).to.eql({ + messageType: MessageType$2.SessionStart + }); + }); + it('should start a session timer', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var timerSpy = sinon$1.spy(mpInstance._SessionManager, 'setSessionTimer'); + mpInstance._SessionManager.startNewSession(); + expect(timerSpy.getCalls().length).to.equal(1); + }); + it('should update sessionStartDate if it does not exist', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionStartDate = null; + mpInstance._SessionManager.startNewSession(); + expect(mpInstance._Store.sessionStartDate).to.eql(now); + }); + it('should NOT update sessionStartDate if one already exists', function () { + var dateInThePast = new Date(2015, 10, 21); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionStartDate = dateInThePast; + mpInstance._SessionManager.startNewSession(); + expect(mpInstance._Store.sessionStartDate).to.eql(dateInThePast); + }); + it('should update dateLastEventSent if sessionStartDate does not exist', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionStartDate = null; + mpInstance._SessionManager.startNewSession(); + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + }); + it('should NOT update dateLastEventSent if sessionStartDate already exists', function () { + var dateInThePast = new Date(2015, 10, 21); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionStartDate = dateInThePast; + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + mpInstance._SessionManager.startNewSession(); + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + }); + it('should call Identity.identify if Store.identifyCalled is false', function () { + // `init` already sends an identify request and resets the identity callback, + // To test this feature in isolation we will "reset" the identify + // request and callback after init so we can test startNewSession + // in isolation. + var identityApiData = { + userIdentities: { + customerid: 'my-customer-id' + } + }; + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var callbackSpy = sinon$1.spy(); + var identifySpy = sinon$1.spy(mpInstance.Identity, 'identify'); + mpInstance._Store.SDKConfig.identifyRequest = identityApiData; + mpInstance._Store.SDKConfig.identityCallback = callbackSpy; + mpInstance._Store.identifyCalled = false; + mpInstance._SessionManager.startNewSession(); + expect(identifySpy.getCall(0).args[0]).to.eql(identityApiData); + expect(identifySpy.getCall(0).args[1]).to.eql(callbackSpy); + expect(callbackSpy.called).to.equal(true); + expect(mpInstance._Store.identifyCalled).to.eql(true); + expect(mpInstance._Store.SDKConfig.identityCallback).to.eql(null); + }); + }); + describe('#endSession', function () { + it('should end a session', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var persistenceSpy = sinon$1.spy(mpInstance._Persistence, 'update'); + clock.tick(31 * MILLISECONDS_IN_ONE_MINUTE); + mpInstance._SessionManager.endSession(); + expect(mpInstance._Store.sessionId).to.equal(null); + expect(mpInstance._Store.dateLastEventSent).to.equal(null); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + // Persistence isn't necessary for this feature, but we should test + // to see that it is called in case this ever needs to be refactored + expect(persistenceSpy.called).to.equal(true); + }); + it('should force a session end when override is used', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var persistenceSpy = sinon$1.spy(mpInstance._Persistence, 'update'); + mpInstance._SessionManager.endSession(true); + expect(mpInstance._Store.sessionId).to.equal(null); + expect(mpInstance._Store.dateLastEventSent).to.equal(null); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + // Persistence isn't necessary for this feature, but we should test + // to see that it is called in case this ever needs to be refactored + expect(persistenceSpy.called).to.equal(true); + }); + it('should log StartingEndSession message and return early if Persistence is null', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns(null); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._SessionManager.endSession(); + // This path currently goes through the !cookies path, + // which doesn't really return anything except for logging the + // initial StartingEndSession message + expect(consoleSpy.getCall(0).firstArg).to.equal(Messages.InformationMessages.StartingEndSession); + // Should only log a single verbose log + expect(consoleSpy.getCalls().length).to.equal(1); + }); + it('should log a NoSessionToEnd Message if Persistence Exists but does not return an sid', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: {} + }); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._SessionManager.endSession(); + // Should log initial StartingEndSession and NoSessionToEnd messages + expect(consoleSpy.getCalls().length).to.equal(2); + expect(consoleSpy.lastCall.firstArg).to.equal(Messages.InformationMessages.NoSessionToEnd); + }); + it('should log an AbandonedEndSession message if SDK canLog() returns false', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: {} + }); + sinon$1.stub(mpInstance._Helpers, 'canLog').returns(false); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._SessionManager.endSession(); + // Should log initial StartingEndSession and AbandonEndSession messages + expect(consoleSpy.getCalls().length).to.equal(2); + expect(consoleSpy.lastCall.firstArg).to.equal(Messages.InformationMessages.AbandonEndSession); + }); + it('should log an AbandonedEndSession message if Store.isEnabled is false', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: {} + }); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._Store.isEnabled = false; + mpInstance._SessionManager.endSession(); + // Should log initial StartingEndSession and AbandonEndSession messagesk + expect(consoleSpy.getCalls().length).to.equal(2); + expect(consoleSpy.lastCall.firstArg).to.equal(Messages.InformationMessages.AbandonEndSession); + }); + it('should log AbandonEndSession message if webviewBridgeEnabled is false but Store.isEnabled is true and devToken is undefined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: {} + }); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._Store.isEnabled = true; + mpInstance._Store.webviewBridgeEnabled = false; + mpInstance._Store.devToken = undefined; + mpInstance._SessionManager.endSession(); + // Should log initial StartingEndSession and AbandonEndSession messages + expect(consoleSpy.getCalls().length).to.equal(2); + expect(consoleSpy.lastCall.firstArg).to.equal(Messages.InformationMessages.AbandonEndSession); + }); + it('should log NoSessionToEnd message if webviewBridgeEnabled and Store.isEnabled are true but devToken is undefined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: {} + }); + var consoleSpy = sinon$1.spy(mpInstance.Logger, 'verbose'); + mpInstance._Store.isEnabled = true; + mpInstance._Store.devToken = undefined; + mpInstance._Store.webviewBridgeEnabled = true; + mpInstance._SessionManager.endSession(); + // Should log initial StartingEndSession and NoSessionToEnd messages + expect(consoleSpy.getCalls().length).to.equal(2); + expect(consoleSpy.lastCall.firstArg).to.equal(Messages.InformationMessages.NoSessionToEnd); + }); + it('should prioritize cookie sessionId over Store.sessionId', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + sid: 'cookie-session-id' + } + }); + mpInstance._Store.sessionId = 'store-session-id'; + mpInstance._SessionManager.endSession(); + expect(mpInstance._Store.sessionId).to.equal('cookie-session-id'); + }); + it('should NOT end session if session has not timed out', function () { + var now = new Date(); + // The default timeout limit is 30 minutes. + var twentyMinutesAgo = new Date(); + twentyMinutesAgo.setMinutes(now.getMinutes() - 20); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var timerSpy = sinon$1.spy(mpInstance._SessionManager, 'setSessionTimer'); + // Session Manager relies on persistence to determine last event sent (LES) time + // Also requires sid to verify session exists + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + les: twentyMinutesAgo, + sid: 'fake-session-id' + } + }); + mpInstance._SessionManager.endSession(); + // We are verifying that the session has not ended, and therefore the + // session ID should still be the same, as opposed to null, which + // is assigned when the session actually ends + expect(mpInstance._Store.sessionId).to.equal('fake-session-id'); + // When session is not timed out, setSessionTimer is called to keep track + // of current session timeout + expect(timerSpy.getCalls().length).to.equal(1); + }); + it('should end session if the session timeout limit has been reached', function () { + var generateUniqueIdSpy = sinon$1.stub(mParticle$1.getInstance()._Helpers, 'generateUniqueId'); + generateUniqueIdSpy.returns('test-unique-id'); + var now = new Date(); + var twentyMinutesAgo = new Date(); + var hourAgo = new Date(); + twentyMinutesAgo.setMinutes(now.getMinutes() - 20); + hourAgo.setMinutes(now.getMinutes() - 60); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + expect(mpInstance._Store.sessionId).to.equal('TEST-UNIQUE-ID'); + // Init will set dateLastEventSent to now, but endSession relies on the persistence layer + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + var persistenceUpdateSpy = sinon$1.spy(mpInstance._Persistence, 'update'); + // Session Manager relies on persistence to determine last event seen (LES) time + // Also requires sid to verify session exists + var persistenceGetterStub = sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + les: twentyMinutesAgo, + sid: 'TEST-UNIQUE-ID' + } + }); + // Fire end session before sessionTimeout window has been reached + mpInstance._SessionManager.endSession(); + expect(mpInstance._Store.sessionId).to.equal('TEST-UNIQUE-ID'); + // Init will set dateLastEventSent to now, but endSession relies on the persistence layer + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + // Session Manager relies on persistence to determine last time seen (LES) + // Also requires sid to verify session exists + persistenceGetterStub.returns({ + gs: { + les: hourAgo, + sid: 'TEST-UNIQUE-ID' + } + }); + mpInstance._SessionManager.endSession(); + expect(mpInstance._Store.sessionId).to.equal(null); + expect(mpInstance._Store.dateLastEventSent).to.equal(null); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + // Persistence isn't necessary for this feature, but we should test + // to see that it is called in case this ever needs to be refactored + expect(persistenceUpdateSpy.called).to.equal(true); + }); + }); + describe('#setSessionTimer', function () { + it('should end a session after the timeout expires', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var endSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'endSession'); + // Start Timer + mpInstance._SessionManager.setSessionTimer(); + // Progress 29 minutes to make sure end session has not fired + clock.tick(29 * MILLISECONDS_IN_ONE_MINUTE); + expect(endSessionSpy.called).to.equal(false); + // Progress one minute to make sure end session fires + clock.tick(1 * MILLISECONDS_IN_ONE_MINUTE); + expect(endSessionSpy.called).to.equal(true); + }); + it('should set a global timer', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Manually clear global timer since it gets set during init + mpInstance._Store.globalTimer = null; + expect(mpInstance._Store.globalTimer).to.eq(null); + mpInstance._SessionManager.setSessionTimer(); + expect(mpInstance._Store.globalTimer).to.be.ok; + }); + }); + describe('#resetSessionTimer', function () { + it('should call startNewSession if sessionId is not defined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionId = null; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._SessionManager.resetSessionTimer(); + expect(startNewSessionSpy.called).to.equal(true); + }); + it('should NOT call startNewSession if sessionId is defined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.sessionId = 'test-session-id'; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._SessionManager.resetSessionTimer(); + expect(startNewSessionSpy.called).to.equal(false); + }); + it('should NOT restart a session if webviewBridgeEnabled is true', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.webviewBridgeEnabled = true; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + var clearSessionTimeoutSpy = sinon$1.spy(mpInstance._SessionManager, 'clearSessionTimeout'); + var setSessionTimerSpy = sinon$1.spy(mpInstance._SessionManager, 'setSessionTimer'); + mpInstance._SessionManager.resetSessionTimer(); + expect(startNewSessionSpy.called).to.equal(false); + expect(clearSessionTimeoutSpy.called).to.equal(false); + expect(setSessionTimerSpy.called).to.equal(false); + }); + it('should reset session timer by calling clearSessionTimeout and setSessionTimer', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var clearSessionTimeoutSpy = sinon$1.spy(mpInstance._SessionManager, 'clearSessionTimeout'); + var setSessionTimerSpy = sinon$1.spy(mpInstance._SessionManager, 'setSessionTimer'); + mpInstance._SessionManager.resetSessionTimer(); + expect(clearSessionTimeoutSpy.called).to.equal(true); + expect(setSessionTimerSpy.called).to.equal(true); + }); + it('should call startNewSessionIfNeeded', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + var startNewSessionIfNeededSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSessionIfNeeded'); + expect(startNewSessionIfNeededSpy.called).to.equal(false); + mpInstance._SessionManager.resetSessionTimer(); + expect(startNewSessionIfNeededSpy.called).to.equal(true); + }); + }); + describe('#clearSessionTimer', function () { + it('should call clearTimeout', function () { + var clearTimeoutSpy = sinon$1.spy(window, 'clearTimeout'); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + expect(clearTimeoutSpy.called).to.equal(false); + mpInstance._SessionManager.clearSessionTimeout(); + expect(clearTimeoutSpy.called).to.equal(true); + }); + }); + describe('startNewSessionIfNeeded', function () { + it('should call startNewSession if sessionId is not available from Persistence', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Session Manager relies on persistence check sid (Session ID) + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + sid: null + } + }); + mpInstance._Store.sessionId = null; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._SessionManager.startNewSessionIfNeeded(); + expect(startNewSessionSpy.called).to.equal(true); + }); + it('should NOT call startNewSession if sessionId is undefined and Persistence is undefined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Session Manager relies on persistence check sid (Session ID) + // However, if persistence is undefined, this will not create a + // new session + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns(null); + mpInstance._Store.sessionId = undefined; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._SessionManager.startNewSessionIfNeeded(); + expect(startNewSessionSpy.called).to.equal(false); + }); + it('should override Store.sessionId from Persistence', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Session Manager relies on persistence check sid (Session ID) + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + sid: 'sid-from-persistence' + } + }); + mpInstance._Store.sessionId = 'sid-from-store'; + mpInstance._SessionManager.startNewSessionIfNeeded(); + mpInstance._Store.sessionId = 'sid-from-persistence'; + }); + it('should set sessionId from Persistence if Store.sessionId is undefined', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Session Manager relies on persistence check sid (Session ID) + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + sid: 'sid-from-persistence' + } + }); + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._Store.sessionId = undefined; + mpInstance._SessionManager.startNewSessionIfNeeded(); + mpInstance._Store.sessionId = 'sid-from-persistence'; + expect(startNewSessionSpy.called).to.equal(true); + }); + it('should NOT call startNewSession if Store.sessionId and Persistence are null', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + // Session Manager relies on persistence check sid (Session ID) + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns(null); + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._Store.sessionId = null; + mpInstance._SessionManager.startNewSessionIfNeeded(); + expect(startNewSessionSpy.called).to.equal(false); + }); + it('should NOT call startNewSession if webviewBridgeEnabled is true', function () { + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + mpInstance._Store.webviewBridgeEnabled = true; + var startNewSessionSpy = sinon$1.spy(mpInstance._SessionManager, 'startNewSession'); + mpInstance._SessionManager.startNewSessionIfNeeded(); + expect(startNewSessionSpy.called).to.equal(false); + }); + }); }); - it('should return the appropriate boolean for if events should be delayed by an integration', function (done) { - var integrationDelays1 = { - 128: false, - 20: false, - 10: true - }; - var integrationDelays2 = { - 128: true - }; - var integrationDelays3 = { - 128: false - }; - var integrationDelays4 = { - 128: false, - 20: false, - 10: false - }; - var result1 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays1); - var result2 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays2); - var result3 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays3); - var result4 = mParticle.getInstance()._Helpers.isDelayedByIntegration(integrationDelays4); - result1.should.equal(true); - result2.should.equal(true); - result3.should.equal(false); - result4.should.equal(false); - done(); + describe('Integration Tests', function () { + it('should end a session if the session timeout expires', function () { + var generateUniqueIdSpy = sinon$1.stub(mParticle$1.getInstance()._Helpers, 'generateUniqueId'); + generateUniqueIdSpy.returns('test-unique-id'); + var now = new Date(); + mParticle$1.init(apiKey, window.mParticle.config); + var mpInstance = mParticle$1.getInstance(); + expect(mpInstance._Store.sessionId).to.equal('TEST-UNIQUE-ID'); + // Init will set dateLastEventSent to now, but endSession relies on the persistence layer + expect(mpInstance._Store.dateLastEventSent).to.eql(now); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + var persistenceSpy = sinon$1.spy(mpInstance._Persistence, 'update'); + // Session Manager relies on persistence to determine last time seen (LES) + // Also requires sid to verify session exists + sinon$1.stub(mpInstance._Persistence, 'getPersistence').returns({ + gs: { + les: now, + sid: 'fake-session-id' + } + }); + // trigger a session end + clock.tick(60 * MILLISECONDS_IN_ONE_MINUTE); + expect(mpInstance._Store.sessionId).to.equal(null); + expect(mpInstance._Store.dateLastEventSent).to.equal(null); + expect(mpInstance._Store.sessionAttributes).to.eql({}); + // Persistence isn't necessary for this feature, but we should test + // to see that it is called in case this ever needs to be refactored + expect(persistenceSpy.called).to.equal(true); + }); }); - it('should return false if integration delay object is empty', function (done) { - var emptyIntegrationDelays = {}; - var result1 = mParticle.getInstance()._Helpers.isDelayedByIntegration(emptyIntegrationDelays); - result1.should.equal(false); - done(); + }); + + var MockSideloadedKit = TestsCore.MockSideloadedKit; + describe('Store', function () { + var now = new Date(); + var sandbox; + var clock; + var sampleConfig = { + appName: 'Store Test', + appVersion: '1.x', + "package": 'com.mparticle.test' + }; + beforeEach(function () { + sandbox = sinon$1.createSandbox(); + clock = sinon$1.useFakeTimers(now.getTime()); + // MP Instance is just used because Store requires an mParticle instance + window.mParticle.init(apiKey, window.mParticle.config); }); - it('should return expected boolean value when strings are passed', function (done) { - mParticle.getInstance()._Helpers.returnConvertedBoolean('false').should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean(false).should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true); - mParticle.getInstance()._Helpers.returnConvertedBoolean('true').should.equal(true); - mParticle.getInstance()._Helpers.returnConvertedBoolean('randomstring').should.equal(true); - mParticle.getInstance()._Helpers.returnConvertedBoolean(0).should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean(1).should.equal(true); - mParticle.getInstance()._Helpers.returnConvertedBoolean('0').should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean('1').should.equal(true); - mParticle.getInstance()._Helpers.returnConvertedBoolean(null).should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean(undefined).should.equal(false); - mParticle.getInstance()._Helpers.returnConvertedBoolean('').should.equal(false); - done(); + afterEach(function () { + window.mParticle._resetForTests(MPConfig); + sandbox.restore(); + clock.restore(); }); - it('should return 0 when hashing undefined or null', function (done) { - mParticle.generateHash(undefined).should.equal(0); - mParticle.generateHash(null).should.equal(0); - _typeof(mParticle.generateHash(false)).should.equal('number'); - mParticle.generateHash(false).should.not.equal(0); - done(); + it('should initialize Store with defaults', function () { + // Use sample config to make sure our types are safe + var store = new Store(sampleConfig, window.mParticle); + expect(store).to.be.ok; + expect(store.isEnabled, 'isEnabled').to.eq(true); + expect(store.sessionAttributes, 'sessionAttributes').to.be.ok; + expect(store.currentSessionMPIDs, 'currentSessionMPIDs').to.be.ok; + expect(store.consentState, 'consentState').to.eq(null); + expect(store.sessionId, 'sessionId').to.eq(null); + expect(store.isFirstRun, 'isFirstRun').to.eq(null); + expect(store.clientId, 'clientId').to.eq(null); + expect(store.deviceId, 'deviceId').to.eq(null); + expect(store.devToken, 'devToken').to.eq(null); + expect(store.serverSettings, 'serverSettings').to.be.ok; + expect(store.dateLastEventSent, 'dateLastEventSent').to.eq(null); + expect(store.sessionStartDate, 'sessionStartDate').to.eq(null); + expect(store.currentPosition, 'currentPosition').to.eq(null); + expect(store.isTracking, 'isTracking').to.eq(false); + expect(store.watchPositionId, 'watchPositionId').to.eq(null); + expect(store.cartProducts.length, 'cartProducts').to.eq(0); + expect(store.eventQueue.length, 'eventQueue').to.eq(0); + expect(store.currencyCode, 'currencyCode').to.eq(null); + expect(store.globalTimer, 'globalTimer').to.eq(null); + expect(store.context, 'context').to.eq(null); + expect(store.configurationLoaded, 'configurationLoaded').to.eq(false); + expect(store.identityCallInFlight, 'identityCallInFlight').to.eq(false); + expect(store.nonCurrentUserMPIDs, 'nonCurrentUserMPIDs').to.be.ok; + expect(store.identifyCalled, 'identifyCalled').to.eq(false); + expect(store.isLoggedIn, 'isLoggedIn').to.eq(false); + expect(store.cookieSyncDates, 'cookieSyncDates').to.be.ok; + expect(store.integrationAttributes, 'integrationAttributes').to.be.ok; + expect(store.requireDelay, 'requireDelay').to.eq(true); + expect(store.isLocalStorageAvailable, 'isLocalStorageAvailable').to.eq(null); + expect(store.storageName, 'storageName').to.eq(null); + expect(store.prodStorageName, 'prodStorageName').to.eq(null); + expect(store.activeForwarders.length, 'activeForwarders').to.eq(0); + expect(store.kits, 'kits').to.be.ok; + expect(store.sideloadedKits, 'sideloaded kits').to.be.ok; + expect(store.configuredForwarders, 'configuredForwarders').to.be.ok; + expect(store.pixelConfigurations.length, 'pixelConfigurations').to.eq(0); + expect(store.integrationDelayTimeoutStart, 'integrationDelayTimeoutStart').to.eq(clock.now); }); - it('should generate random value', function (done) { - var randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); - randomValue.should.be.ok(); - window.crypto.getRandomValues = undefined; - randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); - randomValue.should.be.ok(); - //old browsers may return undefined despite - //defining the getRandomValues API. - window.crypto.getRandomValues = function (a) { - a = undefined; - return a; - }; - randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); - randomValue.should.be.ok(); - done(); + it('should initialize store.SDKConfig with valid defaults', function () { + var store = new Store(sampleConfig, window.mParticle); + expect(store.SDKConfig.aliasMaxWindow, 'aliasMaxWindow').to.eq(90); + expect(store.SDKConfig.aliasUrl, 'aliasUrl').to.eq('jssdks.mparticle.com/v1/identity/'); + expect(store.SDKConfig.appName).to.eq('Store Test'); + expect(store.SDKConfig.appVersion, 'appVersion').to.eq('1.x'); + expect(store.SDKConfig.cookieDomain, 'cookieDomain').to.eq(null); + expect(store.SDKConfig.configUrl, 'configUrl').to.eq('jssdkcdns.mparticle.com/JS/v2/'); + expect(store.SDKConfig.customFlags, 'customFlags').to.deep.equal({}); + expect(store.SDKConfig.dataPlan, 'dataPlan').to.deep.equal({}); + expect(store.SDKConfig.dataPlanOptions, 'dataPlanOptions').to.be.undefined; + expect(store.SDKConfig.dataPlanResult, 'dataPlanResult').to.be.undefined; + expect(store.SDKConfig.flags.eventBatchingIntervalMillis, 'flags.eventBatchingIntervalMillis').to.eq(0); + expect(store.SDKConfig.flags.reportBatching, 'flags.reportBatching').to.eq(false); + expect(store.SDKConfig.forceHttps, 'forceHttps').to.eq(true); + expect(store.SDKConfig.identityCallback, 'identityCallback').to.be.undefined; + expect(store.SDKConfig.identityUrl, 'identityUrl').to.eq('identity.mparticle.com/v1/'); + expect(store.SDKConfig.identifyRequest, 'identifyRequest').to.be.undefined; + expect(store.SDKConfig.integrationDelayTimeout, 'integrationDelayTimeout').to.eq(5000); + expect(store.SDKConfig.isDevelopmentMode, 'isDevelopmentMode').to.eq(false); + expect(store.SDKConfig.isIOS, 'isIOS').to.eq(false); + expect(store.SDKConfig.kits, 'kits').to.deep.equal({}); + expect(store.SDKConfig.sideloadedKits, 'kits').to.deep.equal([]); + expect(store.SDKConfig.logLevel, 'logLevel').to.eq(null); + expect(store.SDKConfig.maxCookieSize, 'maxCookieSize').to.eq(3000); + expect(store.SDKConfig.maxProducts, 'maxProducts').to.eq(20); + expect(store.SDKConfig.minWebviewBridgeVersion, 'minWebviewBridgeVersion').to.eq(1); + expect(store.SDKConfig["package"], 'package').to.eq('com.mparticle.test'); + expect(store.SDKConfig.sessionTimeout, 'sessionTimeout').to.eq(30); + expect(store.SDKConfig.useCookieStorage, 'useCookieStorage').to.eq(false); + expect(store.SDKConfig.useNativeSdk, 'useNativeSdk').to.eq(false); + expect(store.SDKConfig.v1SecureServiceUrl, 'v1SecureServiceUrl').to.eq('jssdks.mparticle.com/v1/JS/'); + expect(store.SDKConfig.v2SecureServiceUrl, 'v2SecureServiceUrl').to.eq('jssdks.mparticle.com/v2/JS/'); + expect(store.SDKConfig.v3SecureServiceUrl, 'v3SecureServiceUrl').to.eq('jssdks.mparticle.com/v3/JS/'); }); - it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in', function (done) { - var cookieName = mParticle.getInstance()._Helpers.createMainStorageName(apiKey); - cookieName.should.equal('mprtcl-v4_test_key'); - done(); + it('should assign expected values to dataPlan', function () { + var dataPlanConfig = __assign(__assign({}, sampleConfig), { + dataPlan: { + planId: 'test-data-plan', + planVersion: 3 + } + }); + var store = new Store(dataPlanConfig, window.mParticle); + expect(store.SDKConfig.dataPlan, 'dataPlan').to.deep.equal({ + PlanId: 'test-data-plan', + PlanVersion: 3 + }); }); - it('should create a storage name based on default mParticle storage version if no apiKey is passed in', function (done) { - var cookieName = mParticle.getInstance()._Helpers.createMainStorageName(); - cookieName.should.equal('mprtcl-v4'); - done(); + it('should assign expected values to side loaded kits', function () { + var sideloadedKit1 = new MockSideloadedKit(); + var sideloadedKit2 = new MockSideloadedKit(); + var sideloadedKits = [sideloadedKit1, sideloadedKit2]; + var config = __assign(__assign({}, sampleConfig), { + sideloadedKits: sideloadedKits + }); + var store = new Store(config, window.mParticle); + expect(store.SDKConfig.sideloadedKits.length, 'side loaded kits').to.equal(sideloadedKits.length); + expect(store.SDKConfig.sideloadedKits[0], 'side loaded kits').to.deep.equal(sideloadedKit1); + expect(store.SDKConfig.sideloadedKits[1], 'side loaded kits').to.deep.equal(sideloadedKit2); }); - it('should create a product storage name based on default mParticle storage version + apiKey if apiKey is passed in', function (done) { - var cookieName = mParticle.getInstance()._Helpers.createProductStorageName(apiKey); - cookieName.should.equal('mprtcl-prodv4_test_key'); - done(); + }); + + function ConfigAPIClient() { + this.getSDKConfiguration = function (apiKey, config, completeSDKInitialization, mpInstance) { + var url; + try { + var xhrCallback = function xhrCallback() { + if (xhr_1.readyState === 4) { + // when a 200 returns, merge current config with what comes back from config, prioritizing user inputted config + if (xhr_1.status === 200) { + config = mpInstance._Helpers.extend({}, config, JSON.parse(xhr_1.responseText)); + completeSDKInitialization(apiKey, config, mpInstance); + mpInstance.Logger.verbose('Successfully received configuration from server'); + } else { + // if for some reason a 200 doesn't return, then we initialize with the just the passed through config + completeSDKInitialization(apiKey, config, mpInstance); + mpInstance.Logger.verbose('Issue with receiving configuration from server, received HTTP Code of ' + xhr_1.status); + } + } + }; + var xhr_1 = mpInstance._Helpers.createXHR(xhrCallback); + url = 'https://' + mpInstance._Store.SDKConfig.configUrl + apiKey + '/config?env='; + if (config.isDevelopmentMode) { + url = url + '1'; + } else { + url = url + '0'; + } + var dataPlan = config.dataPlan; + if (dataPlan) { + if (dataPlan.planId) { + url = url + '&plan_id=' + dataPlan.planId || ''; + } + if (dataPlan.planVersion) { + url = url + '&plan_version=' + dataPlan.planVersion || ''; + } + } + if (xhr_1) { + xhr_1.open('get', url); + xhr_1.send(null); + } + } catch (e) { + completeSDKInitialization(apiKey, config, mpInstance); + mpInstance.Logger.error('Error getting forwarder configuration from mParticle servers.'); + } + }; + } + + describe('ConfigAPIClient', function () { + var mockServer; + var sdkInitCompleteCallback; + var configUrl; + var dataPlan; + var dataPlanResult; + beforeEach(function () { + mockServer = sinon$1.createFakeServer(); + mockServer.respondImmediately = true; + sdkInitCompleteCallback = sinon$1.spy(); + window.mParticle._resetForTests(MPConfig); }); - it('should create a product storage name based on default mParticle storage version if no apiKey is passed in', function (done) { - var cookieName = mParticle.getInstance()._Helpers.createProductStorageName(); - cookieName.should.equal('mprtcl-prodv4'); - done(); + afterEach(function () { + mockServer.reset(); + sinon$1.restore(); + }); + describe('#getSDKConfiguration', function () { + describe('with defaults', function () { + it('should fetch a config from the server', function () { + var config = { + requestConfig: true + }; + mockServer.respondWith(urls.config, [200, {}, JSON.stringify({ + appName: 'Test App', + kitConfigs: [] + })]); + window.mParticle.init(apiKey, config); + var configAPIClient = new ConfigAPIClient(); + configAPIClient.getSDKConfiguration(apiKey, config, sdkInitCompleteCallback, window.mParticle.getInstance()); + expect(sdkInitCompleteCallback.getCalls().length).to.equal(1); + expect(sdkInitCompleteCallback.calledWithMatch(apiKey, MPConfig, window.mParticle.getInstance())); + expect(mockServer.lastRequest).to.haveOwnProperty('response'); + // TODO: Check mockServer + expect(mockServer.lastRequest.url).to.equal(urls.config); + var configResponse = JSON.parse(mockServer.lastRequest.response); + expect(configResponse).to.be.ok; + expect(configResponse.appName).to.equal('Test App'); + expect(configResponse.kitConfigs).to.be.ok; + }); + it('should continue sdk init if fetch fails', function () { + var config = { + requestConfig: true + }; + mockServer.respondWith(urls.config, [400, {}, '']); + window.mParticle.init(apiKey, window.mParticle.config); + var configAPIClient = new ConfigAPIClient(); + configAPIClient.getSDKConfiguration(apiKey, config, sdkInitCompleteCallback, window.mParticle.getInstance()); + expect(sdkInitCompleteCallback.getCalls().length).to.equal(1); + expect(sdkInitCompleteCallback.calledWithMatch(apiKey, MPConfig, window.mParticle.getInstance())); + expect(mockServer.lastRequest).to.haveOwnProperty('response'); + expect(mockServer.lastRequest.url).to.equal(urls.config); + }); + }); + describe('with Data Plan', function () { + beforeEach(function () { + configUrl = "".concat(urls.config, "&plan_id=test_data_plan&plan_version=42"); + dataPlan = { + planId: 'test_data_plan', + planVersion: 42 + }; + dataPlanResult = { + dtpn: { + blok: { + ev: false, + ea: false, + ua: false, + id: false + }, + vers: { + version: 17, + data_plan_id: 'fake_data_plan', + last_modified_on: '2022-02-16T17:52:19.13Z', + version_document: { + data_points: [] + } + } + } + }; + mockServer.respondWith(configUrl, [200, {}, JSON.stringify({ + appName: 'Test App', + kitConfigs: [], + dataPlanResult: dataPlanResult + })]); + }); + it('appends data plan information to url', function () { + var config = { + requestConfig: true, + dataPlan: dataPlan + }; + window.mParticle.init(apiKey, window.mParticle.config); + var configAPIClient = new ConfigAPIClient(); + configAPIClient.getSDKConfiguration(apiKey, config, sdkInitCompleteCallback, window.mParticle.getInstance()); + expect(sdkInitCompleteCallback.getCalls().length).to.equal(1); + expect(sdkInitCompleteCallback.calledWithMatch(apiKey, MPConfig, window.mParticle.getInstance())); + expect(mockServer.lastRequest).to.haveOwnProperty('url'); + expect(mockServer.lastRequest.url).to.equal(configUrl); + }); + it('returns data plan information within the HTTP Response', function () { + var configUrl = "".concat(urls.config, "&plan_id=test_data_plan&plan_version=42"); + var config = { + requestConfig: true, + dataPlan: dataPlan + }; + window.mParticle.init(apiKey, window.mParticle.config); + var configAPIClient = new ConfigAPIClient(); + configAPIClient.getSDKConfiguration(apiKey, config, sdkInitCompleteCallback, window.mParticle.getInstance()); + expect(mockServer.lastRequest).to.haveOwnProperty('method'); + expect(mockServer.lastRequest).to.haveOwnProperty('response'); + expect(mockServer.lastRequest.method).to.equal('get'); + expect(mockServer.lastRequest.url).to.equal(configUrl); + var configResponse = JSON.parse(mockServer.lastRequest.response); + expect(configResponse).to.be.ok; + expect(configResponse.appName).to.equal('Test App'); + expect(configResponse.kitConfigs).to.be.ok; + expect(configResponse.dataPlanResult).to.be.ok; + }); + }); }); }); @@ -17991,25 +72542,5 @@ afterEach(function () { // window.fetchMock.restore(); }); - // import './tests-identity'; - // import './tests-event-logging'; - // import './tests-eCommerce'; - // import './tests-cookie-syncing'; - // import './tests-identities-attributes'; - // import './tests-native-sdk'; - // import './tests-consent'; - // import './tests-serverModel'; - // import './tests-mockBatchCreator.ts'; - // import './tests-mParticleUser'; - // import './tests-self-hosting-specific'; - // import './tests-runtimeToBatchEventsDTO'; - // import './tests-apiClient'; - // import './tests-mparticle-instance-manager'; - // import './tests-queue-public-methods'; - // import './tests-validators'; - // import './tests-utils'; - // import './tests-session-manager'; - // import './tests-store'; - // import './tests-config-api-client'; })); diff --git a/test/cross-browser-testing/browserstack.karma.config.js b/test/cross-browser-testing/browserstack.karma.config.js index 38987ed0..5b24629a 100644 --- a/test/cross-browser-testing/browserstack.karma.config.js +++ b/test/cross-browser-testing/browserstack.karma.config.js @@ -38,27 +38,27 @@ const customLaunchers = { // os: 'OS X', // os_version: 'Ventura' // }, - // bs_chrome_mac_100: { - // base: 'BrowserStack', - // browser: 'chrome', - // browser_version: '100.0', - // os: 'OS X', - // os_version: 'Ventura' - // }, - // These two browsers fail because they cannot run ES6 syntax. - // Our tests have some ES6 syntax in them, so we need to transpile the tests - // to get them to run properly. - bs_firefox_mac_34: { + bs_chrome_mac_100: { base: 'BrowserStack', - browser: 'firefox', - browser_version: '34.0', + browser: 'chrome', + browser_version: '100.0', os: 'OS X', - os_version: 'Snow Leopard' + os_version: 'Ventura' }, - // bs_chrome_mac_38: { + // These two browsers fail because they cannot run ES6 syntax. + // Our tests have some ES6 syntax in them, so we need to transpile the tests + // to get them to run properly. + // bs_firefox_mac_39: { + // base: 'BrowserStack', + // browser: 'firefox', + // browser_version: '39.0', + // os: 'OS X', + // os_version: 'Snow Leopard' + // }, + // bs_chrome_mac_40: { // base: 'BrowserStack', // browser: 'chrome', - // browser_version: '38.0', + // browser_version: '40.0', // os: 'OS X', // os_version: 'Mojave' // }, diff --git a/test/cross-browser-testing/rollup.CBT.config.js b/test/cross-browser-testing/rollup.CBT.config.js index 3bdd9672..e5571c70 100644 --- a/test/cross-browser-testing/rollup.CBT.config.js +++ b/test/cross-browser-testing/rollup.CBT.config.js @@ -116,7 +116,7 @@ export default [ presets: ['@babel/preset-env'], plugins: ['@babel/plugin-transform-runtime'], extensions, - // ...babelSettings, + ...babelSettings, exclude: ['node_modules/**/*'], babelHelpers: 'runtime', }), diff --git a/test/karma.config.js b/test/karma.config.js index a70d793b..73947713 100644 --- a/test/karma.config.js +++ b/test/karma.config.js @@ -2,7 +2,7 @@ const { DEBUG } = process.env; const files = [ 'lib/geomock.js', - '../node_modules/fetch-mock/dist/es5/client-bundle.js', + // '../node_modules/fetch-mock/dist/es5/client-bundle.js', '../dist/mparticle.js', 'test-bundle.js', ]; diff --git a/test/src/tests-batchUploader.ts b/test/src/tests-batchUploader.ts index e52047b0..eb6fb4a4 100644 --- a/test/src/tests-batchUploader.ts +++ b/test/src/tests-batchUploader.ts @@ -13,6 +13,8 @@ import { BatchUploader } from '../../src/batchUploader'; import { expect } from 'chai'; import _BatchValidator from '../../src/mockBatchCreator'; import Logger from '../../src/logger.js'; +import fetchMock from 'fetch-mock/esm/client'; + declare global { interface Window { mParticle: MParticleWebSDK; @@ -113,7 +115,7 @@ describe('batch uploader', () => { let clock; beforeEach(() => { - window.fetchMock.restore(); + fetchMock.restore(); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -126,7 +128,7 @@ describe('batch uploader', () => { afterEach(() => { mockServer.reset(); - window.fetchMock.restore(); + fetchMock.restore(); window.localStorage.clear(); }); @@ -212,11 +214,11 @@ describe('batch uploader', () => { window.mParticle.init(apiKey, window.mParticle.config); }); afterEach(() => { - window.fetchMock.restore(); + fetchMock.restore(); }); it('should reject batches without events', async () => { - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); const newLogger = new Logger(window.mParticle.config); const mpInstance = window.mParticle.getInstance(); @@ -241,10 +243,10 @@ describe('batch uploader', () => { false ); - expect(window.fetchMock.calls().length).to.equal(1); + expect(fetchMock.calls().length).to.equal(1); const actualBatchResult = JSON.parse( - window.fetchMock.calls()[0][1].body + fetchMock.calls()[0][1].body ); expect(actualBatchResult.events.length).to.equal(1); @@ -252,7 +254,7 @@ describe('batch uploader', () => { }); it('should return batches that fail to upload with 500 errors', async () => { - window.fetchMock.post(urls.events, 500); + fetchMock.post(urls.events, 500); const newLogger = new Logger(window.mParticle.config); const mpInstance = window.mParticle.getInstance(); @@ -299,7 +301,7 @@ describe('batch uploader', () => { }); it('should return batches that fail to upload with 429 errors', async () => { - window.fetchMock.post(urls.events, 429); + fetchMock.post(urls.events, 429); const newLogger = new Logger(window.mParticle.config); const mpInstance = window.mParticle.getInstance(); @@ -346,7 +348,7 @@ describe('batch uploader', () => { }); it('should return null if batches fail to upload with 401 errors', async () => { - window.fetchMock.post(urls.events, 401); + fetchMock.post(urls.events, 401); const newLogger = new Logger(window.mParticle.config); const mpInstance = window.mParticle.getInstance(); @@ -380,7 +382,7 @@ describe('batch uploader', () => { }); it('should return batches that fail to unknown HTTP errors', async () => { - window.fetchMock.post(urls.events, 400); + fetchMock.post(urls.events, 400); const newLogger = new Logger(window.mParticle.config); const mpInstance = window.mParticle.getInstance(); @@ -433,7 +435,7 @@ describe('batch uploader', () => { describe('Offline Storage Feature Flag', () => { beforeEach(() => { sinon.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mockServer.reset(); window.localStorage.clear(); @@ -441,7 +443,7 @@ describe('batch uploader', () => { }); afterEach(() => { sinon.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mockServer.reset(); window.localStorage.clear(); @@ -569,7 +571,7 @@ describe('batch uploader', () => { afterEach(() => { sinon.restore(); window.localStorage.clear(); - window.fetchMock.restore(); + fetchMock.restore(); clock.restore(); }); @@ -623,7 +625,7 @@ describe('batch uploader', () => { clock = sinon.useFakeTimers({ now: new Date().getTime(), }); - window.fetchMock.restore(); + fetchMock.restore(); window.sessionStorage.clear(); window.localStorage.clear(); @@ -631,7 +633,7 @@ describe('batch uploader', () => { afterEach(() => { sinon.restore(); - window.fetchMock.restore(); + fetchMock.restore(); clock.restore(); }); @@ -673,7 +675,7 @@ describe('batch uploader', () => { it('should purge events from Session Storage upon Batch Creation', (done) => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); @@ -722,7 +724,7 @@ describe('batch uploader', () => { it('should save batches in sequence to Local Storage when an HTTP 500 error is encountered', (done) => { const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.fetchMock.post(urls.events, 500); + fetchMock.post(urls.events, 500); window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); @@ -779,7 +781,7 @@ describe('batch uploader', () => { it('should save batches in sequence to Local Storage when an HTTP 429 error is encountered', (done) => { const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.fetchMock.post(urls.events, 429); + fetchMock.post(urls.events, 429); window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); @@ -834,7 +836,7 @@ describe('batch uploader', () => { // Offline Storage afterwards const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.fetchMock.post(urls.events, 401); + fetchMock.post(urls.events, 401); window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); @@ -870,13 +872,13 @@ describe('batch uploader', () => { const batchStorageKey = 'mprtcl-v4_abcdef-batches'; // First upload is successful - window.fetchMock.post(urls.events, 200, { + fetchMock.post(urls.events, 200, { overwriteRoutes: false, repeat: 1, }); // Second upload is rate limited - window.fetchMock.post(urls.events, 429, { + fetchMock.post(urls.events, 429, { overwriteRoutes: false, }); @@ -1015,7 +1017,7 @@ describe('batch uploader', () => { const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); // Set up SDK and Uploader window.mParticle._resetForTests(MPConfig); @@ -1082,19 +1084,19 @@ describe('batch uploader', () => { // To verify the sequence, we should look at what has been uploaded // as the upload queue and Offline Storage should be empty - expect(window.fetchMock.calls().length).to.equal(4); + expect(fetchMock.calls().length).to.equal(4); const uploadedBatch1: Batch = JSON.parse( - window.fetchMock.calls()[0][1].body + fetchMock.calls()[0][1].body ); const uploadedBatch2: Batch = JSON.parse( - window.fetchMock.calls()[1][1].body + fetchMock.calls()[1][1].body ); const uploadedBatch3: Batch = JSON.parse( - window.fetchMock.calls()[2][1].body + fetchMock.calls()[2][1].body ); const uploadedBatch4: Batch = JSON.parse( - window.fetchMock.calls()[3][1].body + fetchMock.calls()[3][1].body ); // The following assertions should verify the sequence presented below @@ -1162,7 +1164,7 @@ describe('batch uploader', () => { }); afterEach(() => { - window.fetchMock.restore(); + fetchMock.restore(); clock.restore(); }); @@ -1170,8 +1172,8 @@ describe('batch uploader', () => { // Batches should be uploaded in the order they were created to prevent // any potential corruption. - window.fetchMock.post(urls.events, 200); - window.fetchMock.config.overwriteRoutes = true; + fetchMock.post(urls.events, 200); + fetchMock.config.overwriteRoutes = true; window.mParticle.config.flags = { ...enableBatchingConfigFlags, @@ -1186,11 +1188,11 @@ describe('batch uploader', () => { window.mParticle.upload(); expect( - window.fetchMock.called(), + fetchMock.called(), 'FetchMock should have been called' ).to.equal(true); - const batch1 = JSON.parse(window.fetchMock._calls[0][1].body); + const batch1 = JSON.parse(fetchMock._calls[0][1].body); // Batch 1 should contain only session start, AST and a single event // in this exact order @@ -1209,7 +1211,7 @@ describe('batch uploader', () => { // Manually initiate the upload process - turn event into batches and upload the batch window.mParticle.upload(); - const batch2 = JSON.parse(window.fetchMock._calls[1][1].body); + const batch2 = JSON.parse(fetchMock._calls[1][1].body); // Batch 2 should contain three custom events expect(batch2.events.length).to.equal(3); @@ -1224,7 +1226,7 @@ describe('batch uploader', () => { // Manually initiate the upload process - turn event into batches and upload the batch window.mParticle.upload(); - const batch3 = JSON.parse(window.fetchMock._calls[2][1].body); + const batch3 = JSON.parse(fetchMock._calls[2][1].body); // Batch 3 should contain two custom events expect(batch3.events.length).to.equal(2); @@ -1240,7 +1242,7 @@ describe('batch uploader', () => { // If batches cannot upload, they should be added back to the Batch Queue // in the order they were created so they can be retransmitted. - window.fetchMock.post(urls.events, 500); + fetchMock.post(urls.events, 500); window.mParticle.config.flags = { ...enableBatchingConfigFlags, @@ -1257,11 +1259,11 @@ describe('batch uploader', () => { window.mParticle.upload(); expect( - window.fetchMock.called(), + fetchMock.called(), 'FetchMock should have been called' ).to.equal(true); - const batch1 = JSON.parse(window.fetchMock._calls[0][1].body); + const batch1 = JSON.parse(fetchMock._calls[0][1].body); // Batch 1 should contain only session start, AST and a single event // in this exact order @@ -1334,12 +1336,12 @@ describe('batch uploader', () => { // https://go.mparticle.com/work/SQDSDKS-5165 it.skip('should keep and retry batches in sequence if the transmission fails midway', (done) => { // First request is successful, subsequent requests fail - window.fetchMock.post(urls.events, 200, { + fetchMock.post(urls.events, 200, { overwriteRoutes: false, repeat: 1, }); - window.fetchMock.post(urls.events, 429, { + fetchMock.post(urls.events, 429, { overwriteRoutes: false, }); @@ -1379,7 +1381,7 @@ describe('batch uploader', () => { setTimeout(() => { // Batch upload should be triggered 3 times, but only // 2 should be waiting for retry - expect(window.fetchMock.calls().length).to.equal(3); + expect(fetchMock.calls().length).to.equal(3); const batchQueue = window.mParticle.getInstance()._APIClient.uploader @@ -1414,8 +1416,8 @@ describe('batch uploader', () => { describe('batching via window.fetch', () => { beforeEach(() => { - window.fetchMock.post(urls.events, 200); - window.fetchMock.config.overwriteRoutes = true; + fetchMock.post(urls.events, 200); + fetchMock.config.overwriteRoutes = true; clock = sinon.useFakeTimers({now: new Date().getTime()}); window.mParticle.config.flags = { @@ -1424,7 +1426,7 @@ describe('batch uploader', () => { }); afterEach(() => { - window.fetchMock.restore(); + fetchMock.restore(); sinon.restore(); clock.restore(); }); @@ -1442,9 +1444,9 @@ describe('batch uploader', () => { // Tick forward 1000 ms to hit upload interval and force an upload clock.tick(1000); - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); batch.events[0].event_type.should.equal('session_start'); @@ -1464,9 +1466,9 @@ describe('batch uploader', () => { clock.tick(1000); // Tick forward 1000 ms to hit upload interval and force an upload - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); batch.events[2].data.location.should.have.property('latitude', 100) batch.events[2].data.location.should.have.property('longitude', 100) @@ -1485,14 +1487,14 @@ describe('batch uploader', () => { mockServer.requests.length.should.equal(1); // no calls made to fetch yet - (window.fetchMock.lastCall() === undefined).should.equal(true) + (fetchMock.lastCall() === undefined).should.equal(true) // force upload, triggering window.fetch window.mParticle.upload(); - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); batch.events[0].event_type.should.equal('session_start'); @@ -1515,9 +1517,9 @@ describe('batch uploader', () => { var product1 = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999); window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart, product1); - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); batch.events[0].event_type.should.equal('session_start'); @@ -1532,9 +1534,9 @@ describe('batch uploader', () => { it('should return pending uploads if a 500 is returned', function(done) { window.mParticle._resetForTests(MPConfig); - var clock = sinon.useFakeTimers(); + // var clock = sinon.useFakeTimers(); - window.fetchMock.post(urls.events, 500); + fetchMock.post(urls.events, 500); window.mParticle.init(apiKey, window.mParticle.config); window.mParticle.logEvent('Test Event'); @@ -1546,15 +1548,15 @@ describe('batch uploader', () => { pendingEvents[1].EventName.should.equal(10); pendingEvents[2].EventName.should.equal('Test Event'); - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); - (window.fetchMock.lastCall() === undefined).should.equal(true); + (fetchMock.lastCall() === undefined).should.equal(true); clock.tick(1000); let nowPendingEvents = window.mParticle.getInstance()._APIClient.uploader.eventsQueuedForProcessing; nowPendingEvents.length.should.equal(0); - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); batch.events[0].event_type.should.equal('session_start'); batch.events[1].event_type.should.equal('application_state_transition'); batch.events[2].event_type.should.equal('custom_event'); @@ -1572,9 +1574,9 @@ describe('batch uploader', () => { // Tick forward 1000 ms to hit upload interval and force an upload clock.tick(1000); - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); batch.events[0].data.should.have.property('source_message_id') @@ -1602,9 +1604,9 @@ describe('batch uploader', () => { // Tick forward 1000 ms to hit upload interval and force an upload clock.tick(1000); - const lastCall = window.fetchMock.lastCall(); + const lastCall = fetchMock.lastCall(); const endpoint = lastCall[0]; - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); endpoint.should.equal(urls.events); // event batch includes session start, ast, then last event is Test Event @@ -1661,11 +1663,11 @@ describe('batch uploader', () => { clock.restore(); setTimeout(function() { - const batch1 = JSON.parse(window.fetchMock._calls[0][1].body); - const batch2 = JSON.parse(window.fetchMock._calls[1][1].body); - const batch3 = JSON.parse(window.fetchMock._calls[2][1].body); - const batch4 = JSON.parse(window.fetchMock._calls[3][1].body); - const batch5 = JSON.parse(window.fetchMock._calls[4][1].body); + const batch1 = JSON.parse(fetchMock._calls[0][1].body); + const batch2 = JSON.parse(fetchMock._calls[1][1].body); + const batch3 = JSON.parse(fetchMock._calls[2][1].body); + const batch4 = JSON.parse(fetchMock._calls[3][1].body); + const batch5 = JSON.parse(fetchMock._calls[4][1].body); // UAC event expect(batch1.events.length, 'Batch 1: UAC event').to.equal(1); @@ -2001,7 +2003,7 @@ describe('batch uploader', () => { it('should return pending uploads if a 500 is returned', function(done) { window.mParticle._resetForTests(MPConfig); - var clock = sinon.useFakeTimers(); + // var clock = sinon.useFakeTimers(); mockServer.respondWith(urls.events, [ 500, @@ -2034,7 +2036,7 @@ describe('batch uploader', () => { it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', function(done) { window.mParticle._resetForTests(MPConfig); - var clock = sinon.useFakeTimers(); + // var clock = sinon.useFakeTimers(); window.mParticle.config.onCreateBatch = function (batch: Batch) { return batch @@ -2052,7 +2054,7 @@ describe('batch uploader', () => { it('should respect rules for the batch modification', function(done) { window.mParticle._resetForTests(MPConfig); - var clock = sinon.useFakeTimers(); + // var clock = sinon.useFakeTimers(); window.mParticle.config.onCreateBatch = function (batch) { batch.events.map(event => { @@ -2079,7 +2081,7 @@ describe('batch uploader', () => { it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', function(done) { window.mParticle._resetForTests(MPConfig); - var clock = sinon.useFakeTimers(); + // var clock = sinon.useFakeTimers(); window.mParticle.config.onCreateBatch = function (batch: Batch) { return undefined; diff --git a/test/src/tests-beaconUpload.ts b/test/src/tests-beaconUpload.ts index b2888028..d32c8b82 100644 --- a/test/src/tests-beaconUpload.ts +++ b/test/src/tests-beaconUpload.ts @@ -3,6 +3,7 @@ import { urls } from './config'; import { apiKey, MPConfig, testMPID } from './config'; import { MParticleWebSDK } from '../../src/sdkRuntimeModels'; import _BatchValidator from '../../src/mockBatchCreator'; +import fetchMock from 'fetch-mock/esm/client'; declare global { interface Window { @@ -14,12 +15,12 @@ declare global { describe('Beacon Upload', () => { let mockServer; before(function() { - window.fetchMock.restore(); + fetchMock.restore(); sinon.restore(); }); beforeEach(function() { - window.fetchMock.restore(); + fetchMock.restore(); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -37,7 +38,7 @@ describe('Beacon Upload', () => { afterEach(() => { sinon.restore(); mockServer.reset(); - window.fetchMock.restore(); + fetchMock.restore(); }); it('should trigger beacon on page visibilitychange events', function(done) { diff --git a/test/src/tests-consent.ts b/test/src/tests-consent.ts index ad465be2..eb8ff8fb 100644 --- a/test/src/tests-consent.ts +++ b/test/src/tests-consent.ts @@ -1,5 +1,7 @@ import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; + import { urls } from './config'; import { apiKey, MPConfig, testMPID } from './config'; import { MParticleWebSDK } from '../../src/sdkRuntimeModels'; @@ -28,7 +30,7 @@ const mParticle = window.mParticle; describe('Consent', function() { beforeEach(function() { - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -42,7 +44,7 @@ describe('Consent', function() { afterEach(function() { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mParticle._resetForTests(MPConfig); }); @@ -646,7 +648,7 @@ describe('Consent', function() { user.setConsentState(consentState); mParticle.logEvent('Test Event'); - const testEvent = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findBatch(fetchMock._calls, 'Test Event'); testEvent.should.have.property('consent_state'); testEvent.consent_state.should.have.property('ccpa'); @@ -685,7 +687,7 @@ describe('Consent', function() { mParticle.logEvent('Test Event'); - const testEvent = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findBatch(fetchMock._calls, 'Test Event'); testEvent.should.have.property('consent_state'); testEvent.consent_state.should.have.property('ccpa'); diff --git a/test/src/tests-cookie-syncing.js b/test/src/tests-cookie-syncing.js index 9601e2fd..c9a39c69 100644 --- a/test/src/tests-cookie-syncing.js +++ b/test/src/tests-cookie-syncing.js @@ -56,7 +56,7 @@ describe('cookie syncing', function() { JSON.stringify({ mpid: testMPID, is_logged_in: false }), ]); - window.fetchMock.post(urls.events, 200); + // fetchMock.post(urls.events, 200); mParticle.init(apiKey, window.mParticle.config); }); diff --git a/test/src/tests-core-sdk.js b/test/src/tests-core-sdk.js index 4dd15b72..dfe7879b 100644 --- a/test/src/tests-core-sdk.js +++ b/test/src/tests-core-sdk.js @@ -4,6 +4,7 @@ import Constants from '../../src/constants'; import sinon from '../../node_modules/sinon/pkg/sinon'; import { urls } from './config'; import { apiKey, das, MPConfig, testMPID, workspaceCookieName } from './config'; +import fetchMock from 'fetch-mock/esm/client'; const DefaultConfig = Constants.DefaultConfig, setLocalStorage = Utils.setLocalStorage, @@ -15,7 +16,7 @@ let mockServer; describe('core SDK', function() { beforeEach(function() { - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -30,14 +31,14 @@ describe('core SDK', function() { afterEach(function() { mockServer.reset(); mParticle._resetForTests(MPConfig); - window.fetchMock.restore(); + fetchMock.restore(); sinon.restore(); }); it('starts new session', function(done) { mParticle.startNewSession(); - const sessionStartEvent = findEventFromRequest(window.fetchMock._calls, 'session_start'); + const sessionStartEvent = findEventFromRequest(fetchMock._calls, 'session_start'); sessionStartEvent.should.be.ok(); sessionStartEvent.data.should.have.property('session_uuid'); @@ -90,7 +91,7 @@ describe('core SDK', function() { mParticle.startNewSession(); mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); sessionEndEvent.should.be.ok(); @@ -101,14 +102,14 @@ describe('core SDK', function() { it('creates a new dateLastEventSent when logging an event, and retains the previous one when ending session', function(done) { mParticle.logEvent('Test Event1'); - const testEvent1 = findEventFromRequest(window.fetchMock._calls, 'Test Event1'); + const testEvent1 = findEventFromRequest(fetchMock._calls, 'Test Event1'); setTimeout(function() { mParticle.logEvent('Test Event2'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); const result1 = testEvent1.data.timestamp_unixtime_ms === testEvent2.data.timestamp_unixtime_ms; const result2 = testEvent2.data.timestamp_unixtime_ms === sessionEndEvent.data.timestamp_unixtime_ms; @@ -139,7 +140,7 @@ describe('core SDK', function() { mParticle.setAppVersion('1.0'); window.mParticle.logEvent('Test Event', mParticle.EventType.Navigation); - const testEventBatch = findBatch(window.fetchMock._calls, 'Test Event'); + const testEventBatch = findBatch(fetchMock._calls, 'Test Event'); testEventBatch.application_info.should.have.property('application_version', '1.0'); done(); @@ -201,7 +202,7 @@ describe('core SDK', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.application_info.should.have.property('application_name', 'newAppName'); @@ -229,7 +230,7 @@ describe('core SDK', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.have.property('application_info'); batch.application_info.should.have.property('package', 'my-web-package'); @@ -247,7 +248,7 @@ describe('core SDK', function() { removeme: new Error(), }); - const sanitizedEvent = findEventFromRequest(window.fetchMock._calls, 'sanitized event'); + const sanitizedEvent = findEventFromRequest(fetchMock._calls, 'sanitized event'); sanitizedEvent.data.custom_attributes.should.have.property('key1', 'value1'); sanitizedEvent.data.custom_attributes.should.have.property('mydate'); @@ -280,13 +281,13 @@ describe('core SDK', function() { product.Attributes.should.have.property('valid'); mParticle.eCommerce.logCheckout(1, 'visa', attrs); - const checkoutEvent = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent = findEventFromRequest(fetchMock._calls, 'checkout'); checkoutEvent.data.custom_attributes.should.not.have.property('invalid'); checkoutEvent.data.custom_attributes.should.have.property('valid'); mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, product, attrs); - const addToCartEvent = findEventFromRequest(window.fetchMock._calls, 'add_to_cart'); + const addToCartEvent = findEventFromRequest(fetchMock._calls, 'add_to_cart'); addToCartEvent.data.custom_attributes.should.not.have.property('invalid'); addToCartEvent.data.custom_attributes.should.have.property('valid'); @@ -307,7 +308,7 @@ describe('core SDK', function() { false, attrs ); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.custom_attributes.should.not.have.property('invalid'); purchaseEvent.data.custom_attributes.should.have.property('valid'); @@ -320,7 +321,7 @@ describe('core SDK', function() { mockServer.requests = []; mParticle.eCommerce.logPromotion(1, promotion, attrs); - const promotionViewEvent = findEventFromRequest(window.fetchMock._calls, 'view'); + const promotionViewEvent = findEventFromRequest(fetchMock._calls, 'view'); promotionViewEvent.data.custom_attributes.should.not.have.property('invalid'); promotionViewEvent.data.custom_attributes.should.have.property('valid'); @@ -331,7 +332,7 @@ describe('core SDK', function() { false, attrs ); - const refundEvent = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent = findEventFromRequest(fetchMock._calls, 'refund'); refundEvent.data.custom_attributes.should.not.have.property('invalid'); refundEvent.data.custom_attributes.should.have.property('valid'); @@ -382,12 +383,12 @@ describe('core SDK', function() { mParticle.init(apiKey, window.mParticle.config); clock.tick(100); mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); clock.tick(70000); mParticle.logEvent('Test Event2'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); testEvent.data.session_uuid.should.not.equal(testEvent2.data.session_uuid); mParticle.getInstance()._SessionManager.clearSessionTimeout(); clock.restore(); @@ -410,9 +411,9 @@ describe('core SDK', function() { clock.tick(150000); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); - const testEvent3 = findEventFromRequest(window.fetchMock._calls, 'Test Event3'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); + const testEvent3 = findEventFromRequest(fetchMock._calls, 'Test Event3'); testEvent2.data.session_uuid.should.equal(testEvent.data.session_uuid); testEvent3.data.session_uuid.should.not.equal(testEvent.data.session_uuid); @@ -434,10 +435,10 @@ describe('core SDK', function() { // This clock tick initiates a session end event that is successful clock.tick(70000); - let sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + let sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); Should(sessionEndEvent).be.ok(); - window.fetchMock._calls = []; + fetchMock._calls = []; clock.tick(100); mParticle.logEvent('Test Event2'); @@ -454,14 +455,14 @@ describe('core SDK', function() { setLocalStorage(workspaceCookieName, new_Persistence); // // This clock tick initiates a session end event that is not successful clock.tick(70000); - sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); Should(sessionEndEvent).not.be.ok(); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); mParticle.logEvent('Test Event3'); - const testEvent3 = findEventFromRequest(window.fetchMock._calls, 'Test Event3'); + const testEvent3 = findEventFromRequest(fetchMock._calls, 'Test Event3'); testEvent3.data.session_uuid.should.equal(testEvent2.data.session_uuid); clock.restore(); @@ -470,7 +471,7 @@ describe('core SDK', function() { it('should get sessionId', function(done) { mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); const sessionId = mParticle.getInstance()._SessionManager.getSession(); @@ -482,7 +483,7 @@ describe('core SDK', function() { it('should set session start date in dto', function(done) { mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); testEvent.data.session_start_unixtime_ms.should.be.above(0); @@ -492,18 +493,18 @@ describe('core SDK', function() { it('should update session start date when manually ending session then starting a new one', function(done) { mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); const testEventSessionStartTime = testEvent.data.session_start_unixtime_ms; mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); const sessionEndEventSessionStartDate = sessionEndEvent.data.session_start_unixtime_ms; sessionEndEventSessionStartDate.should.equal(testEventSessionStartTime); mParticle.logEvent('Test Event2'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); const testEvent2SessionStartDate = testEvent2.data.session_start_unixtime_ms; testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate); @@ -521,21 +522,21 @@ describe('core SDK', function() { clock.tick(10); mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); const testEventSessionStartDate = testEvent.data.session_start_unixtime_ms; // trigger session timeout which ends session automatically clock.tick(60000); // note to self - session end event not being triggered, could be the same bug - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); const sessionEndEventSessionStartDate = sessionEndEvent.data.session_start_unixtime_ms; sessionEndEventSessionStartDate.should.equal(testEventSessionStartDate); clock.tick(100); mParticle.logEvent('Test Event2'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); const testEvent2SessionStartDate = testEvent2.data.session_start_unixtime_ms; testEvent2SessionStartDate.should.be.above(sessionEndEventSessionStartDate); @@ -548,10 +549,10 @@ describe('core SDK', function() { it('should load SDK with the included api on init and not send events to previous apikey in persistence', function(done) { mParticle.logEvent('Test Event1'); - const testEvent1URL = findRequest(window.fetchMock._calls, 'Test Event1')[0]; + const testEvent1URL = findRequest(fetchMock._calls, 'Test Event1')[0]; testEvent1URL.should.equal(urls.events); - window.fetchMock.post( + fetchMock.post( 'https://jssdks.mparticle.com/v3/JS/new-api-key/events', 200 ); @@ -559,7 +560,7 @@ describe('core SDK', function() { mParticle.init('new-api-key', window.mParticle.config); mParticle.logEvent('Test Event2'); - const testEvent2URL = findRequestURL(window.fetchMock._calls, 'Test Event2'); + const testEvent2URL = findRequestURL(fetchMock._calls, 'Test Event2'); testEvent2URL.should.equal( 'https://jssdks.mparticle.com/v3/JS/new-api-key/events' ); @@ -751,7 +752,7 @@ describe('core SDK', function() { warnMessages.length.should.equal(0); errorMessages.length.should.equal(0); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); Should(testEvent).be.ok(); done(); @@ -814,7 +815,7 @@ describe('core SDK', function() { // test events endpoint mParticle.logEvent('Test Event'); - const testEventURL = findRequestURL(window.fetchMock._calls, 'Test Event'); + const testEventURL = findRequestURL(fetchMock._calls, 'Test Event'); testEventURL.should.equal( 'https://' + window.mParticle.config.v3SecureServiceUrl + @@ -865,7 +866,7 @@ describe('core SDK', function() { eventBatchingIntervalMillis: 0, } - window.fetchMock.post( + fetchMock.post( 'https://def-v3SecureServiceUrl/v3/JS/test_key/events', 200 ); @@ -877,7 +878,7 @@ describe('core SDK', function() { window.mParticle.logEvent('Test Event'); - window.fetchMock.lastOptions().body.should.be.ok() + fetchMock.lastOptions().body.should.be.ok() done(); }); @@ -977,7 +978,7 @@ describe('core SDK', function() { mParticle.Identity.identify({ userIdentities: { customerid: 'test' } }); mParticle.logEvent('Test Event'); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); testEvent.should.be.ok(); diff --git a/test/src/tests-eCommerce.js b/test/src/tests-eCommerce.js index 87dd24e4..48fa7c7d 100644 --- a/test/src/tests-eCommerce.js +++ b/test/src/tests-eCommerce.js @@ -1,6 +1,7 @@ import Utils from './utils'; import sinon from 'sinon'; import { urls, apiKey, workspaceToken, MPConfig, testMPID, ProductActionType, PromotionActionType } from './config'; +import fetchMock from 'fetch-mock/esm/client'; const getLocalStorageProducts = Utils.getLocalStorageProducts, forwarderDefaultConfiguration = Utils.forwarderDefaultConfiguration, @@ -14,7 +15,7 @@ describe('eCommerce', function() { delete mParticle._instances['default_instance']; mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer.respondWith(urls.identify, [ 200, @@ -27,7 +28,7 @@ describe('eCommerce', function() { afterEach(function() { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mParticle._resetForTests(MPConfig); }); @@ -94,7 +95,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logPurchase(transactionAttributes, product); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.should.have.property('product_action'); purchaseEvent.data.product_action.should.have.property('action', 'purchase'); @@ -125,7 +126,7 @@ describe('eCommerce', function() { it('should not log a ecommerce event if there is a typo in the product action type', function(done) { // fetchMock calls will have session start and AST events, we want to reset so that we can prove the product action type does not go through (length remains 0 after logging) - window.fetchMock._calls = []; + fetchMock._calls = []; const product = mParticle.eCommerce.createProduct( 'iPhone', '12345', @@ -138,7 +139,7 @@ describe('eCommerce', function() { mParticle.ProductActionType.Typo, // <------ will result in a null when converting the product action type as this is not a real value [product] ); - window.fetchMock._calls.length.should.equal(0); + fetchMock._calls.length.should.equal(0); done(); }); @@ -167,7 +168,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logPurchase(transactionAttributes, product); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.should.have.property('product_action'); purchaseEvent.data.product_action.should.have.property('action', 'purchase'); @@ -219,12 +220,12 @@ describe('eCommerce', function() { ); mParticle.eCommerce.logPurchase(transactionAttributes, product); - const purchaseEvent1 = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent1 = findEventFromRequest(fetchMock._calls, 'purchase'); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, product, null, null, transactionAttributes) - const purchaseEvent2 = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent2 = findEventFromRequest(fetchMock._calls, 'purchase'); const { product_action: productAction1 } = purchaseEvent1.data; const { product_action: productAction2 } = purchaseEvent2.data @@ -266,7 +267,7 @@ describe('eCommerce', function() { product2, ]); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.should.have.property('product_action'); purchaseEvent.data.product_action.should.have.property('products').with.lengthOf(2); @@ -288,7 +289,7 @@ describe('eCommerce', function() { product2, ]); - const refundEvent = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent = findEventFromRequest(fetchMock._calls, 'refund'); refundEvent.data.should.have.property('product_action'); refundEvent.data.product_action.should.have.property('products').with.lengthOf(2); @@ -329,7 +330,7 @@ describe('eCommerce', function() { promotion ); - const promotionEvent = findEventFromRequest(window.fetchMock._calls, 'click'); + const promotionEvent = findEventFromRequest(fetchMock._calls, 'click'); Should(promotionEvent).be.ok(); @@ -363,7 +364,7 @@ describe('eCommerce', function() { [promotion1, promotion2] ); - const promotionEvent = findEventFromRequest(window.fetchMock._calls, 'click'); + const promotionEvent = findEventFromRequest(fetchMock._calls, 'click'); Should(promotionEvent).be.ok(); @@ -397,7 +398,7 @@ describe('eCommerce', function() { { shouldUploadEvent: false } ); - const promotionEvent = findEventFromRequest(window.fetchMock._calls, 'click'); + const promotionEvent = findEventFromRequest(fetchMock._calls, 'click'); Should(promotionEvent).not.be.ok(); done(); @@ -425,7 +426,7 @@ describe('eCommerce', function() { ); mParticle.eCommerce.logImpression(impression); - const impressionEvent = findEventFromRequest(window.fetchMock._calls, 'impression'); + const impressionEvent = findEventFromRequest(fetchMock._calls, 'impression'); Should(impressionEvent).be.ok(); @@ -447,7 +448,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logImpression(impression, null, null, { shouldUploadEvent: false }); - const impressionEvent = findEventFromRequest(window.fetchMock._calls, 'impression'); + const impressionEvent = findEventFromRequest(fetchMock._calls, 'impression'); Should(impressionEvent).not.be.ok(); @@ -472,7 +473,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logImpression([impression, impression2]); - const impressionEvent = findEventFromRequest(window.fetchMock._calls, 'impression'); + const impressionEvent = findEventFromRequest(fetchMock._calls, 'impression'); Should(impressionEvent).be.ok(); @@ -511,7 +512,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logRefund(transactionAttributes, product); - const refundEvent = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent = findEventFromRequest(fetchMock._calls, 'refund'); Should(refundEvent).be.ok(); @@ -561,13 +562,13 @@ describe('eCommerce', function() { mParticle.eCommerce.logRefund(transactionAttributes, product); - const refundEvent1 = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent1 = findEventFromRequest(fetchMock._calls, 'refund'); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Refund, product, null, null, transactionAttributes) - const refundEvent2 = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent2 = findEventFromRequest(fetchMock._calls, 'refund'); Should(refundEvent1).be.ok(); Should(refundEvent2).be.ok(); @@ -623,7 +624,7 @@ describe('eCommerce', function() { { shouldUploadEvent: false} ); - const event = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const event = findEventFromRequest(fetchMock._calls, 'purchase'); Should(event).not.be.ok(); done(); @@ -634,7 +635,7 @@ describe('eCommerce', function() { mParticle.eCommerce.Cart.add(product, true); - const addToCartEvent = findEventFromRequest(window.fetchMock._calls, 'add_to_cart'); + const addToCartEvent = findEventFromRequest(fetchMock._calls, 'add_to_cart'); addToCartEvent.data.should.have.property('product_action'); addToCartEvent.data.product_action.should.have.property('action', 'add_to_cart'); @@ -650,7 +651,7 @@ describe('eCommerce', function() { mParticle.eCommerce.Cart.add(product); mParticle.eCommerce.Cart.remove({ Sku: '12345' }, true); - const removeFromCartEvent = findEventFromRequest(window.fetchMock._calls, 'remove_from_cart'); + const removeFromCartEvent = findEventFromRequest(fetchMock._calls, 'remove_from_cart'); removeFromCartEvent.data.should.have.property('product_action'); removeFromCartEvent.data.product_action.should.have.property('action', 'remove_from_cart'); @@ -727,7 +728,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logCheckout(1, 'Visa'); - const checkoutEvent = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent = findEventFromRequest(fetchMock._calls, 'checkout'); Should(checkoutEvent).be.ok(); @@ -752,7 +753,7 @@ describe('eCommerce', function() { mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Checkout, [product1, product2], null, null, {Step: 4, Option: 'Visa'}); - const checkoutEvent = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent = findEventFromRequest(fetchMock._calls, 'checkout'); Should(checkoutEvent).be.ok(); @@ -777,7 +778,7 @@ describe('eCommerce', function() { { color: 'blue' } ); - const checkoutOptionEvent = findEventFromRequest(window.fetchMock._calls, 'checkout_option'); + const checkoutOptionEvent = findEventFromRequest(fetchMock._calls, 'checkout_option'); Should(checkoutOptionEvent).be.ok(); @@ -801,7 +802,7 @@ describe('eCommerce', function() { product ); - const viewDetailEvent = findEventFromRequest(window.fetchMock._calls, 'view_detail'); + const viewDetailEvent = findEventFromRequest(fetchMock._calls, 'view_detail'); Should(viewDetailEvent).be.ok(); viewDetailEvent.should.have.property('event_type', 'commerce_event'); @@ -896,7 +897,7 @@ describe('eCommerce', function() { ); mParticle.eCommerce.logPurchase(transactionAttributes, product); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.product_action.products[0].should.not.have.property('position'); @@ -920,7 +921,7 @@ describe('eCommerce', function() { mParticle.eCommerce.Cart.add([product1, product2], true); - const addToCartEvent = findEventFromRequest(window.fetchMock._calls, 'add_to_cart'); + const addToCartEvent = findEventFromRequest(fetchMock._calls, 'add_to_cart'); Should(addToCartEvent).be.ok(); @@ -947,7 +948,7 @@ describe('eCommerce', function() { mParticle.eCommerce.Cart.add(product1, true); - const addToCartEvent = findEventFromRequest(window.fetchMock._calls, 'add_to_cart'); + const addToCartEvent = findEventFromRequest(fetchMock._calls, 'add_to_cart'); Should(addToCartEvent).be.ok(); @@ -1421,7 +1422,7 @@ describe('eCommerce', function() { it('should add customFlags to logCheckout events', function(done) { mParticle.eCommerce.logCheckout(1, {}, {}, { interactionEvent: true }); - const checkoutEvent = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent = findEventFromRequest(fetchMock._calls, 'checkout'); checkoutEvent.data.custom_flags.interactionEvent.should.equal(true); done(); @@ -1435,7 +1436,7 @@ describe('eCommerce', function() { { price: 5 }, { interactionEvent: true } ); - const unknownEvent = findEventFromRequest(window.fetchMock._calls, 'unknown'); + const unknownEvent = findEventFromRequest(fetchMock._calls, 'unknown'); unknownEvent.data.custom_flags.interactionEvent.should.equal(true); @@ -1457,7 +1458,7 @@ describe('eCommerce', function() { { interactionEvent: true } ); - const purchaseEvent = findEventFromRequest(window.fetchMock._calls, 'purchase'); + const purchaseEvent = findEventFromRequest(fetchMock._calls, 'purchase'); purchaseEvent.data.custom_flags.interactionEvent.should.equal(true); @@ -1479,7 +1480,7 @@ describe('eCommerce', function() { ); - const promotionEvent = findEventFromRequest(window.fetchMock._calls, 'click'); + const promotionEvent = findEventFromRequest(fetchMock._calls, 'click'); promotionEvent.data.custom_flags.interactionEvent.should.equal(true); @@ -1498,7 +1499,7 @@ describe('eCommerce', function() { { interactionEvent: true } ); - const impressionEvent = findEventFromRequest(window.fetchMock._calls, 'impression'); + const impressionEvent = findEventFromRequest(fetchMock._calls, 'impression'); impressionEvent.data.custom_flags.interactionEvent.should.equal(true); done(); @@ -1518,7 +1519,7 @@ describe('eCommerce', function() { { shipping: 5 }, { interactionEvent: true } ); - const refundEvent = findEventFromRequest(window.fetchMock._calls, 'refund'); + const refundEvent = findEventFromRequest(fetchMock._calls, 'refund'); refundEvent.data.custom_flags.interactionEvent.should.equal(true); diff --git a/test/src/tests-event-logging.js b/test/src/tests-event-logging.js index 4d220681..bff35721 100644 --- a/test/src/tests-event-logging.js +++ b/test/src/tests-event-logging.js @@ -1,5 +1,7 @@ import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; + import { urls, apiKey, testMPID, MPConfig, @@ -13,7 +15,7 @@ let mockServer; describe('event logging', function() { beforeEach(function() { mParticle._resetForTests(MPConfig); - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); delete mParticle._instances['default_instance']; mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -29,7 +31,7 @@ describe('event logging', function() { afterEach(function() { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mParticle._resetForTests(MPConfig); }); @@ -39,8 +41,8 @@ describe('event logging', function() { mParticle.EventType.Navigation, { mykey: 'myvalue' } ); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); - const testEventBatch = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); + const testEventBatch = findBatch(fetchMock._calls, 'Test Event'); testEvent.data.should.have.property('event_name', 'Test Event'); testEvent.data.should.have.property('custom_event_type', 'navigation'); @@ -59,14 +61,14 @@ describe('event logging', function() { { mykey: 'myvalue' } ); - const testEventBatch = findBatch(window.fetchMock._calls, 'Test Event'); + const testEventBatch = findBatch(fetchMock._calls, 'Test Event'); // this das should be the SDK auto generated one, which is 36 characters long testEventBatch.mp_deviceid.should.have.length(36) mParticle.setDeviceId('foo-guid'); window.mParticle.logEvent('Test Event2',); - const testEvent2Batch = findBatch(window.fetchMock._calls, 'Test Event2'); + const testEvent2Batch = findBatch(fetchMock._calls, 'Test Event2'); // das should be the one passed to setDeviceId() testEvent2Batch.should.have.property('mp_deviceid', 'foo-guid'); @@ -81,7 +83,7 @@ describe('event logging', function() { mParticle.init(apiKey, window.mParticle.config); window.mParticle.logEvent('Test Event',); - const testEventBatch = findBatch(window.fetchMock._calls, 'Test Event'); + const testEventBatch = findBatch(fetchMock._calls, 'Test Event'); // this das should be the SDK auto generated one testEventBatch.should.have.property('mp_deviceid', 'foo-guid'); @@ -110,10 +112,10 @@ describe('event logging', function() { } ); - const uploadEvent = findEventFromRequest(window.fetchMock._calls, 'Test Standard Upload'); - const uploadEventBatch = findBatch(window.fetchMock._calls, 'Test Standard Upload'); + const uploadEvent = findEventFromRequest(fetchMock._calls, 'Test Standard Upload'); + const uploadEventBatch = findBatch(fetchMock._calls, 'Test Standard Upload'); - const bypassedEvent = findEventFromRequest(window.fetchMock._calls, 'Test Upload Bypass'); + const bypassedEvent = findEventFromRequest(fetchMock._calls, 'Test Upload Bypass'); uploadEvent.should.be.ok(); uploadEvent.data.should.have.property('event_name', 'Test Standard Upload'); @@ -148,10 +150,10 @@ describe('event logging', function() { shouldUploadEvent: false, }); - const uploadEvent = findEventFromRequest(window.fetchMock._calls, 'Test Standard Upload'); - const uploadEventBatch = findBatch(window.fetchMock._calls, 'Test Standard Upload'); + const uploadEvent = findEventFromRequest(fetchMock._calls, 'Test Standard Upload'); + const uploadEventBatch = findBatch(fetchMock._calls, 'Test Standard Upload'); - const bypassedEvent = findEventFromRequest(window.fetchMock._calls, 'Test Upload Bypass'); + const bypassedEvent = findEventFromRequest(fetchMock._calls, 'Test Upload Bypass'); uploadEvent.should.be.ok(); @@ -169,7 +171,7 @@ describe('event logging', function() { it('should log an error', function(done) { mParticle.logError('my error'); - const errorEvent = findEventFromRequest(window.fetchMock._calls, 'my error'); + const errorEvent = findEventFromRequest(fetchMock._calls, 'my error'); Should(errorEvent).be.ok(); @@ -186,7 +188,7 @@ describe('event logging', function() { mParticle.logError(error); - const errorEvent = findEventFromRequest(window.fetchMock._calls, 'my error'); + const errorEvent = findEventFromRequest(fetchMock._calls, 'my error'); Should(errorEvent).be.ok(); @@ -205,7 +207,7 @@ describe('event logging', function() { mParticle.logError(error, { location: 'my path', myData: 'my data' }); - const errorEvent = findEventFromRequest(window.fetchMock._calls, 'my error'); + const errorEvent = findEventFromRequest(fetchMock._calls, 'my error'); Should(errorEvent).be.ok(); errorEvent.data.should.have.property('message', 'Error'); @@ -223,7 +225,7 @@ describe('event logging', function() { valid: 10, }); - const errorEvent = findEventFromRequest(window.fetchMock._calls, 'my error'); + const errorEvent = findEventFromRequest(fetchMock._calls, 'my error'); Should(errorEvent).be.ok(); errorEvent.data.should.have.property('message', 'Error'); @@ -242,7 +244,7 @@ describe('event logging', function() { }); it('should log an AST with firstRun = true when first visiting a page, and firstRun = false when reloading the page', function(done) { - const astEvent = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); + const astEvent = findEventFromRequest(fetchMock._calls, 'application_state_transition'); astEvent.data.should.have.property('application_transition_type', 'application_initialized'); astEvent.data.should.have.property('is_first_run', true); @@ -252,10 +254,10 @@ describe('event logging', function() { astEvent.data.should.have.property('launch_referral', window.location.href); } - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.init(apiKey, window.mParticle.config) - const astEvent2 = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); + const astEvent2 = findEventFromRequest(fetchMock._calls, 'application_state_transition'); astEvent2.data.should.have.property('is_first_run', false); @@ -264,11 +266,11 @@ describe('event logging', function() { it('should log an AST on init with firstRun = false when cookies already exist', function(done) { // cookies currently exist, mParticle.init called from beforeEach - window.fetchMock._calls = []; + fetchMock._calls = []; // log second AST mParticle.init(apiKey, window.mParticle.config); - const astEvent = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); + const astEvent = findEventFromRequest(fetchMock._calls, 'application_state_transition'); astEvent.data.should.have.property('is_first_run', false); done(); @@ -277,7 +279,7 @@ describe('event logging', function() { it('should log a page view', function(done) { mParticle.logPageView(); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).be.ok(); @@ -297,7 +299,7 @@ describe('event logging', function() { } ); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).be.ok(); @@ -314,7 +316,7 @@ describe('event logging', function() { 'MyCustom.Flag': 'Test', }); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).be.ok(); @@ -332,7 +334,7 @@ describe('event logging', function() { { shouldUploadEvent: false } ); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).not.be.ok(); done(); @@ -340,7 +342,7 @@ describe('event logging', function() { it('should not log a PageView event if there are invalid attrs', function(done) { mParticle.logPageView('test1', 'invalid', null); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).not.be.ok(); @@ -350,30 +352,30 @@ describe('event logging', function() { it('should not log an event that has an invalid customFlags', function(done) { mParticle.logPageView('test', null, 'invalid'); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); Should(pageViewEvent).not.be.ok(); done(); }); it('should log event with name PageView when an invalid event name is passed', function(done) { - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logPageView(null); - window.fetchMock._calls.length.should.equal(1); - const pageViewEvent = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + fetchMock._calls.length.should.equal(1); + const pageViewEvent = findEventFromRequest(fetchMock._calls, 'screen_view'); pageViewEvent.data.screen_name.should.equal('PageView'); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logPageView({ test: 'test' }); - window.fetchMock._calls.length.should.equal(1); - const pageViewEvent2 = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + fetchMock._calls.length.should.equal(1); + const pageViewEvent2 = findEventFromRequest(fetchMock._calls, 'screen_view'); pageViewEvent2.data.screen_name.should.equal('PageView'); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logPageView([1, 2, 3]); - window.fetchMock._calls.length.should.equal(1); - const pageViewEvent3 = findEventFromRequest(window.fetchMock._calls, 'screen_view'); + fetchMock._calls.length.should.equal(1); + const pageViewEvent3 = findEventFromRequest(fetchMock._calls, 'screen_view'); pageViewEvent3.data.screen_name.should.equal('PageView'); done(); @@ -382,7 +384,7 @@ describe('event logging', function() { it('should log opt out', function(done) { mParticle.setOptOut(true); - const optOutEvent = findEventFromRequest(window.fetchMock._calls, 'opt_out'); + const optOutEvent = findEventFromRequest(fetchMock._calls, 'opt_out'); optOutEvent.event_type.should.equal('opt_out'); optOutEvent.data.should.have.property('is_opted_out', true); @@ -391,20 +393,20 @@ describe('event logging', function() { }); it('log event requires name', function(done) { - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent(); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); done(); }); it('log event requires valid event type', function(done) { - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test', 100); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); done(); }); @@ -412,7 +414,7 @@ describe('event logging', function() { it('event attributes must be object', function(done) { mParticle.logEvent('Test Event', null, 1); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); testEvent.data.should.have.property('custom_attributes', null); @@ -421,36 +423,36 @@ describe('event logging', function() { it('opting out should prevent events being sent', function(done) { mParticle.setOptOut(true); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); done(); }); it('after logging optout, and reloading, events still should not be sent until opt out is enabled when using local storage', function(done) { mParticle.setOptOut(true); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); mParticle.setOptOut(false); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(1); + fetchMock._calls.should.have.lengthOf(1); mParticle.setOptOut(true); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); done(); }); @@ -459,23 +461,23 @@ describe('event logging', function() { mParticle.config.useCookieStorage = true; mParticle.init(apiKey, window.mParticle.config); mParticle.setOptOut(true); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); mParticle.setOptOut(false); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(1); + fetchMock._calls.should.have.lengthOf(1); mParticle.setOptOut(true); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test'); - window.fetchMock._calls.should.have.lengthOf(0); + fetchMock._calls.should.have.lengthOf(0); done(); }); @@ -543,7 +545,7 @@ describe('event logging', function() { it('should send das with each event logged', function(done) { window.mParticle.logEvent('Test Event'); - const testEventBatch = findBatch(window.fetchMock._calls, 'Test Event'); + const testEventBatch = findBatch(fetchMock._calls, 'Test Event'); testEventBatch.should.have.property('mp_deviceid'); testEventBatch.mp_deviceid.length.should.equal(36); @@ -565,7 +567,7 @@ describe('event logging', function() { mParticle.Identity.getCurrentUser().setConsentState(consentState); window.mParticle.logEvent('Test Event'); - const testEvent = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findBatch(fetchMock._calls, 'Test Event'); testEvent.should.have.property('consent_state'); testEvent.consent_state.should.have.property('gdpr'); @@ -580,7 +582,7 @@ describe('event logging', function() { mParticle.Identity.getCurrentUser().setConsentState(null); window.mParticle.logEvent('Test Event2'); - const testEvent2 = findBatch(window.fetchMock._calls, 'Test Event2'); + const testEvent2 = findBatch(fetchMock._calls, 'Test Event2'); testEvent2.should.have.property('consent_state', null); @@ -590,7 +592,7 @@ describe('event logging', function() { it('should log integration attributes with each event', function(done) { mParticle.setIntegrationAttribute(128, { MCID: 'abcdefg' }); mParticle.logEvent('Test Event'); - const testEvent = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findBatch(fetchMock._calls, 'Test Event'); testEvent.should.have.property('integration_attributes'); testEvent.integration_attributes.should.have.property('128'); @@ -616,17 +618,17 @@ describe('event logging', function() { // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) clock.tick(1000); successCallbackCalled.should.equal(true); - let testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + let testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); testEvent.data.location.latitude.should.equal(52.5168); testEvent.data.location.longitude.should.equal(13.3889); - window.fetchMock._calls = []; + fetchMock._calls = []; //this will hit the watch position again, but won't call the callback again clock.tick(1000); numberTimesCalled.should.equal(1); - testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); Should(testEvent).not.be.ok(); @@ -655,16 +657,16 @@ describe('event logging', function() { clock.tick(1000); successCallbackCalled.should.equal(true); - let testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + let testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); testEvent.data.should.have.property('location', null); - window.fetchMock._calls = []; + fetchMock._calls = []; //this will hit the watch position again, but won't call the callback again clock.tick(1000); numberTimesCalled.should.equal(1); - testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); Should(testEvent).not.be.ok(); navigator.geolocation.shouldFail = false; @@ -719,7 +721,7 @@ describe('event logging', function() { // mock geo will successfully run after 1 second (geomock.js // navigator.geolocation.delay) clock.tick(1000); successCallbackCalled.should.equal(true); - const testEvent = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const testEvent = findEventFromRequest(fetchMock._calls, 'Test Event'); const latitudeResult = 52.5168; const longitudeResult = 13.3889; @@ -741,7 +743,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.application_info.should.have.property('application_name', 'a name'); @@ -755,11 +757,11 @@ describe('event logging', function() { mParticle.init(apiKey, mParticle.config); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.events[0].data.should.have.property('is_first_run', true); mParticle.init(apiKey, mParticle.config); - const batch2 = JSON.parse(window.fetchMock.lastOptions().body); + const batch2 = JSON.parse(fetchMock.lastOptions().body); batch2.events[0].data.should.have.property('is_first_run', false); delete window.mParticle.config.flags @@ -776,7 +778,7 @@ describe('event logging', function() { mParticle.init(apiKey, mParticle.config); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.events[0].data.should.have.property('launch_referral'); batch.events[0].data.launch_referral.should.startWith('http://localhost') @@ -795,7 +797,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.application_info.should.have.property('application_name', 'another name'); delete window.mParticle.config.flags @@ -817,7 +819,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.have.property('context'); batch.context.should.have.property('data_plan'); @@ -841,7 +843,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.have.property('context'); batch.context.should.have.property('data_plan'); @@ -865,7 +867,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.not.have.property('context'); @@ -898,7 +900,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); errorMessage.should.equal('Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)') - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.not.have.property('context'); delete window.mParticle.config.flags @@ -942,7 +944,7 @@ describe('event logging', function() { window.mParticle.logEvent('Test Event'); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.should.have.property('consent_state'); batch.consent_state.should.have.properties(['gdpr', 'ccpa']); @@ -991,7 +993,7 @@ describe('event logging', function() { customFlags, transactionAttributes); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); batch.events[0].data.product_action.total_amount.should.equal(0); batch.events[0].data.product_action.shipping_amount.should.equal(0); @@ -1028,7 +1030,7 @@ describe('event logging', function() { customFlags, transactionAttributes); - const batch = JSON.parse(window.fetchMock.lastOptions().body); + const batch = JSON.parse(fetchMock.lastOptions().body); (batch.events[0].data.product_action.products[0].position === null).should.equal(true) batch.events[0].data.product_action.products[0].price.should.equal(0); batch.events[0].data.product_action.products[0].quantity.should.equal(0); diff --git a/test/src/tests-forwarders.js b/test/src/tests-forwarders.js index ecb6f9a7..7833ddb8 100644 --- a/test/src/tests-forwarders.js +++ b/test/src/tests-forwarders.js @@ -3,6 +3,8 @@ import sinon from 'sinon'; import { urls } from './config'; import { apiKey, MPConfig, testMPID, MessageType } from './config'; import { expect } from 'chai'; +import fetchMock from 'fetch-mock/esm/client'; + const findEventFromRequest = Utils.findEventFromRequest, getForwarderEvent = Utils.getForwarderEvent, @@ -16,7 +18,7 @@ describe('forwarders', function() { beforeEach(function() { mParticle._resetForTests(MPConfig); delete mParticle._instances['default_instance']; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -53,7 +55,7 @@ describe('forwarders', function() { }); afterEach(function() { - window.fetchMock.restore(); + fetchMock.restore(); delete window.MockForwarder1; mockServer.restore(); }); @@ -1022,7 +1024,7 @@ describe('forwarders', function() { { 'my-key': 'my-value' } ); - const event = findEventFromRequest(window.fetchMock._calls, 'send this event to forwarder', true); + const event = findEventFromRequest(fetchMock._calls, 'send this event to forwarder', true); Should(event).should.not.have.property('n'); @@ -2216,19 +2218,19 @@ describe('forwarders', function() { mParticle._setIntegrationDelay(10, true); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('Test Event1'); - window.fetchMock._calls.length.should.equal(0); + fetchMock._calls.length.should.equal(0); mParticle._setIntegrationDelay(10, false); mParticle._setIntegrationDelay(128, false); mParticle.logEvent('Test Event2'); - window.fetchMock._calls.length.should.equal(4); + fetchMock._calls.length.should.equal(4); - const sessionStartEvent = findEventFromRequest(window.fetchMock._calls, 'session_start'); - const ASTEvent = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); - const testEvent1 = findEventFromRequest(window.fetchMock._calls, 'Test Event1'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const sessionStartEvent = findEventFromRequest(fetchMock._calls, 'session_start'); + const ASTEvent = findEventFromRequest(fetchMock._calls, 'application_state_transition'); + const testEvent1 = findEventFromRequest(fetchMock._calls, 'Test Event1'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); sessionStartEvent.should.be.ok(); ASTEvent.should.be.ok(); @@ -2259,19 +2261,19 @@ describe('forwarders', function() { .length ).equal(3); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('Test Event1'); - window.fetchMock._calls.length.should.equal(0); + fetchMock._calls.length.should.equal(0); clock.tick(5001); mParticle.logEvent('Test Event2'); - window.fetchMock._calls.length.should.equal(4); + fetchMock._calls.length.should.equal(4); - const sessionStartEvent = findEventFromRequest(window.fetchMock._calls, 'session_start'); - const ASTEvent = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); - const testEvent1 = findEventFromRequest(window.fetchMock._calls, 'Test Event1'); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); + const sessionStartEvent = findEventFromRequest(fetchMock._calls, 'session_start'); + const ASTEvent = findEventFromRequest(fetchMock._calls, 'application_state_transition'); + const testEvent1 = findEventFromRequest(fetchMock._calls, 'Test Event1'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); sessionStartEvent.should.be.ok(); ASTEvent.should.be.ok(); @@ -2287,19 +2289,19 @@ describe('forwarders', function() { mParticle._setIntegrationDelay(24, false); mParticle._setIntegrationDelay(10, true); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('Test Event3'); - window.fetchMock._calls.length.should.equal(0); + fetchMock._calls.length.should.equal(0); clock.tick(1001); mParticle.logEvent('Test Event4'); - window.fetchMock._calls.length.should.equal(4); + fetchMock._calls.length.should.equal(4); - const sessionStartEvent2 = findEventFromRequest(window.fetchMock._calls, 'session_start'); - const ASTEvent2 = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); - const testEvent3 = findEventFromRequest(window.fetchMock._calls, 'Test Event3'); - const testEvent4 = findEventFromRequest(window.fetchMock._calls, 'Test Event4'); + const sessionStartEvent2 = findEventFromRequest(fetchMock._calls, 'session_start'); + const ASTEvent2 = findEventFromRequest(fetchMock._calls, 'application_state_transition'); + const testEvent3 = findEventFromRequest(fetchMock._calls, 'Test Event3'); + const testEvent4 = findEventFromRequest(fetchMock._calls, 'Test Event4'); sessionStartEvent2.should.be.ok(); ASTEvent2.should.be.ok(); @@ -2317,15 +2319,15 @@ describe('forwarders', function() { mParticle._setIntegrationDelay(128, true); mParticle._setIntegrationDelay(24, false); mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('test1'); - window.fetchMock._calls.length.should.equal(0); + fetchMock._calls.length.should.equal(0); // now that we set all integrations to false, the SDK should process queued events mParticle._setIntegrationDelay(128, false); clock.tick(5001); - window.fetchMock._calls.length.should.equal(3); + fetchMock._calls.length.should.equal(3); clock.restore(); done(); @@ -2714,7 +2716,7 @@ describe('forwarders', function() { mParticle.logEvent('foo', mParticle.EventType.Navigation); - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); expect(batch).to.have.property('application_info'); expect(batch.application_info).to.have.property( @@ -2731,7 +2733,7 @@ describe('forwarders', function() { mParticle.logEvent('foo', mParticle.EventType.Navigation); - const batch = JSON.parse(window.fetchMock.lastCall()[1].body); + const batch = JSON.parse(fetchMock.lastCall()[1].body); expect(batch).to.have.property('application_info'); expect(batch.application_info).not.to.have.property( diff --git a/test/src/tests-identities-attributes.js b/test/src/tests-identities-attributes.js index 9f2d1197..73f0ed86 100644 --- a/test/src/tests-identities-attributes.js +++ b/test/src/tests-identities-attributes.js @@ -1,5 +1,7 @@ import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; + import { urls, apiKey, testMPID, MPConfig } from './config'; @@ -15,7 +17,7 @@ describe('identities and attributes', function() { mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer.respondWith(urls.identify, [ 200, {}, @@ -26,7 +28,7 @@ describe('identities and attributes', function() { afterEach(function() { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); }); it('should set user attribute', function(done) { @@ -39,7 +41,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); event.should.have.property('user_attributes'); event.user_attributes.should.have.property('gender', 'male'); @@ -64,7 +66,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); let cookies = getLocalStorage(); cookies[testMPID].ua.should.have.property('gender', 'female'); @@ -76,7 +78,7 @@ describe('identities and attributes', function() { mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'male'); mParticle.logEvent('test user attributes2'); - const event2 = findBatch(window.fetchMock._calls, 'test user attributes2'); + const event2 = findBatch(fetchMock._calls, 'test user attributes2'); event2.user_attributes.should.have.property('Gender', 'male'); event2.user_attributes.should.not.have.property('gender'); @@ -99,7 +101,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); const cookies = getLocalStorage(); cookies[testMPID].ua.should.have.property('gender', 'male'); @@ -123,7 +125,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); event.user_attributes.should.not.have.property('gender'); const cookies = getLocalStorage(); @@ -143,7 +145,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); event.user_attributes.should.not.have.property('Gender'); const cookies = getLocalStorage(); @@ -157,12 +159,12 @@ describe('identities and attributes', function() { mParticle.logEvent('test event'); - const event = findEventFromRequest(window.fetchMock._calls, 'test event'); + const event = findEventFromRequest(fetchMock._calls, 'test event'); Should(event.data.custom_attributes).equal(null); mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); sessionEndEvent.data.custom_attributes.should.have.property('name', 'test'); @@ -175,7 +177,7 @@ describe('identities and attributes', function() { mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); sessionEndEvent.data.custom_attributes.should.have.property('name', 'test1'); sessionEndEvent.data.custom_attributes.should.not.have.property('Name'); @@ -186,13 +188,13 @@ describe('identities and attributes', function() { it("should not set a session attribute's key as an object or array)", function(done) { mParticle.setSessionAttribute({ key: 'value' }, 'test'); mParticle.endSession(); - const sessionEndEvent1 = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent1 = findEventFromRequest(fetchMock._calls, 'session_end'); mParticle.startNewSession(); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.setSessionAttribute(['test'], 'test'); mParticle.endSession(); - const sessionEndEvent2 = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent2 = findEventFromRequest(fetchMock._calls, 'session_end'); Object.keys(sessionEndEvent1.data.custom_attributes).length.should.equal(0); Object.keys(sessionEndEvent2.data.custom_attributes).length.should.equal(0); @@ -205,11 +207,11 @@ describe('identities and attributes', function() { mParticle.setSessionAttribute('name', 'test'); mParticle.endSession(); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.startNewSession(); mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); sessionEndEvent.data.custom_attributes.should.not.have.property('name'); @@ -220,7 +222,7 @@ describe('identities and attributes', function() { mParticle.setPosition(34.134103, -118.321694); mParticle.logEvent('Test Event'); - const event = findEventFromRequest(window.fetchMock._calls, 'Test Event'); + const event = findEventFromRequest(fetchMock._calls, 'Test Event'); event.data.should.have.property('location'); event.data.location.should.have.property('latitude', 34.134103); @@ -234,7 +236,7 @@ describe('identities and attributes', function() { mParticle.logEvent('Test Event'); - const event = findBatch(window.fetchMock._calls, 'Test Event'); + const event = findBatch(fetchMock._calls, 'Test Event'); event.should.have.property('user_attributes'); event.user_attributes.should.have.property('test', null); @@ -251,7 +253,7 @@ describe('identities and attributes', function() { mParticle.logEvent('Test Event'); - const event = findBatch(window.fetchMock._calls, 'Test Event'); + const event = findBatch(fetchMock._calls, 'Test Event'); event.should.have.property('user_attributes'); event.user_attributes.should.not.have.property('Test'); @@ -269,7 +271,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test event'); - const event = findBatch(window.fetchMock._calls, 'test event'); + const event = findBatch(fetchMock._calls, 'test event'); event.should.have.property('user_attributes'); event.user_attributes.should.not.have.property('test'); @@ -286,7 +288,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test event'); - const event = findBatch(window.fetchMock._calls, 'test event'); + const event = findBatch(fetchMock._calls, 'test event'); event.should.have.property('user_attributes'); event.user_attributes.should.not.have.property('Test'); @@ -311,7 +313,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); event.should.have.property('user_attributes'); event.user_attributes.should.have.property('numbers', [1, 2, 3, 4, 5]); @@ -344,7 +346,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); const cookies = getLocalStorage(); event.should.have.property('user_attributes'); @@ -361,7 +363,7 @@ describe('identities and attributes', function() { ]); mParticle.logEvent('test user attributes2'); - const event2 = findBatch(window.fetchMock._calls, 'test user attributes2'); + const event2 = findBatch(fetchMock._calls, 'test user attributes2'); const cookies3 = getLocalStorage(); event2.user_attributes.should.have.property('numbers', [1, 2, 3, 4, 5]); @@ -387,7 +389,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); const cookies = getLocalStorage(); @@ -414,7 +416,7 @@ describe('identities and attributes', function() { mParticle.logEvent('test user attributes'); - const event = findBatch(window.fetchMock._calls, 'test user attributes'); + const event = findBatch(fetchMock._calls, 'test user attributes'); const cookies = getLocalStorage(); event.should.have.property('user_attributes', {}); @@ -531,7 +533,7 @@ describe('identities and attributes', function() { mParticle.endSession(); - const sessionEndEvent = findEventFromRequest(window.fetchMock._calls, 'session_end'); + const sessionEndEvent = findEventFromRequest(fetchMock._calls, 'session_end'); sessionEndEvent.data.custom_attributes.should.not.have.property('name'); @@ -543,7 +545,7 @@ describe('identities and attributes', function() { bad: 'bad', }); mParticle.logEvent('test bad user attributes1'); - const event1 = findBatch(window.fetchMock._calls, 'test bad user attributes1'); + const event1 = findBatch(fetchMock._calls, 'test bad user attributes1'); mParticle.Identity.getCurrentUser().setUserAttribute('gender', [ 'bad', @@ -551,32 +553,32 @@ describe('identities and attributes', function() { 'bad', ]); mParticle.logEvent('test bad user attributes2'); - const event2 = findBatch(window.fetchMock._calls, 'test bad user attributes2'); + const event2 = findBatch(fetchMock._calls, 'test bad user attributes2'); mParticle.Identity.getCurrentUser().setUserAttribute( { bad: 'bad' }, 'male' ); mParticle.logEvent('test bad user attributes3'); - const event3 = findBatch(window.fetchMock._calls, 'test bad user attributes3'); + const event3 = findBatch(fetchMock._calls, 'test bad user attributes3'); mParticle.Identity.getCurrentUser().setUserAttribute( ['bad', 'bad', 'bad'], 'female' ); mParticle.logEvent('test bad user attributes4'); - const event4 = findBatch(window.fetchMock._calls, 'test bad user attributes4'); + const event4 = findBatch(fetchMock._calls, 'test bad user attributes4'); mParticle.Identity.getCurrentUser().setUserAttribute(null, 'female'); mParticle.logEvent('test bad user attributes5'); - const event5 = findBatch(window.fetchMock._calls, 'test bad user attributes5'); + const event5 = findBatch(fetchMock._calls, 'test bad user attributes5'); mParticle.Identity.getCurrentUser().setUserAttribute( undefined, 'female' ); mParticle.logEvent('test bad user attributes6'); - const event6 = findBatch(window.fetchMock._calls, 'test bad user attributes6'); + const event6 = findBatch(fetchMock._calls, 'test bad user attributes6'); event1.should.have.property('user_attributes'); event1.user_attributes.should.not.have.property('gender'); @@ -622,10 +624,10 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); // set a new attribute, age - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); - let body = JSON.parse(window.fetchMock.lastOptions().body) + let body = JSON.parse(fetchMock.lastOptions().body) body.user_attributes.should.have.property('age', '25') let event = body.events[0]; event.should.be.ok(); @@ -637,9 +639,9 @@ describe('identities and attributes', function() { event.data.is_new_attribute.should.equal(true); // change age attribute - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('age', '30'); - body = JSON.parse(window.fetchMock.lastOptions().body); + body = JSON.parse(fetchMock.lastOptions().body); body.user_attributes.should.have.property('age', '30') event = body.events[0]; event.event_type.should.equal('user_attribute_change'); @@ -650,9 +652,9 @@ describe('identities and attributes', function() { event.data.is_new_attribute.should.equal(false); // removes age attribute - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().removeUserAttribute('age'); - body = JSON.parse(window.fetchMock.lastOptions().body); + body = JSON.parse(fetchMock.lastOptions().body); body.user_attributes.should.not.have.property('age'); event = body.events[0]; event.event_type.should.equal('user_attribute_change'); @@ -663,13 +665,13 @@ describe('identities and attributes', function() { event.data.is_new_attribute.should.equal(false); // set a user attribute list - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttributeList('age', [ 'test1', 'test2', ]); - body = JSON.parse(window.fetchMock.lastOptions().body); + body = JSON.parse(fetchMock.lastOptions().body); body.user_attributes.age[0].should.equal('test1'); body.user_attributes.age[1].should.equal('test2'); @@ -688,17 +690,17 @@ describe('identities and attributes', function() { event.data.is_new_attribute.should.equal(true); // changes ordering of above attribute list - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttributeList('age', [ 'test2', 'test1', ]); - body = JSON.parse(window.fetchMock.lastOptions().body); + body = JSON.parse(fetchMock.lastOptions().body); body.user_attributes.age[0].should.equal('test2'); body.user_attributes.age[1].should.equal('test1'); - event = JSON.parse(window.fetchMock.lastOptions().body).events[0]; + event = JSON.parse(fetchMock.lastOptions().body).events[0]; event.event_type.should.equal('user_attribute_change'); obj = { test1: true, @@ -725,7 +727,7 @@ describe('identities and attributes', function() { mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); const testMPID = mParticle.Identity.getCurrentUser().getMPID(); - let body = JSON.parse(window.fetchMock.lastOptions().body) + let body = JSON.parse(fetchMock.lastOptions().body) body.mpid.should.equal(testMPID); let event = body.events[0] event.event_type.should.equal('user_attribute_change'); @@ -761,7 +763,7 @@ describe('identities and attributes', function() { testMPIDUser.getMPID().should.equal('testMPID'); anotherMPIDUser.setUserAttribute('age', '30'); - body = JSON.parse(window.fetchMock.lastOptions().body) + body = JSON.parse(fetchMock.lastOptions().body) event = body.events[0]; body.mpid.should.equal(anotherMPIDUser.getMPID()); event.event_type.should.equal('user_attribute_change'); @@ -772,7 +774,7 @@ describe('identities and attributes', function() { event.data.is_new_attribute.should.equal(true); testMPIDUser.setUserAttribute('age', '20'); - body = JSON.parse(window.fetchMock.lastOptions().body) + body = JSON.parse(fetchMock.lastOptions().body) body.mpid.should.equal(testMPIDUser.getMPID()); event = body.events[0]; event.event_type.should.equal('user_attribute_change'); @@ -784,7 +786,7 @@ describe('identities and attributes', function() { // remove user attribute anotherMPIDUser.removeUserAttribute('age'); - body = JSON.parse(window.fetchMock.lastOptions().body) + body = JSON.parse(fetchMock.lastOptions().body) body.mpid.should.equal(anotherMPIDUser.getMPID()); event = body.events[0]; event.event_type.should.equal('user_attribute_change'); @@ -796,7 +798,7 @@ describe('identities and attributes', function() { testMPIDUser.removeUserAttribute('age'); - body = JSON.parse(window.fetchMock.lastOptions().body) + body = JSON.parse(fetchMock.lastOptions().body) body.mpid.should.equal(testMPIDUser.getMPID()); event = body.events[0]; event.event_type.should.equal('user_attribute_change'); @@ -814,7 +816,7 @@ describe('identities and attributes', function() { it('should send user identity change requests when setting new identities on new users', function(done) { mParticle._resetForTests(MPConfig); - window.fetchMock._calls = []; + fetchMock._calls = []; window.mParticle.config.identifyRequest = { userIdentities: { @@ -824,16 +826,16 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); - JSON.parse(window.fetchMock.lastOptions().body).user_identities.should.have.property( + JSON.parse(fetchMock.lastOptions().body).user_identities.should.have.property( 'email', 'initial@gmail.com' ); mParticle.logEvent('testAfterInit'); - JSON.parse(window.fetchMock.lastOptions().body).user_identities.should.have.property('email', 'initial@gmail.com'); + JSON.parse(fetchMock.lastOptions().body).user_identities.should.have.property('email', 'initial@gmail.com'); - window.fetchMock.calls().forEach(call => { + fetchMock.calls().forEach(call => { JSON.parse(call[1].body).user_identities.should.have.property('email', 'initial@gmail.com') }); @@ -843,7 +845,7 @@ describe('identities and attributes', function() { JSON.stringify({ mpid: 'anotherMPID', is_logged_in: true }), ]); - window.fetchMock._calls = []; + fetchMock._calls = []; // anonymous user is in storage, new user logs in const loginUser = { @@ -853,7 +855,7 @@ describe('identities and attributes', function() { }; mParticle.Identity.login(loginUser); - let body = JSON.parse(window.fetchMock.lastOptions().body); + let body = JSON.parse(fetchMock.lastOptions().body); // should be the new MPID body.mpid.should.equal('anotherMPID'); @@ -873,7 +875,7 @@ describe('identities and attributes', function() { event.data.old.created_this_batch.should.equal(false); mParticle.logEvent('testAfterLogin'); - body = JSON.parse(window.fetchMock.lastOptions().body); + body = JSON.parse(fetchMock.lastOptions().body); body.user_identities.should.have.property('customer_id', 'customerid1'); body.user_identities.should.not.have.property('email'); @@ -891,7 +893,7 @@ describe('identities and attributes', function() { ]); mParticle.Identity.modify(modifyUser); - const body2 = JSON.parse(window.fetchMock.lastOptions().body); + const body2 = JSON.parse(fetchMock.lastOptions().body); body2.mpid.should.equal('anotherMPID'); body2.user_identities.should.have.property('customer_id', 'customerid2'); body2.user_identities.should.not.have.property('email'); @@ -916,11 +918,11 @@ describe('identities and attributes', function() { }, }; - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.modify(modifyUser2); - const body3 = JSON.parse(window.fetchMock.lastOptions().body); + const body3 = JSON.parse(fetchMock.lastOptions().body); body3.mpid.should.equal('anotherMPID'); const event3 = body3.events[0]; @@ -942,7 +944,7 @@ describe('identities and attributes', function() { other: 'other1', }, }; - window.fetchMock._calls = []; + fetchMock._calls = []; mockServer.respondWith(urls.logout, [ 200, @@ -952,8 +954,8 @@ describe('identities and attributes', function() { mParticle.Identity.logout(logoutUser); //only call is for `other` change event, not for previous ID types of email and customerid - window.fetchMock._calls.length.should.equal(1); - const body4 = JSON.parse(window.fetchMock.lastOptions().body); + fetchMock._calls.length.should.equal(1); + const body4 = JSON.parse(fetchMock.lastOptions().body); body4.mpid.should.equal('mpid2'); const event4 = body4.events[0]; @@ -971,7 +973,7 @@ describe('identities and attributes', function() { mParticle.logEvent('testAfterLogout'); - const body5 = JSON.parse(window.fetchMock.lastOptions().body); + const body5 = JSON.parse(fetchMock.lastOptions().body); body5.mpid.should.equal('mpid2'); Object.keys(body5.user_identities).length.should.equal(1); body5.user_identities.should.have.property('other', 'other1'); @@ -1009,7 +1011,7 @@ describe('identities and attributes', function() { mParticle.Identity.login(loginUser); - let batch = JSON.parse(window.fetchMock.lastOptions().body); + let batch = JSON.parse(fetchMock.lastOptions().body); batch.mpid.should.equal(testMPID); batch.user_identities.should.have.property('email', 'initial@gmail.com'); batch.user_identities.should.have.property('customer_id', 'customerid1'); @@ -1028,13 +1030,13 @@ describe('identities and attributes', function() { mParticle.Identity.logout(logoutUser); - batch = JSON.parse(window.fetchMock.lastOptions().body); + batch = JSON.parse(fetchMock.lastOptions().body); batch.mpid.should.equal('mpid2'); batch.user_identities.should.have.property('other', 'other1'); batch.user_identities.should.not.have.property('email'); batch.user_identities.should.not.have.property('customer_id'); - window.fetchMock._calls = []; + fetchMock._calls = []; // log back in with previous MPID, but with only a single UI, all UIs should be on batch mockServer.respondWith(urls.login, [ 200, @@ -1045,10 +1047,10 @@ describe('identities and attributes', function() { mParticle.Identity.login(loginUser); // switching back to logged in user shoudl not result in any UIC events - Should(window.fetchMock.lastOptions()).not.be.ok() + Should(fetchMock.lastOptions()).not.be.ok() mParticle.logEvent('event after logging back in') - batch = JSON.parse(window.fetchMock.lastOptions().body); + batch = JSON.parse(fetchMock.lastOptions().body); batch.mpid.should.equal(testMPID); batch.user_identities.should.have.property('email', 'initial@gmail.com'); batch.user_identities.should.have.property('customer_id', 'customerid1'); @@ -1066,9 +1068,9 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); // set a new attribute, age - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); - const body1 = JSON.parse(window.fetchMock.lastOptions().body) + const body1 = JSON.parse(fetchMock.lastOptions().body) body1.user_attributes.should.have.property('age', '25') const event1 = body1.events[0]; event1.should.be.ok(); @@ -1082,9 +1084,9 @@ describe('identities and attributes', function() { // test setting attributes with 'false' values (i.e false, 0 and '') // check for UAC event for testFalse: fasle when set for first time - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testFalse', false); - const body2 = JSON.parse(window.fetchMock.lastOptions().body) + const body2 = JSON.parse(fetchMock.lastOptions().body) body2.user_attributes.should.have.property('testFalse', false) const event2 = body2.events[0]; event2.should.be.ok(); @@ -1096,9 +1098,9 @@ describe('identities and attributes', function() { event2.data.is_new_attribute.should.equal(true); // check for UAC event for testEmptyString: '' when set for first time - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString', ''); - const body3 = JSON.parse(window.fetchMock.lastOptions().body) + const body3 = JSON.parse(fetchMock.lastOptions().body) body3.user_attributes.should.have.property('testEmptyString', '') const event3 = body3.events[0]; event3.should.be.ok(); @@ -1110,9 +1112,9 @@ describe('identities and attributes', function() { event3.data.is_new_attribute.should.equal(true); // check for UAC event for testZero: 0 when set for first time - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testZero', 0); - const body4 = JSON.parse(window.fetchMock.lastOptions().body) + const body4 = JSON.parse(fetchMock.lastOptions().body) body4.user_attributes.should.have.property('testZero', 0) const event4 = body4.events[0]; event4.should.be.ok(); @@ -1131,13 +1133,13 @@ describe('identities and attributes', function() { userAttributes.should.have.property('testZero'); // re-set all previous attributes with the same values - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('age', '25'); mParticle.Identity.getCurrentUser().setUserAttribute('testFalse', false); mParticle.Identity.getCurrentUser().setUserAttribute('testEmptyString', ''); mParticle.Identity.getCurrentUser().setUserAttribute('testZero', 0); - (window.fetchMock.lastOptions() === undefined).should.equal(true); - (window.fetchMock._calls.length === 0).should.equal(true); + (fetchMock.lastOptions() === undefined).should.equal(true); + (fetchMock._calls.length === 0).should.equal(true); done() }); @@ -1152,9 +1154,9 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); // set initial test attribute with 'falsey' value to 0 - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', 0); - const body1 = JSON.parse(window.fetchMock.lastOptions().body) + const body1 = JSON.parse(fetchMock.lastOptions().body) body1.user_attributes.should.have.property('testFalsey', 0) const event1 = body1.events[0]; event1.should.be.ok(); @@ -1166,9 +1168,9 @@ describe('identities and attributes', function() { event1.data.is_new_attribute.should.equal(true); // re-set same test attribute with 'falsey' value to '' - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', ''); - const body2 = JSON.parse(window.fetchMock.lastOptions().body) + const body2 = JSON.parse(fetchMock.lastOptions().body) body2.user_attributes.should.have.property('testFalsey', '') const event2 = body2.events[0]; event2.should.be.ok(); @@ -1180,9 +1182,9 @@ describe('identities and attributes', function() { event2.data.is_new_attribute.should.equal(false); // re-set same test attribute with 'falsey' value to false - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', false); - const body3 = JSON.parse(window.fetchMock.lastOptions().body) + const body3 = JSON.parse(fetchMock.lastOptions().body) body3.user_attributes.should.have.property('testFalsey', false) const event3 = body3.events[0]; event3.should.be.ok(); @@ -1194,9 +1196,9 @@ describe('identities and attributes', function() { event3.data.is_new_attribute.should.equal(false); // re-set same test attribute with 'falsey' value to original value 0 - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.Identity.getCurrentUser().setUserAttribute('testFalsey', 0); - const body4 = JSON.parse(window.fetchMock.lastOptions().body) + const body4 = JSON.parse(fetchMock.lastOptions().body) body4.user_attributes.should.have.property('testFalsey', 0) const event4 = body4.events[0]; event4.should.be.ok(); diff --git a/test/src/tests-identity.js b/test/src/tests-identity.js index 4117f140..2131362d 100644 --- a/test/src/tests-identity.js +++ b/test/src/tests-identity.js @@ -1,6 +1,7 @@ import Constants from '../../src/constants'; import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import { urls, apiKey, testMPID, MPConfig, @@ -22,7 +23,7 @@ let mockServer; describe('identity', function() { beforeEach(function() { delete mParticle.config.useCookieStorage; - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -36,7 +37,7 @@ describe('identity', function() { afterEach(function() { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); mParticle._resetForTests(MPConfig); }); @@ -1011,10 +1012,10 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.logEvent('Test Event1'); - let testEvent1 = findEventFromRequest(window.fetchMock._calls, 'Test Event1'); + let testEvent1 = findEventFromRequest(fetchMock._calls, 'Test Event1'); Should(testEvent1).not.be.ok(); @@ -1027,12 +1028,12 @@ describe('identity', function() { mParticle.logEvent('Test Event2'); mParticle.Identity.login(); // server requests will have AST, sessionStart, Test1, Test2, and login - testEvent1 = findEventFromRequest(window.fetchMock._calls, 'Test Event1'); - window.fetchMock._calls.length.should.equal(4); + testEvent1 = findEventFromRequest(fetchMock._calls, 'Test Event1'); + fetchMock._calls.length.should.equal(4); - const testEvent2 = findEventFromRequest(window.fetchMock._calls, 'Test Event2'); - const ASTEvent = findEventFromRequest(window.fetchMock._calls, 'application_state_transition'); - const sessionStartEvent = findEventFromRequest(window.fetchMock._calls, 'session_start'); + const testEvent2 = findEventFromRequest(fetchMock._calls, 'Test Event2'); + const ASTEvent = findEventFromRequest(fetchMock._calls, 'application_state_transition'); + const sessionStartEvent = findEventFromRequest(fetchMock._calls, 'session_start'); const loginEvent = getIdentityEvent(mockServer.requests, 'login'); Should(testEvent1).be.ok(); @@ -1276,7 +1277,7 @@ describe('identity', function() { mParticle.logEvent('Test Event1'); - const testEvent1Batch = findBatch(window.fetchMock._calls, 'Test Event1'); + const testEvent1Batch = findBatch(fetchMock._calls, 'Test Event1'); testEvent1Batch.user_attributes.should.have.property('foo1', 'bar1'); testEvent1Batch.user_identities.should.have.property('customer_id', 'customerid1'); @@ -1309,7 +1310,7 @@ describe('identity', function() { mParticle.Identity.logout(user2); mParticle.logEvent('Test Event2'); - const testEvent2Batch = findBatch(window.fetchMock._calls, 'Test Event2'); + const testEvent2Batch = findBatch(fetchMock._calls, 'Test Event2'); Object.keys(testEvent2Batch.user_attributes).length.should.equal(0); testEvent2Batch.user_identities.should.have.property('customer_id', 'customerid2'); @@ -1322,7 +1323,7 @@ describe('identity', function() { mParticle.Identity.login(user1); mParticle.logEvent('Test Event3'); - const testEvent3Batch = findBatch(window.fetchMock._calls, 'Test Event3'); + const testEvent3Batch = findBatch(fetchMock._calls, 'Test Event3'); testEvent3Batch.user_attributes.should.have.property('foo1', 'bar1'); Object.keys(testEvent3Batch.user_identities).length.should.equal(2); @@ -1688,7 +1689,7 @@ describe('identity', function() { mParticle.eCommerce.logCheckout(1); - const checkoutEvent = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent = findEventFromRequest(fetchMock._calls, 'checkout'); checkoutEvent.data.product_action.should.have.property('products', null) @@ -1699,10 +1700,10 @@ describe('identity', function() { ]); mParticle.Identity.login(identityAPIRequest1); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.eCommerce.logCheckout(1); - const checkoutEvent2 = findEventFromRequest(window.fetchMock._calls, 'checkout'); + const checkoutEvent2 = findEventFromRequest(fetchMock._calls, 'checkout'); checkoutEvent2.data.product_action.should.have.property('products', null); @@ -2023,14 +2024,14 @@ describe('identity', function() { mParticle.Identity.getCurrentUser().setUserAttribute('foo', 'bar'); }; - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.init(apiKey, window.mParticle.config); - (window.fetchMock._calls.length === 0).should.equal.true + (fetchMock._calls.length === 0).should.equal.true clock.tick(1000); - const sessionStartEventBatch = findBatch(window.fetchMock._calls, 'session_start'); - const ASTEventBatch = findBatch(window.fetchMock._calls, 'application_state_transition'); + const sessionStartEventBatch = findBatch(fetchMock._calls, 'session_start'); + const ASTEventBatch = findBatch(fetchMock._calls, 'application_state_transition'); sessionStartEventBatch.user_attributes.should.have.property('foo', 'bar'); ASTEventBatch.user_attributes.should.have.property('foo', 'bar'); @@ -2064,10 +2065,10 @@ describe('identity', function() { JSON.stringify({ mpid: 'MPID1', is_logged_in: false }), ]); - window.fetchMock._calls = []; + fetchMock._calls = []; mParticle.init(apiKey, window.mParticle.config); //the only server request is the AST, there is no request to Identity - window.fetchMock._calls.length.should.equal(1); + fetchMock._calls.length.should.equal(1); result.should.have.properties('body', 'httpCode', 'getUser'); result.httpCode.should.equal(-3); diff --git a/test/src/tests-main.js b/test/src/tests-main.js index 096da3a7..7b7db871 100644 --- a/test/src/tests-main.js +++ b/test/src/tests-main.js @@ -32,30 +32,30 @@ afterEach(function() { }); import '../cross-browser-testing/test-cross-browser' -// import './tests-core-sdk'; -// import './tests-batchUploader'; -// import './tests-beaconUpload'; -// import './tests-kit-blocking'; -// import './tests-persistence'; -// import './tests-forwarders'; +import './tests-core-sdk'; +import './tests-batchUploader'; +import './tests-beaconUpload'; +import './tests-kit-blocking'; +import './tests-persistence'; +import './tests-forwarders'; import './tests-helpers'; -// import './tests-identity'; -// import './tests-event-logging'; -// import './tests-eCommerce'; -// import './tests-cookie-syncing'; -// import './tests-identities-attributes'; -// import './tests-native-sdk'; -// import './tests-consent'; -// import './tests-serverModel'; -// import './tests-mockBatchCreator.ts'; -// import './tests-mParticleUser'; -// import './tests-self-hosting-specific'; -// import './tests-runtimeToBatchEventsDTO'; -// import './tests-apiClient'; -// import './tests-mparticle-instance-manager'; -// import './tests-queue-public-methods'; -// import './tests-validators'; -// import './tests-utils'; -// import './tests-session-manager'; -// import './tests-store'; -// import './tests-config-api-client'; +import './tests-identity'; +import './tests-event-logging'; +import './tests-eCommerce'; +import './tests-cookie-syncing'; +import './tests-identities-attributes'; +import './tests-native-sdk'; +import './tests-consent'; +import './tests-serverModel'; +import './tests-mockBatchCreator.ts'; +import './tests-mParticleUser'; +import './tests-self-hosting-specific'; +import './tests-runtimeToBatchEventsDTO'; +import './tests-apiClient'; +import './tests-mparticle-instance-manager'; +import './tests-queue-public-methods'; +import './tests-validators'; +import './tests-utils'; +import './tests-session-manager'; +import './tests-store'; +import './tests-config-api-client'; diff --git a/test/src/tests-mparticle-instance-manager.js b/test/src/tests-mparticle-instance-manager.js index 0a9579ee..26d140bd 100644 --- a/test/src/tests-mparticle-instance-manager.js +++ b/test/src/tests-mparticle-instance-manager.js @@ -1,4 +1,5 @@ import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import { urls, MPConfig } from './config'; import Utils from './utils'; const findEventFromRequest = Utils.findEventFromRequest; @@ -174,6 +175,22 @@ describe('mParticle instance manager', function() { }); describe('multiple instances testing', function() { + before(function () { + // default instance event mock + fetchMock.post( + 'https://jssdks.mparticle.com/v3/JS/apiKey1/events', + 200 + ); + fetchMock.post( + 'https://jssdks.mparticle.com/v3/JS/apiKey2/events', + 200 + ); + fetchMock.post( + 'https://jssdks.mparticle.com/v3/JS/apiKey3/events', + 200 + ); + }); + beforeEach(function() { //remove each of the instance's localStorage localStorage.removeItem('mprtcl-v4_wtTest1'); @@ -204,20 +221,6 @@ describe('mParticle instance manager', function() { [200, {}, JSON.stringify({ workspaceToken: 'wtTest3' })] ); - // default instance event mock - window.fetchMock.post( - 'https://jssdks.mparticle.com/v3/JS/apiKey1/events', - 200 - ); - window.fetchMock.post( - 'https://jssdks.mparticle.com/v3/JS/apiKey2/events', - 200 - ); - window.fetchMock.post( - 'https://jssdks.mparticle.com/v3/JS/apiKey3/events', - 200 - ); - // identity mock mockServer.respondWith( urls.identify, @@ -258,63 +261,63 @@ describe('mParticle instance manager', function() { mParticle.getInstance('instance3').logEvent('hi3'); const instance1Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey1', 'hi1' ); instance1Event.should.be.ok(); const instance2Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey2', 'hi2' ); instance2Event.should.be.ok(); const instance3Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'hi3' ); instance3Event.should.be.ok(); const instance1EventsFail1 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey1', 'hi2' ); Should(instance1EventsFail1).not.be.ok(); const instance1EventsFail2 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey1', 'hi3' ); Should(instance1EventsFail2).not.be.ok(); const instance2EventsFail1 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey2', 'hi1' ); Should(instance2EventsFail1).not.be.ok(); const instance2EventsFail2 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey2', 'hi3' ); Should(instance2EventsFail2).not.be.ok(); const instance3EventsFail1 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'hi1' ); Should(instance3EventsFail1).not.be.ok(); const instance3EventsFail2 = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'hi2' ); @@ -371,17 +374,17 @@ describe('mParticle instance manager', function() { .eCommerce.logPurchase(ta, [product1, product2]); const instance1Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey1', 'purchase' ); let instance2Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey2', 'purchase' ); let instance3Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'purchase' ); @@ -394,12 +397,12 @@ describe('mParticle instance manager', function() { .eCommerce.logPurchase(ta, [product1, product2]); instance2Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey2', 'purchase' ); instance3Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'purchase' ); @@ -412,7 +415,7 @@ describe('mParticle instance manager', function() { .eCommerce.logPurchase(ta, [product1, product2]); instance3Event = returnEventForMPInstance( - window.fetchMock._calls, + fetchMock._calls, 'apiKey3', 'purchase' ); diff --git a/test/src/tests-persistence.ts b/test/src/tests-persistence.ts index f20bbabe..9ad253e8 100644 --- a/test/src/tests-persistence.ts +++ b/test/src/tests-persistence.ts @@ -1,5 +1,6 @@ import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import { urls, @@ -33,7 +34,7 @@ let mockServer; describe('migrations and persistence-related', () => { beforeEach(() => { - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -47,7 +48,7 @@ describe('migrations and persistence-related', () => { afterEach(() => { mockServer.restore(); - window.fetchMock.restore(); + fetchMock.restore(); }); it('should move new schema from cookies to localStorage with useCookieStorage = false', done => { @@ -433,7 +434,7 @@ describe('migrations and persistence-related', () => { mParticle.init(apiKey, mParticle.config); mParticle.logEvent('Test Event'); - const testEvent = findBatch(window.fetchMock._calls, 'Test Event'); + const testEvent = findBatch(fetchMock._calls, 'Test Event'); testEvent.integration_attributes.should.have.property('128'); testEvent.integration_attributes['128'].should.have.property('MCID', 'abcedfg'); diff --git a/test/src/tests-self-hosting-specific.js b/test/src/tests-self-hosting-specific.js index dfeb71c9..6dd7c9b9 100644 --- a/test/src/tests-self-hosting-specific.js +++ b/test/src/tests-self-hosting-specific.js @@ -1,5 +1,7 @@ import Utils from './utils'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; + import { urls, apiKey, MPConfig } from './config'; const { findEventFromRequest, findBatch } = Utils; @@ -9,12 +11,12 @@ let mockServer; // Calls to /config are specific to only the self hosting environment describe('/config self-hosting integration tests', function() { beforeEach(function() { - window.fetchMock.post(urls.events, 200); + fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); }); afterEach(function() { - window.fetchMock.restore(); + fetchMock.restore(); sinon.restore(); }) @@ -47,13 +49,13 @@ describe('/config self-hosting integration tests', function() { // log event before config and identify come back mParticle.logEvent('Test'); - let event = findEventFromRequest(window.fetchMock._calls, 'Test'); + let event = findEventFromRequest(fetchMock._calls, 'Test'); Should(event).not.be.ok(); // config and identify now get triggered, which runs through the event queue clock.tick(300); - event = findBatch(window.fetchMock._calls, 'Test'); + event = findBatch(fetchMock._calls, 'Test'); event.should.be.ok(); event.mpid.should.equal('identifyMPID'); @@ -112,7 +114,7 @@ describe('/config self-hosting integration tests', function() { // config triggers, login triggers immediately before identify clock.tick(300); - const event1 = findBatch(window.fetchMock._calls, 'Test'); + const event1 = findBatch(fetchMock._calls, 'Test'); event1.mpid.should.equal('loginMPID'); messages .indexOf('Parsing "login" identity response from server') @@ -122,7 +124,7 @@ describe('/config self-hosting integration tests', function() { messages .indexOf('Parsing "identify" identity response from server') .should.equal(-1); - const event2 = findBatch(window.fetchMock._calls, 'identify callback event', false, mockServer); + const event2 = findBatch(fetchMock._calls, 'identify callback event', false, mockServer); event2.mpid.should.equal('loginMPID'); mockServer.restore();