From abf73f7d94255d9e8fe688841f955bd511c14894 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Thu, 15 Oct 2020 15:18:15 -0400 Subject: [PATCH 01/33] build: remove fake titanium-sdk node_module used by titanium CLI tisdk3fixes hook --- build/lib/packager.js | 19 +------------------ build/titanium-sdk/lib/titanium.js | 4 ---- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 build/titanium-sdk/lib/titanium.js diff --git a/build/lib/packager.js b/build/lib/packager.js index 65af3e7d971..df68fb26081 100644 --- a/build/lib/packager.js +++ b/build/lib/packager.js @@ -148,10 +148,7 @@ class Packager { } // Include 'ti.cloak' - await utils.unzip(path.join(ROOT_DIR, 'support', 'ti.cloak.zip'), path.join(this.zipSDKDir, 'node_modules')); - - // hack the fake titanium-sdk npm package in - return this.hackTitaniumSDKModule(); + return utils.unzip(path.join(ROOT_DIR, 'support', 'ti.cloak.zip'), path.join(this.zipSDKDir, 'node_modules')); } /** @@ -201,20 +198,6 @@ class Packager { return copyFiles(this.srcDir, this.zipSDKDir, files); } - async hackTitaniumSDKModule() { - // FIXME Remove these hacks for titanium-sdk when titanium-cli has been released and the tisdk3fixes.js hook is gone! - // Now copy over hacked titanium-sdk fake node_module - console.log('Copying titanium-sdk node_module stub for backwards compatibility with titanium-cli'); - await fs.copy(path.join(__dirname, '../titanium-sdk'), path.join(this.zipSDKDir, 'node_modules/titanium-sdk')); - - // Hack the package.json to include "titanium-sdk": "*" in dependencies - console.log('Inserting titanium-sdk as production dependency'); - const packageJSONPath = path.join(this.zipSDKDir, 'package.json'); - const packageJSON = require(packageJSONPath); // eslint-disable-line security/detect-non-literal-require - packageJSON.dependencies['titanium-sdk'] = '*'; - return fs.writeJSON(packageJSONPath, packageJSON); - } - /** * Includes the pre-packaged pre-built native modules. We now gather them from a JSON file listing URLs to download. */ diff --git a/build/titanium-sdk/lib/titanium.js b/build/titanium-sdk/lib/titanium.js deleted file mode 100644 index f9030dd12fa..00000000000 --- a/build/titanium-sdk/lib/titanium.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; - -var ti = require('node-titanium-sdk/lib/titanium'); -exports.validateCorrectSDK = ti.validateCorrectSDK; From a7120186948916a4b3b33c7972be1bcd56370ce8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 10:24:55 +0000 Subject: [PATCH 02/33] build(deps-dev): bump mocha from 8.1.3 to 8.2.0 Bumps [mocha](https://github.com/mochajs/mocha) from 8.1.3 to 8.2.0. - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v8.1.3...v8.2.0) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 523 ++++++++++------------------------------------ package.json | 2 +- 2 files changed, 117 insertions(+), 408 deletions(-) diff --git a/package-lock.json b/package-lock.json index c6945731470..52e0e1d823b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3930,6 +3930,12 @@ "@types/node": "*" } }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -4481,71 +4487,6 @@ } } }, - "array.prototype.map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", - "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.4" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -6868,86 +6809,6 @@ "object-keys": "^1.0.12" } }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", - "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", - "dev": true, - "requires": { - "es-abstract": "^1.17.4", - "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", @@ -7850,21 +7711,10 @@ } }, "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "flat-cache": { "version": "2.0.1", @@ -9141,12 +8991,6 @@ "kind-of": "^3.0.2" } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -9249,12 +9093,6 @@ "is-extglob": "^2.1.1" } }, - "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", - "dev": true - }, "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -9321,12 +9159,6 @@ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, - "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -9576,22 +9408,6 @@ "istanbul-lib-report": "^3.0.0" } }, - "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", - "dev": true - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, "jake": { "version": "10.8.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", @@ -11164,15 +10980,16 @@ } }, "mocha": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", - "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.0.tgz", + "integrity": "sha512-lEWEMq2LMfNJMKeuEwb5UELi+OgFDollXaytR5ggQcHpzG3NP/R7rvixAvF+9/lLsTWhWG+4yD2M70GsM06nxw==", "dev": true, "requires": { + "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.4.2", - "debug": "4.1.1", + "chokidar": "3.4.3", + "debug": "4.2.0", "diff": "4.0.2", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", @@ -11183,32 +11000,50 @@ "log-symbols": "4.0.0", "minimatch": "3.0.4", "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", + "nanoid": "3.1.12", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "7.2.0", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.0.0", + "workerpool": "6.0.2", "yargs": "13.3.2", "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" + "yargs-unparser": "2.0.0" }, "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "diff": { @@ -11223,6 +11058,15 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -11239,6 +11083,12 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -11280,20 +11130,29 @@ "dev": true }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11352,6 +11211,12 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" }, + "nanoid": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "dev": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -13138,72 +13003,6 @@ } } }, - "promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "requires": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, "psl": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", @@ -13402,6 +13201,15 @@ "minimatch": "^3.0.4" } }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "readline-sync": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", @@ -13906,9 +13714,9 @@ "dev": true }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -15497,9 +15305,9 @@ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" }, "workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", "dev": true }, "wrap-ansi": { @@ -15755,127 +15563,28 @@ } }, "yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "yargs-parser": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", - "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, diff --git a/package.json b/package.json index 36be9fd59ae..d5c7bf1ef81 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "glob": "^7.1.6", "husky": "^4.3.0", "lint-staged": "^10.4.0", - "mocha": "^8.1.3", + "mocha": "^8.2.0", "mocha-jenkins-reporter": "^0.4.5", "npm-run-all": "^4.1.5", "nyc": "^15.1.0", From 732f6ec336b68aedfee1103d661ee2086fb0f35f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 10:59:06 +0000 Subject: [PATCH 03/33] build(deps-dev): bump lint-staged from 10.4.0 to 10.4.2 Bumps [lint-staged](https://github.com/okonet/lint-staged) from 10.4.0 to 10.4.2. - [Release notes](https://github.com/okonet/lint-staged/releases) - [Commits](https://github.com/okonet/lint-staged/compare/v10.4.0...v10.4.2) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 42 +++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 52e0e1d823b..dee20778811 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5369,12 +5369,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -9667,9 +9666,9 @@ } }, "lint-staged": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.0.tgz", - "integrity": "sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.2.tgz", + "integrity": "sha512-OLCA9K1hS+Sl179SO6kX0JtnsaKj/MZalEhUj5yAgXsb63qPI/Gfn6Ua1KuZdbfkZNEu3/n5C/obYCu70IMt9g==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -9690,12 +9689,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -9745,12 +9743,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "execa": { @@ -9913,12 +9911,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -10383,12 +10380,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, diff --git a/package.json b/package.json index d5c7bf1ef81..6ed73c167e7 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "folder-hash": "^4.0.0", "glob": "^7.1.6", "husky": "^4.3.0", - "lint-staged": "^10.4.0", + "lint-staged": "^10.4.2", "mocha": "^8.2.0", "mocha-jenkins-reporter": "^0.4.5", "npm-run-all": "^4.1.5", From 2f852afecac00234a5803ad113dcca5f6a5372fe Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 11:23:58 +0000 Subject: [PATCH 04/33] build(deps-dev): bump rollup from 2.31.0 to 2.32.0 Bumps [rollup](https://github.com/rollup/rollup) from 2.31.0 to 2.32.0. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.31.0...v2.32.0) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index dee20778811..36af1cd9135 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13537,9 +13537,9 @@ } }, "rollup": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.31.0.tgz", - "integrity": "sha512-0d8S3XwEZ7aCP910/9SjnelgLvC+ZXziouVolzxPOM1zvKkHioGkWGJIWmlOULlmvB8BZ6S0wrgsT4yMz0eyMg==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.0.tgz", + "integrity": "sha512-0FIG1jY88uhCP2yP4CfvtKEqPDRmsUwfY1kEOOM+DH/KOGATgaIFd/is1+fQOxsvh62ELzcFfKonwKWnHhrqmw==", "dev": true, "requires": { "fsevents": "~2.1.2" diff --git a/package.json b/package.json index 6ed73c167e7..78bb81618cc 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "request-promise-native": "^1.0.9", - "rollup": "^2.31.0", + "rollup": "^2.32.0", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", From ebc3800e22c77ec5761652cb49fa0fd5edae9ccc Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Fri, 16 Oct 2020 15:26:50 -0400 Subject: [PATCH 05/33] chore(deps): update android to use v8 8.6.395.10 --- android/package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/android/package.json b/android/package.json index 88e2cfd9abb..fee1aca9606 100644 --- a/android/package.json +++ b/android/package.json @@ -19,10 +19,9 @@ ], "architectures": ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"], "v8": { - "version": "8.4.371.22", + "version": "8.6.395.10", "mode": "release", - "checksum": "4fd238e9e22dda0a6d67cf132d95ac6b874cf82bec28769e25672877b3cca09ef9ef268be9482e2cc0ca20227f495e5d3ad038c83a9b90f72ad9d5e6a7bad77d", - "integrity": "sha512-YIZPTv0KMbd+TrtUDszGOBnVvpr8HnyX7cYn+s0mT/XAURC57ni1QH9hA/HCTsGciWQBeHAHX1yZjE0cR/pesw==" + "integrity": "sha512-0b+/oiaae52wbTY6svDWAGJn7wyfBfBzGHNREY5uu1VTAbG8g962SwphhB0798pM1YMLR76RO7JvKQBv6sGP9A==" }, "minSDKVersion": "19", "compileSDKVersion": "30", From f77659212deb2fc7291bd7c7f19d0b4d553c14f6 Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Thu, 15 Oct 2020 19:20:18 -0700 Subject: [PATCH 06/33] chore(android): updated gradle/dependency versions - Updated gradle from 6.5.1 to 6.7 - Updated Androd gradle tool from 4.0.1 to 4.1.0 * Can no longer use Android Studio versions older than 4.1 - Updated kotlin from 1.4.0 to 1.4.10 - Updated AndroidX dependencies to newest versions - Removed remaining "ant" related files from Titanium SDK Fixes TIMOB-28173 --- android/app/build.gradle | 2 +- android/build.gradle | 10 +- android/gradle/wrapper/gradle-wrapper.jar | Bin 58694 -> 58910 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/gradlew | 2 + android/gradlew.bat | 1 + android/kroll-apt/build.gradle | 2 +- android/runtime/common/AndroidManifest.xml | 11 -- android/runtime/common/proguard.cfg | 40 ----- android/runtime/common/project.properties | 12 -- android/runtime/common/res/values/strings.xml | 4 - android/runtime/v8/AndroidManifest.xml | 14 -- .../runtime/v8/cdt_formatting_standard.xml | 166 ------------------ android/runtime/v8/proguard.cfg | 40 ----- android/runtime/v8/project.properties | 13 -- android/runtime/v8/res/values/strings.xml | 4 - android/templates/build/root.build.gradle | 6 +- android/templates/build/ti.constants.gradle | 10 +- android/titanium/build.gradle | 10 +- 19 files changed, 25 insertions(+), 324 deletions(-) delete mode 100644 android/runtime/common/AndroidManifest.xml delete mode 100644 android/runtime/common/proguard.cfg delete mode 100644 android/runtime/common/project.properties delete mode 100644 android/runtime/common/res/values/strings.xml delete mode 100644 android/runtime/v8/AndroidManifest.xml delete mode 100644 android/runtime/v8/cdt_formatting_standard.xml delete mode 100644 android/runtime/v8/proguard.cfg delete mode 100644 android/runtime/v8/project.properties delete mode 100644 android/runtime/v8/res/values/strings.xml diff --git a/android/app/build.gradle b/android/app/build.gradle index f6d8b211dfb..abc3ab19791 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2019 by Axway. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway. All Rights Reserved. * Licensed under the terms of the Apache Public License. * Please see the LICENSE included with this distribution for details. */ diff --git a/android/build.gradle b/android/build.gradle index 236c28dcb5a..3ac4d4c9ee8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,20 +1,20 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2019 by Axway. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway. All Rights Reserved. * Licensed under the terms of the Apache Public License. * Please see the LICENSE included with this distribution for details. */ buildscript { - ext.kotlin_version = '1.4.0' + ext.kotlin_version = '1.4.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'com.google.gms:google-services:4.3.3' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.google.gms:google-services:4.3.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -28,7 +28,7 @@ allprojects { // Load plugin used to enforce our Java coding style guidelines. project.apply plugin: 'checkstyle' checkstyle { - toolVersion = '8.34' + toolVersion = '8.36.2' configFile file("${rootDir}/checkstyle.xml"); ignoreFailures false showViolations true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar index 490fda8577df6c95960ba7077c43220e5bb2c0d9..62d4c053550b91381bbd28b1afc82d634bf73a8a 100644 GIT binary patch delta 6447 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 F{|nTN-B$nr diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index ac33e9944a6..14e30f7416a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew index 2fe81a7d95e..fbd7c515832 100755 --- a/android/gradlew +++ b/android/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/android/gradlew.bat b/android/gradlew.bat index 9109989e3cb..a9f778a7a96 100644 --- a/android/gradlew.bat +++ b/android/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% diff --git a/android/kroll-apt/build.gradle b/android/kroll-apt/build.gradle index 43fa7c6f491..8fb4524f749 100644 --- a/android/kroll-apt/build.gradle +++ b/android/kroll-apt/build.gradle @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2019 by Axway. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway. All Rights Reserved. * Licensed under the terms of the Apache Public License. * Please see the LICENSE included with this distribution for details. */ diff --git a/android/runtime/common/AndroidManifest.xml b/android/runtime/common/AndroidManifest.xml deleted file mode 100644 index 94af589d037..00000000000 --- a/android/runtime/common/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/android/runtime/common/proguard.cfg b/android/runtime/common/proguard.cfg deleted file mode 100644 index b1cdf17b5bb..00000000000 --- a/android/runtime/common/proguard.cfg +++ /dev/null @@ -1,40 +0,0 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService - --keepclasseswithmembernames class * { - native ; -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} diff --git a/android/runtime/common/project.properties b/android/runtime/common/project.properties deleted file mode 100644 index b15f1208ad4..00000000000 --- a/android/runtime/common/project.properties +++ /dev/null @@ -1,12 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -android.library=true -# Project target. -target=Google Inc.:Google APIs:16 diff --git a/android/runtime/common/res/values/strings.xml b/android/runtime/common/res/values/strings.xml deleted file mode 100644 index 8f48259afca..00000000000 --- a/android/runtime/common/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - kroll-common - diff --git a/android/runtime/v8/AndroidManifest.xml b/android/runtime/v8/AndroidManifest.xml deleted file mode 100644 index da636c7e46c..00000000000 --- a/android/runtime/v8/AndroidManifest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/android/runtime/v8/cdt_formatting_standard.xml b/android/runtime/v8/cdt_formatting_standard.xml deleted file mode 100644 index ddf963574f2..00000000000 --- a/android/runtime/v8/cdt_formatting_standard.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/runtime/v8/proguard.cfg b/android/runtime/v8/proguard.cfg deleted file mode 100644 index b1cdf17b5bb..00000000000 --- a/android/runtime/v8/proguard.cfg +++ /dev/null @@ -1,40 +0,0 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService - --keepclasseswithmembernames class * { - native ; -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} diff --git a/android/runtime/v8/project.properties b/android/runtime/v8/project.properties deleted file mode 100644 index 3fb98c31866..00000000000 --- a/android/runtime/v8/project.properties +++ /dev/null @@ -1,13 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -android.library=true -android.library.reference.1=../common -# Project target. -target=android-19 diff --git a/android/runtime/v8/res/values/strings.xml b/android/runtime/v8/res/values/strings.xml deleted file mode 100644 index bb427c215af..00000000000 --- a/android/runtime/v8/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - kroll-v8 - diff --git a/android/templates/build/root.build.gradle b/android/templates/build/root.build.gradle index fd2d68a59ff..6cc739e1500 100644 --- a/android/templates/build/root.build.gradle +++ b/android/templates/build/root.build.gradle @@ -1,14 +1,14 @@ buildscript { - ext.kotlin_version = '1.4.0' + ext.kotlin_version = '1.4.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'com.google.gms:google-services:4.3.3' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.google.gms:google-services:4.3.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/android/templates/build/ti.constants.gradle b/android/templates/build/ti.constants.gradle index 4b84d09cd61..bd4a76fb0af 100644 --- a/android/templates/build/ti.constants.gradle +++ b/android/templates/build/ti.constants.gradle @@ -1,16 +1,16 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2019 by Axway. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway. All Rights Reserved. * Licensed under the terms of the Apache Public License. * Please see the LICENSE included with this distribution for details. */ project.ext { - tiAndroidXAppCompatLibVersion = '1.1.0' - tiAndroidXCoreLibVersion = '1.3.0' + tiAndroidXAppCompatLibVersion = '1.2.0' + tiAndroidXCoreLibVersion = '1.3.2' tiAndroidXFragmentLibVersion = '1.2.5' - tiMaterialLibVersion = '1.1.0' - tiPlayServicesBaseLibVersion = '17.3.0' + tiMaterialLibVersion = '1.2.1' + tiPlayServicesBaseLibVersion = '17.4.0' tiManifestPlaceholders = [ tiActivityConfigChanges: 'density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode' ] diff --git a/android/titanium/build.gradle b/android/titanium/build.gradle index 153de474293..616411cac34 100644 --- a/android/titanium/build.gradle +++ b/android/titanium/build.gradle @@ -64,6 +64,8 @@ android { targetSdkVersion 30 versionName tiBuildVersionString versionCode tiBuildVersionCode + buildConfigField('int', 'VERSION_CODE', tiBuildVersionCode.toString()) + buildConfigField('String', 'VERSION_NAME', '"' + tiBuildVersionString + '"') buildConfigField('String', 'TI_BUILD_HASH_STRING', '"' + tiBuildHashString + '"') buildConfigField('String', 'TI_BUILD_TIME_STRING', '"' + tiBuildTimeString + '"') manifestPlaceholders = project.ext.tiManifestPlaceholders @@ -288,10 +290,10 @@ dependencies { implementation "androidx.appcompat:appcompat:${project.ext.tiAndroidXAppCompatLibVersion}" implementation 'androidx.cardview:cardview:1.0.0' implementation "androidx.core:core:${project.ext.tiAndroidXCoreLibVersion}" - implementation 'androidx.drawerlayout:drawerlayout:1.1.0' - implementation 'androidx.exifinterface:exifinterface:1.2.0' + implementation 'androidx.drawerlayout:drawerlayout:1.1.1' + implementation 'androidx.exifinterface:exifinterface:1.3.1' implementation "androidx.fragment:fragment:${project.ext.tiAndroidXFragmentLibVersion}" - implementation 'androidx.media:media:1.1.0' + implementation 'androidx.media:media:1.2.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.transition:transition:1.3.1' @@ -309,7 +311,7 @@ dependencies { // The Google Play Services libraries are only used by Titanium's geolocation feature. // We link to them dynamically at runtime. So, they can be safely excluded when in the app project. implementation "com.google.android.gms:play-services-base:${project.ext.tiPlayServicesBaseLibVersion}" - implementation 'com.google.android.gms:play-services-location:17.0.0' + implementation 'com.google.android.gms:play-services-location:17.1.0' // WebSocket library is needed to do JavaScript debugging. implementation 'org.java-websocket:Java-WebSocket:1.5.1' From 8deb674c55f5ea2c5192c024b224edfb5e68786e Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Thu, 15 Oct 2020 22:40:21 -0700 Subject: [PATCH 07/33] feat(android): added build/scons-gradlew script - Guarantees "local.properties" file is alway generating when running lint. --- build/lib/android/index.js | 32 ++++++++++++++++++-------------- build/scons-gradlew.js | 27 +++++++++++++++++++++++++++ build/scons.js | 1 + lint-staged.config.js | 2 +- package.json | 2 +- 5 files changed, 48 insertions(+), 16 deletions(-) create mode 100755 build/scons-gradlew.js diff --git a/build/lib/android/index.js b/build/lib/android/index.js index 92c30f91be3..098e62c6d20 100644 --- a/build/lib/android/index.js +++ b/build/lib/android/index.js @@ -71,17 +71,11 @@ class Android { } async clean() { - // Create "local.properties" file which tells gradle where to find the Android SDK/NDK directories. - await createLocalPropertiesFile(this.androidSdk, this.androidNdk); - // Clean all Titanium Android projects. - await gradlew('clean'); + await this.runGradleTask('clean'); } async build() { - // Create "local.properties" file which tells gradle where to find the Android SDK/NDK directories. - await createLocalPropertiesFile(this.androidSdk, this.androidNdk); - // Set up the build system to fail if unable to generate a V8 snapshot. Needed for fast app startup times. // Note: Allow system to override this behavior if environment variable is already defined. if (typeof process.env.TI_SDK_BUILD_REQUIRES_V8_SNAPSHOTS === 'undefined') { @@ -93,7 +87,7 @@ class Android { process.env.TI_SDK_BUILD_GIT_HASH = this.gitHash; process.env.TI_SDK_BUILD_TIMESTAMP = this.timestamp; process.env.TI_SDK_VERSION_TAG = this.versionTag; - await gradlew(':titanium:assembleRelease'); + await this.runGradleTask(':titanium:assembleRelease'); } async package(packager) { @@ -103,14 +97,11 @@ class Android { const ZIP_ANDROID_PATH = path.join(packager.zipSDKDir, 'android'); await fs.mkdirs(ZIP_ANDROID_PATH); - // Create "local.properties" file which tells gradle where to find the Android SDK/NDK directories. - await createLocalPropertiesFile(this.androidSdk, this.androidNdk); - // Generate a maven repo directory structure and dependencies POM file for last built Titanium AAR library. process.env.TI_SDK_BUILD_VERSION = this.sdkVersion; process.env.TI_SDK_BUILD_GIT_HASH = this.gitHash; process.env.TI_SDK_VERSION_TAG = this.versionTag; - await gradlew(':titanium:publish'); + await this.runGradleTask(':titanium:publish'); // Copy the above created maven directory tree to the destination. await copyFile(path.join(TITANIUM_ANDROID_PATH, 'titanium', 'build', 'outputs'), ZIP_ANDROID_PATH, 'm2repository'); @@ -166,11 +157,24 @@ class Android { // This generates C/C++ interop code between JavaScript and the Java APIs which have these annotations. await copyFile(path.join(TITANIUM_ANDROID_PATH, 'kroll-apt', 'build', 'libs'), ZIP_ANDROID_PATH, 'kroll-apt.jar'); } + + async runGradleTask(task, args) { + // Create "local.properties" file which tells gradle where to find the Android SDK/NDK directories. + await createLocalPropertiesFile(this.androidSdk, this.androidNdk); + + // Run the given gradle task. + const newArgs = [ task ]; + if (Array.isArray(args)) { + newArgs.push(...args); + } else { + newArgs.push('--console', GRADLE_CONSOLE_MODE, '--warning-mode', 'all'); + } + await gradlew(newArgs); + } } -async function gradlew(task) { +async function gradlew(args) { await new Promise((resolve, reject) => { - const args = [ task, '--console', GRADLE_CONSOLE_MODE, '--warning-mode', 'all' ]; const childProcess = spawn(GRADLEW_FILE_PATH, args, { cwd: TITANIUM_ANDROID_PATH, stdio: 'inherit' }); childProcess.on('error', reject); childProcess.on('exit', (exitCode) => { diff --git a/build/scons-gradlew.js b/build/scons-gradlew.js new file mode 100755 index 00000000000..8b5e306576c --- /dev/null +++ b/build/scons-gradlew.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node +'use strict'; + +const version = require('../package.json').version; +const program = require('commander'); + +const argsIndex = process.argv.indexOf('--args'); +const mainArgs = (argsIndex >= 0) ? process.argv.slice(0, argsIndex) : process.argv; +const gradlewArgs = (argsIndex >= 0) ? process.argv.slice(argsIndex + 1) : null; + +program + .arguments('') + .option('-v, --sdk-version [version]', 'Override the SDK version we report', process.env.PRODUCT_VERSION || version) + .option('-t, --version-tag [tag]', 'Override the SDK version tag we report') + .option('-s, --android-sdk [path]', 'Explicitly set the path to the Android SDK used for building') + .option('-n, --android-ndk [path]', 'Explicitly set the path to the Android NDK used for building') + .option('--args [arguments...]', 'Arguments to be passed to gradlew tool (Must be set last)') + .action((task, options) => { + const AndroidBuilder = require('./lib/android'); + new AndroidBuilder(options).runGradleTask(task, gradlewArgs) + .then(() => process.exit(0)) + .catch(err => { + console.error(err); + return process.exit(1); + }); + }) + .parse(mainArgs); diff --git a/build/scons.js b/build/scons.js index 53af0b7b511..d1258531040 100755 --- a/build/scons.js +++ b/build/scons.js @@ -21,6 +21,7 @@ commander .command('xcode-test', 'Hacks the XCode project for iOS to copy in the unit test suite so it can be run under XCode\'s debugger') .command('check-ios-toplevel', 'Ensures we don\'t check in prefilled values for version/hash/timestamp') .command('xcode-project-build ', 'Runs the portion of the xcode project setup') + .command('gradlew ', 'Executes an Android gradle task via the gradlew command line tool') .command('deprecations', 'Checks the apidocs for deprecated but unremoved types/properties/methods') .command('removals ', 'Checks the apidocs for deprecated and removed types/properties/methods older than a given version') .parse(process.argv); diff --git a/lint-staged.config.js b/lint-staged.config.js index 3c1db5619ae..43e73c35514 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -13,7 +13,7 @@ const asyncFilter = async (arr, predicate) => { module.exports = { 'android/**/*.java': filenames => { - return `./android/gradlew checkJavaStyle -p ./android --console plain -PchangedFiles='${filenames.join(',')}'`; + return `./build/node scons gradlew checkJavaStyle --args --console plain -PchangedFiles='${filenames.join(',')}'`; }, 'iphone/**/*.{m,h}': [ 'npx clang-format -style=file -i' diff --git a/package.json b/package.json index 78bb81618cc..5169b557b77 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "ios-sanity-check": "./build/scons check-ios-toplevel", "link": "npm run deploy -- --symlink", "lint": "npm-run-all --parallel lint:!\\(ios\\)", - "lint:android": "./android/gradlew checkJavaStyle -p ./android --console plain", + "lint:android": "./build/scons gradlew checkJavaStyle", "lint:docs": "tdoc-validate ./apidoc", "lint:ios": "npm-run-all --parallel lint:objc lint:swift", "lint:objc": "clang-format-lint $npm_package_config_format_objc", From 4e148ae4374eea3a3d4803c52ccd7c88a8ae7cff Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Tue, 6 Oct 2020 20:07:26 -0700 Subject: [PATCH 08/33] refactor(android): temp file handling - Moved Ti.Filesystem.tempDirectory location: * From: .//cache/_tmp * To: .//cache/.titanium/tmp - Moved Ti.Filesystem.createTempFile() location: * From: Ti.Filesystem.applicationCacheDirectory * To: Ti.Filesystem.tempDirectory - Moved Ti.Filesystem.createTempDirectory() location: * From a directory Titanium did not provide a constant for. * To: Ti.Filesystem.tempDirectory - Modified HTTP response cache file handling: * Moved from external storage to internal storage for privacy. * Now supports caching if app does not have WRITE_EXTERNAL_STORAGE permission. (No longer requires this permission.) * No longer monitors external storage mounting/unmounting. - Simplified temp file deletion via hidden "trash" folder. - Partially removed usage of "TiTempFileHelper.java" class. Will fully remove in next commit. Fixes TIMOB-28058 --- .../titanium/filesystem/FilesystemModule.java | 35 +-- .../titanium/network/TiHTTPClient.java | 28 +-- .../appcelerator/kroll/KrollApplication.java | 6 +- .../kroll/util/TiTempFileHelper.java | 2 + .../appcelerator/titanium/TiApplication.java | 213 +++++++++++++----- .../titanium/util/TiResponseCache.java | 18 +- 6 files changed, 192 insertions(+), 110 deletions(-) diff --git a/android/modules/filesystem/src/java/ti/modules/titanium/filesystem/FilesystemModule.java b/android/modules/filesystem/src/java/ti/modules/titanium/filesystem/FilesystemModule.java index 4b9685a7af1..2e799060a9c 100644 --- a/android/modules/filesystem/src/java/ti/modules/titanium/filesystem/FilesystemModule.java +++ b/android/modules/filesystem/src/java/ti/modules/titanium/filesystem/FilesystemModule.java @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2016 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -52,24 +52,32 @@ public FilesystemModule() public FileProxy createTempFile(KrollInvocation invocation) { try { - File f = File.createTempFile("tifile", "tmp"); - String[] parts = { f.getAbsolutePath() }; + File file = File.createTempFile("tifile", ".tmp", TiApplication.getInstance().getTiTempDir()); + String[] parts = { file.getAbsolutePath() }; return new FileProxy(invocation.getSourceUrl(), parts, false); - } catch (IOException e) { - Log.e(TAG, "Unable to create tmp file: " + e.getMessage(), e); - return null; + } catch (Exception ex) { + Log.e(TAG, "Unable to create tmp file: " + ex.getMessage(), ex); } + return null; } @Kroll.method public FileProxy createTempDirectory(KrollInvocation invocation) { - String dir = String.valueOf(System.currentTimeMillis()); - File tmpdir = new File(System.getProperty("java.io.tmpdir")); - File f = new File(tmpdir, dir); - f.mkdirs(); - String[] parts = { f.getAbsolutePath() }; - return new FileProxy(invocation.getSourceUrl(), parts); + try { + File parentDir = TiApplication.getInstance().getTiTempDir(); + String tempDirName = "tidir" + System.currentTimeMillis(); + File tempDir = new File(parentDir, tempDirName); + for (int index = 0; tempDir.exists(); index++) { + tempDir = new File(parentDir, tempDirName + index); + } + tempDir.mkdirs(); + String[] parts = { tempDir.getAbsolutePath() }; + return new FileProxy(invocation.getSourceUrl(), parts, false); + } catch (Exception ex) { + Log.e(TAG, "Unable to create tmp directory: " + ex.getMessage(), ex); + } + return null; } @Kroll.method @@ -186,8 +194,7 @@ public String getExternalStorageDirectory() @Kroll.getProperty public String getTempDirectory() { - TiApplication tiApplication = TiApplication.getInstance(); - return "file://" + tiApplication.getTempFileHelper().getTempDirectory().getAbsolutePath(); + return "file://" + TiApplication.getInstance().getTiTempDir().getAbsolutePath(); } @Kroll.method diff --git a/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java b/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java index e7e8c4723e8..6dba3ddf3f9 100644 --- a/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java +++ b/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -52,7 +52,6 @@ import android.util.Base64; import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.common.Log; -import org.appcelerator.kroll.util.TiTempFileHelper; import org.appcelerator.titanium.TiApplication; import org.appcelerator.titanium.TiBlob; import org.appcelerator.titanium.TiC; @@ -281,11 +280,6 @@ private TiFile createFileResponseData(boolean dumpResponseOut) throws IOExceptio outFile = tiFile.getFile(); try { responseOut = new FileOutputStream(outFile, dumpResponseOut); - // If the response file is in the temp folder, don't delete it during cleanup. - TiApplication app = TiApplication.getInstance(); - if (app != null) { - app.getTempFileHelper().excludeFileOnCleanup(outFile); - } } catch (FileNotFoundException e) { responseFile = null; tiFile = null; @@ -299,12 +293,8 @@ private TiFile createFileResponseData(boolean dumpResponseOut) throws IOExceptio } if (tiFile == null) { - TiApplication app = TiApplication.getInstance(); - if (app != null) { - TiTempFileHelper tempFileHelper = app.getTempFileHelper(); - outFile = tempFileHelper.createTempFile("tihttp", "tmp"); - tiFile = new TiFile(outFile, outFile.getAbsolutePath(), false); - } + outFile = File.createTempFile("tihttp", ".tmp", TiApplication.getInstance().getTiTempDir()); + tiFile = new TiFile(outFile, outFile.getAbsolutePath(), false); } if (dumpResponseOut) { @@ -1018,8 +1008,10 @@ private int addTitaniumFileAsPostData(String name, Object value) blob = ((TiResourceFile) value).read(); } String mimeType = blob.getMimeType(); - File tmpFile = - File.createTempFile("tixhr", "." + TiMimeTypeHelper.getFileExtensionFromMimeType(mimeType, "txt")); + File tmpFile = File.createTempFile( + "tixhr", + "." + TiMimeTypeHelper.getFileExtensionFromMimeType(mimeType, "txt"), + TiApplication.getInstance().getTiTempDir()); createFileFromBlob(blob, tmpFile); tmpFiles.add(tmpFile); @@ -1132,8 +1124,10 @@ private Object titaniumFileAsPutData(Object value) blob = ((TiResourceFile) value).read(); } String mimeType = blob.getMimeType(); - File tmpFile = - File.createTempFile("tixhr", "." + TiMimeTypeHelper.getFileExtensionFromMimeType(mimeType, "txt")); + File tmpFile = File.createTempFile( + "tixhr", + "." + TiMimeTypeHelper.getFileExtensionFromMimeType(mimeType, "txt"), + TiApplication.getInstance().getTiTempDir()); createFileFromBlob(blob, tmpFile); tmpFiles.add(tmpFile); diff --git a/android/runtime/common/src/java/org/appcelerator/kroll/KrollApplication.java b/android/runtime/common/src/java/org/appcelerator/kroll/KrollApplication.java index d36847d255f..ef5cba802ed 100644 --- a/android/runtime/common/src/java/org/appcelerator/kroll/KrollApplication.java +++ b/android/runtime/common/src/java/org/appcelerator/kroll/KrollApplication.java @@ -6,11 +6,9 @@ */ package org.appcelerator.kroll; +import android.app.Activity; import org.appcelerator.kroll.common.CurrentActivityListener; import org.appcelerator.kroll.common.TiDeployData; -import org.appcelerator.kroll.util.TiTempFileHelper; - -import android.app.Activity; /** * An interface for things Kroll needs from the application instance @@ -24,8 +22,6 @@ public interface KrollApplication { void waitForCurrentActivity(CurrentActivityListener l); - TiTempFileHelper getTempFileHelper(); - TiDeployData getDeployData(); boolean isFastDevMode(); diff --git a/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java b/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java index 58bcbaf05db..f39e6f367ea 100644 --- a/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java +++ b/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java @@ -6,6 +6,8 @@ */ package org.appcelerator.kroll.util; +//TODO: Delete this file... + import java.io.File; import java.io.IOException; import java.util.ArrayList; diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java index 81108c546d8..cf8fa018e09 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -33,7 +33,6 @@ import org.appcelerator.kroll.common.TiDeployData; import org.appcelerator.kroll.common.TiMessenger; import org.appcelerator.kroll.util.KrollAssetHelper; -import org.appcelerator.kroll.util.TiTempFileHelper; import org.appcelerator.titanium.util.TiBlobLruCache; import org.appcelerator.titanium.util.TiFileHelper; import org.appcelerator.titanium.util.TiImageLruCache; @@ -91,13 +90,10 @@ public abstract class TiApplication extends Application implements KrollApplicat private WeakReference currentActivity; private String density; private String defaultUnit; - private TiResponseCache responseCache; private BroadcastReceiver localeReceiver; - private BroadcastReceiver externalStorageReceiver; private AccessibilityManager accessibilityManager = null; protected TiDeployData deployData; - protected TiTempFileHelper tempFileHelper; protected ITiAppInfo appInfo; protected TiStylesheet stylesheet; protected HashMap> modules; @@ -360,12 +356,13 @@ public void uncaughtException(Thread t, Throwable e) proxyMap = new HashMap>(5); - tempFileHelper = new TiTempFileHelper(this); - deployData = new TiDeployData(this); registerActivityLifecycleCallbacks(new TiApplicationLifecycle()); + // Delete all Titanium temp files created from previous app execution. + deleteTiTempFiles(); + // Set up a listener to be invoked just before Titanium's JavaScript runtime gets terminated. // Note: Runtime will be terminated once all Titanium activities have been destroyed. KrollRuntime.addOnDisposingListener(new KrollRuntime.OnDisposingListener() { @@ -380,6 +377,9 @@ public void onDisposing(KrollRuntime runtime) // Cancel all Titanium timers. cancelTimers(); + + // Delete all Titanium temp files. + deleteTiTempFiles(); } }); } @@ -388,7 +388,6 @@ public void onDisposing(KrollRuntime runtime) public void onTerminate() { stopLocaleMonitor(); - stopExternalStorageMonitor(); accessibilityManager = null; super.onTerminate(); } @@ -468,23 +467,158 @@ public void postOnCreate() TiConfig.DEBUG = TiConfig.LOGD = appProperties.getBool("ti.android.debug", false); USE_LEGACY_WINDOW = appProperties.getBool(PROPERTY_USE_LEGACY_WINDOW, false); + // Start listening for system locale changes. startLocaleMonitor(); - startExternalStorageMonitor(); - // Register the default cache handler - responseCache = new TiResponseCache(getRemoteCacheDir(), this); - TiResponseCache.setDefault(responseCache); + // Register our custom HTTP response cache handler. + TiResponseCache.setDefault(new TiResponseCache( + tryCreateDir(getTiInternalCacheDir(), "http-response-cache"), this)); + + // Set up an unhandled exception handler. KrollRuntime.setPrimaryExceptionHandler(new TiExceptionHandler()); } - private File getRemoteCacheDir() + /** + * Gets Titanium's hidden caches directory on internal storage. + * @return Return a file object referencing the specified directory. + */ + private File getTiInternalCacheDir() + { + return tryCreateDir(getCacheDir(), ".titanium"); + } + + /** + * Gets the "Ti.Filesystem.tempDirectory" folder on internal storage. + * @return Return a file object referencing the specified directory. + */ + public File getTiTempDir() { - File cacheDir = new File(tempFileHelper.getTempDirectory(), "remote-cache"); - if (!cacheDir.exists()) { - cacheDir.mkdirs(); - tempFileHelper.excludeFileOnCleanup(cacheDir); + return tryCreateDir(getTiInternalCacheDir(), "tmp"); + } + + /** + * Creates the given directory. Will catch and log any exception that may occur doing so. + * @param directory Reference to the directory to be created. Can be null. + * @return Returns the "directory" argument reference. + */ + private File tryCreateDir(File directory) + { + return tryCreateDir(directory, null); + } + + /** + * Creates the given directory. Will catch and log any exception that may occur doing so. + * @param parent Reference to the directory to be created. Can be null. + * @param child The relative subdirectory path to be appended to the given parent. Can be null. + * @return + * Returns a new file object referencing the combined "parent" and "child" path. + * Returns the "parent" argument if the "child" argument is null. + */ + private File tryCreateDir(File parent, String child) + { + // Validate argument. + if (parent == null) { + return null; + } + + // Append the child path to the parent folder and create the directory tree. + File file = (child != null) ? new File(parent, child) : parent; + try { + file.mkdirs(); + } catch (Throwable ex) { + Log.w(TAG, "Failed to create directory tree.", ex); + } + return file; + } + + /** Deletes all temporary files created under the "Ti.Filesystem.tempDirectory" folder. */ + private void deleteTiTempFiles() + { + // Create the "trash" directory if it doesn't already exist. + File trashDir = tryCreateDir(getTiInternalCacheDir(), "trash"); + + // Set up an array of all temp directories to be trashed. + File[] dirArray = new File[] { + // The "Ti.Filesystem.tempDirectory" folder. + getTiTempDir(), + + // The legacy temp folder used before Titanium 9.3.0. Won't exist for new app installations. + new File(getCacheDir(), "_tmp") + }; + + // Trash the above directories. + String renameSuffix = "_" + System.currentTimeMillis(); + for (File nextDir : dirArray) { + boolean wasTrashed = true; + try { + // Move folder under the "trash" folder to be deleted asynchronously. + if (nextDir.exists()) { + wasTrashed = false; + wasTrashed = nextDir.renameTo(new File(trashDir, nextDir.getName() + renameSuffix)); + } + } catch (Exception ex) { + Log.e(TAG, "Failed to trash directory: " + nextDir, ex); + } finally { + // If failed to move existing folder to "trash", then do a blocking delete. (Should never happen.) + if (!wasTrashed) { + tryDeleteTree(nextDir); + } + } } - return cacheDir.getAbsoluteFile(); + + // Async delete the "trash" directory tree. + Thread thread = new Thread(() -> { + tryDeleteTree(trashDir); + }); + thread.start(); + } + + /** + * Recursively deletes the given directory tree. + * Will never throw an exception and will return the result as a boolean instead. + * @param file Reference to a file or directory. Can be null. + * @return + * Returns true if successfully deleted all files and folders under given directory tree. + * Returns false if at least 1 deletion failed or if given a null argument. + */ + private boolean tryDeleteTree(File file) + { + boolean wasSuccessful = false; + try { + if (file != null) { + wasSuccessful = deleteTree(file); + } + } catch (Throwable ex) { + Log.e(TAG, "Failed to delete directory tree: " + file, ex); + } + return wasSuccessful; + } + + /** + * Recursively deletes the given directory tree. + * @param file Reference to a directory or a single file. Can be null, in which case this method no-ops. + * @return + * Returns true if successfully deleted all files and folders under given directory tree. + * Returns false if at least 1 deletion failed or if given a null argument. + * @exception SecurityException Thrown if don't have permission to delete at least 1 file in the tree. + */ + private boolean deleteTree(File file) throws SecurityException + { + // Validate argument. + if (file == null) { + return false; + } + + // If given a directory, then recursively delete the entire tree. + boolean wasDeleted = true; + if (file.isDirectory()) { + for (File nextFile : file.listFiles()) { + wasDeleted = deleteTree(nextFile) && wasDeleted; + } + } + + // Delete the given directory/file. + return (file.delete() && wasDeleted); } public void setRootActivity(TiRootActivity rootActivity) @@ -511,8 +645,6 @@ public void setRootActivity(TiRootActivity rootActivity) break; } } - - tempFileHelper.scheduleCleanTempDir(); } /** @@ -836,12 +968,6 @@ public void softRestart() TiApplication.launch(); } - @Override - public TiTempFileHelper getTempFileHelper() - { - return tempFileHelper; - } - /** * @return true if the current thread is the main thread, false otherwise. * @module.api @@ -909,41 +1035,6 @@ private void stopLocaleMonitor() unregisterReceiver(localeReceiver); } - private void startExternalStorageMonitor() - { - externalStorageReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) - { - if (Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction())) { - responseCache.setCacheDir(getRemoteCacheDir()); - TiResponseCache.setDefault(responseCache); - Log.i(TAG, "SD card has been mounted. Enabling cache for http responses.", Log.DEBUG_MODE); - - } else { - // if the sd card is removed, we don't cache http responses - TiResponseCache.setDefault(null); - Log.i(TAG, "SD card has been unmounted. Disabling cache for http responses.", Log.DEBUG_MODE); - } - } - }; - - IntentFilter filter = new IntentFilter(); - - filter.addAction(Intent.ACTION_MEDIA_MOUNTED); - filter.addAction(Intent.ACTION_MEDIA_REMOVED); - filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); - filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL); - filter.addDataScheme("file"); - - registerReceiver(externalStorageReceiver, filter); - } - - private void stopExternalStorageMonitor() - { - unregisterReceiver(externalStorageReceiver); - } - @Override public void dispose() { diff --git a/android/titanium/src/java/org/appcelerator/titanium/util/TiResponseCache.java b/android/titanium/src/java/org/appcelerator/titanium/util/TiResponseCache.java index 9ff1b7132da..4fdddf88ab5 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/util/TiResponseCache.java +++ b/android/titanium/src/java/org/appcelerator/titanium/util/TiResponseCache.java @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2009-2020 by Axway, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -13,7 +13,6 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -50,8 +49,7 @@ public class TiResponseCache extends ResponseCache private static final int DEFAULT_CACHE_SIZE = 25 * 1024 * 1024; // 25MB private static final int INITIAL_DELAY = 10000; private static final int CLEANUP_DELAY = 60000; - private static HashMap> completeListeners = - new HashMap>(); + private static HashMap> completeListeners = new HashMap<>(); private static long maxCacheSize = 0; // List of Video Media Formats from http://developer.android.com/guide/appendix/media-formats.html @@ -74,18 +72,12 @@ public TiCacheCleanup(File cacheDir, long maxSize) this.maxSize = maxSize; } - // TODO @Override + @Override public void run() { // Build up a list of access times HashMap lastTime = new HashMap(); - for (File hdrFile : cacheDir.listFiles(new FilenameFilter() { - // TODO @Override - public boolean accept(File dir, String name) - { - return name.endsWith(HEADER_SUFFIX); - } - })) { + for (File hdrFile : cacheDir.listFiles((dir, name) -> name.endsWith(HEADER_SUFFIX))) { lastTime.put(hdrFile.lastModified(), hdrFile); } @@ -400,7 +392,7 @@ public TiResponseCache(File cachedir, TiApplication tiApp) { super(); assert cachedir.isDirectory() : "cachedir MUST be a directory"; - cacheDir = cachedir; + this.cacheDir = cachedir; maxCacheSize = tiApp.getAppProperties().getInt(CACHE_SIZE_KEY, DEFAULT_CACHE_SIZE) * 1024; Log.d(TAG, "max cache size is:" + maxCacheSize, Log.DEBUG_MODE); From b2dfd31830b5269b21041d85160d4b560edc2a4b Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Tue, 6 Oct 2020 21:57:57 -0700 Subject: [PATCH 09/33] test: createTempFile()/Dir() is in Ti.Filesystem.tempDirectory path --- tests/Resources/ti.filesystem.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Resources/ti.filesystem.test.js b/tests/Resources/ti.filesystem.test.js index cd4d3dc9834..d4330b629de 100644 --- a/tests/Resources/ti.filesystem.test.js +++ b/tests/Resources/ti.filesystem.test.js @@ -104,14 +104,14 @@ describe('Titanium.Filesystem', () => { stream.close(); }); - // FIXME Get working on Android. Either exists() or deleteDirectory() is returning false - it.androidBroken('createTempDirectory()', () => { + it('createTempDirectory()', () => { should(Ti.Filesystem.createTempDirectory).not.be.undefined(); should(Ti.Filesystem.createTempDirectory).be.a.Function(); const dir = Ti.Filesystem.createTempDirectory(); should.exist(dir); should.exist(dir.name); should(dir.exists()).be.true(); + should(dir.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, dir.name).nativePath); should(dir.deleteDirectory()).be.true(); should(dir.exists()).be.false(); }); @@ -124,6 +124,7 @@ describe('Titanium.Filesystem', () => { should(file).be.ok(); // not null or undefined. should(file).not.; causes a stack overflow somehow. should(file.name).be.a.String(); should(file.exists()).be.true(); + should(file.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, file.name).nativePath); should(file.deleteFile()).be.true(); should(file.exists()).be.false(); }); From 8aaf973832860d8a49833a00c9142d69505dd41f Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Tue, 13 Oct 2020 09:24:28 -0700 Subject: [PATCH 10/33] refactor(android): removed "TiTempFileHelper.java" --- .../kroll/util/TiTempFileHelper.java | 198 ------------------ 1 file changed, 198 deletions(-) delete mode 100644 android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java diff --git a/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java b/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java deleted file mode 100644 index f39e6f367ea..00000000000 --- a/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Appcelerator Titanium Mobile - * Copyright (c) 2011-2012 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -package org.appcelerator.kroll.util; - -//TODO: Delete this file... - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -import org.appcelerator.kroll.common.Log; - -import android.Manifest; -import android.app.Application; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Environment; -import android.content.Context; - -/** - * This class helps create and delete temporary files in the app's external cache directory. - * Temporary files will be automatically deleted the next time the application starts, or whenever {@link #scheduleCleanTempDir()} - * is called - */ -public class TiTempFileHelper -{ - private static final String TAG = "TiTempFileHelper"; - - public static final String TEMPDIR = "_tmp"; - public static final int DEFAULT_CLEAN_TIMEOUT = 5; // The number of seconds the async cleanup method uses for - - protected File tempDir; - protected ArrayList createdThisSession = new ArrayList(); - - private String previousExternalStorageState; - private String appPackageName; - private File internalCacheDir; - private Context context; - - public TiTempFileHelper(Application app) - { - appPackageName = app.getPackageName(); - internalCacheDir = app.getCacheDir(); - context = app.getApplicationContext(); - - updateTempDir(); - } - - /** - * Create a temporary file inside the external cache directory - * - * @see File#createTempFile(String, String) - * @throws IOException - * when the external storage state is either unmounted or read only - */ - public File createTempFile(String prefix, String suffix) throws IOException - { - updateTempDir(); - File tempFile = File.createTempFile(prefix, suffix, tempDir); - excludeFileOnCleanup(tempFile); - return tempFile; - } - - /** - * This method is equivalent to - * - *
-	 * scheduleCleanTempDir(TiTempFileHelper.DEFAULT_CLEAN_TIMEOUT, TimeUnit.SECONDS)
-	 * 
- */ - public void scheduleCleanTempDir() - { - scheduleCleanTempDir(DEFAULT_CLEAN_TIMEOUT, TimeUnit.SECONDS); - } - - /** - * Walks the temporary directory and deletes all of the files. - * This method runs asynchronously in a low priority thread, using the - * passed in timeout and time units. - */ - public void scheduleCleanTempDir(long delay, TimeUnit timeUnit) - { - if (!tempDir.exists()) { - Log.w(TAG, "The external temp directory doesn't exist, skipping cleanup"); - return; - } - - ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); - - service.schedule(new AsyncCleanup(service), delay, timeUnit); - } - - protected class AsyncCleanup implements Runnable, ThreadFactory - { - protected ExecutorService service; - - public AsyncCleanup(ExecutorService service) - { - this.service = service; - } - - // TODO @Override - public void run() - { - doCleanTempDir(); - service.shutdown(); - } - - // TODO @Override - public Thread newThread(Runnable r) - { - Thread thread = new Thread(r); - thread.setPriority(Thread.MIN_PRIORITY); - return thread; - } - } - - /** - * Adds file to the list of temp files created during this session. It will only be added to the list if the file - * is located in the temp folder. This file will not be wiped during cleanup. - */ - public void excludeFileOnCleanup(File f) - { - if (f != null && tempDir.equals(f.getParentFile())) { - synchronized (createdThisSession) - { - createdThisSession.add(f.getAbsolutePath()); - } - } - } - - protected void doCleanTempDir() - { - if (!tempDir.exists()) { - Log.w(TAG, "The temp directory doesn't exist, skipping cleanup"); - return; - } - for (File file : tempDir.listFiles()) { - String absolutePath = file.getAbsolutePath(); - synchronized (createdThisSession) - { - if (createdThisSession.contains(absolutePath)) { - continue; - } - } - - Log.d(TAG, "Deleting temporary file " + absolutePath, Log.DEBUG_MODE); - try { - file.delete(); - } catch (Exception e) { - Log.w(TAG, "Exception trying to delete " + absolutePath + ", skipping", e, Log.DEBUG_MODE); - } - } - } - - public File getTempDirectory() - { - updateTempDir(); - return tempDir; - } - - private void updateTempDir() - { - String extState = Environment.getExternalStorageState(); - if (!extState.equals(previousExternalStorageState)) { - if (Environment.MEDIA_MOUNTED.equals(extState) - && (Build.VERSION.SDK_INT < 23 - || (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED - && context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED))) { - - // See http://developer.android.com/guide/topics/data/data-storage.html#ExternalCache - // getExternalCacheDir() is available since API 8 - File externalCacheDir = context.getExternalCacheDir(); - tempDir = new File(externalCacheDir, TEMPDIR); - } else { - // Use internal storage cache if SD card is removed - tempDir = new File(internalCacheDir, TEMPDIR); - } - - // go ahead and make sure the temp directory exists - if (!tempDir.exists()) { - tempDir.mkdirs(); - } - } - previousExternalStorageState = extState; - } -} From 8f3dfc5230aa65c20fc6e90d16cfd84196ea70e7 Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Fri, 16 Oct 2020 17:13:33 -0700 Subject: [PATCH 11/33] chore(android): update temp file changes based on feedback --- .../src/java/org/appcelerator/titanium/TiApplication.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java index cf8fa018e09..c656a5ba07c 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java @@ -538,7 +538,7 @@ private void deleteTiTempFiles() File trashDir = tryCreateDir(getTiInternalCacheDir(), "trash"); // Set up an array of all temp directories to be trashed. - File[] dirArray = new File[] { + File[] dirArray = { // The "Ti.Filesystem.tempDirectory" folder. getTiTempDir(), @@ -585,9 +585,7 @@ private boolean tryDeleteTree(File file) { boolean wasSuccessful = false; try { - if (file != null) { - wasSuccessful = deleteTree(file); - } + wasSuccessful = deleteTree(file); } catch (Throwable ex) { Log.e(TAG, "Failed to delete directory tree: " + file, ex); } @@ -618,7 +616,7 @@ private boolean deleteTree(File file) throws SecurityException } // Delete the given directory/file. - return (file.delete() && wasDeleted); + return (wasDeleted && file.delete()); } public void setRootActivity(TiRootActivity rootActivity) From 5e2b5a45b816fa13ce33b06a8d5d7bd10abaec61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Mon, 19 Oct 2020 23:33:35 +0200 Subject: [PATCH 12/33] fix(ios): fix MediaModule compile error (#12187) Fixes TIMOB-28202 --- iphone/Classes/MediaModule.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iphone/Classes/MediaModule.m b/iphone/Classes/MediaModule.m index b3319511532..99a3756f8b0 100644 --- a/iphone/Classes/MediaModule.m +++ b/iphone/Classes/MediaModule.m @@ -2016,7 +2016,7 @@ - (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationCon - (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController { #if defined(USE_TI_MEDIASHOWCAMERA) || defined(USE_TI_MEDIAOPENPHOTOGALLERY) || defined(USE_TI_MEDIASTARTVIDEOEDITING) -#if IS_SDK_IOS_14 +#if IS_SDK_IOS_14 && defined(USE_TI_MEDIAOPENPHOTOGALLERY) [self closeModalPicker:picker ?: _phPicker]; #else [self closeModalPicker:picker]; From a292c8619be9904081712003e3872d446afb02a3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2020 10:25:41 +0000 Subject: [PATCH 13/33] build(deps-dev): bump titanium-docgen from 4.8.1 to 4.8.2 Bumps [titanium-docgen](https://github.com/appcelerator/docs-devkit/tree/HEAD/packages/titanium-docgen) from 4.8.1 to 4.8.2. - [Release notes](https://github.com/appcelerator/docs-devkit/releases) - [Changelog](https://github.com/appcelerator/docs-devkit/blob/develop/packages/titanium-docgen/CHANGELOG.md) - [Commits](https://github.com/appcelerator/docs-devkit/commits/v4.8.2/packages/titanium-docgen) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 32 ++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 36af1cd9135..3fb1a17604d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9657,9 +9657,9 @@ "dev": true }, "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", "dev": true, "requires": { "uc.micro": "^1.0.1" @@ -10586,16 +10586,24 @@ } }, "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.1.tgz", + "integrity": "sha512-+y+88n2za9jayLU9ELoGdTKucnW4qIIg6JRWmkesrw8LBnp/Eb2Vurg2P1epf+iNvpRc7IzDjbYcgreOuuOZzw==", "dev": true, "requires": { - "argparse": "^1.0.7", + "argparse": "^2.0.1", "entities": "~2.0.0", - "linkify-it": "^2.0.0", + "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + } } }, "mdurl": { @@ -14713,15 +14721,15 @@ } }, "titanium-docgen": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/titanium-docgen/-/titanium-docgen-4.8.1.tgz", - "integrity": "sha512-UTk47gLVC16lllVAGw2eey8JgM2lrMlQU8wd8r5nyGHPJkmHWOJp1Wr9nYW6NGzml1cVGftYaz/GCK+S1mjlOg==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/titanium-docgen/-/titanium-docgen-4.8.2.tgz", + "integrity": "sha512-/gdk894JbEwsMf+c1k0fkITuAIKgihYRU2A2BqLaPVpty5rnnJXgYv/4HovOK4XeBA8O/ELtUCUH/QGHtgYrGw==", "dev": true, "requires": { "colors": "^1.4.0", "ejs": "^3.0.1", "js-yaml": "^3.13.1", - "markdown-it": "^10.0.0", + "markdown-it": "^12.0.0", "node-appc": "^0.3.4" }, "dependencies": { diff --git a/package.json b/package.json index 5169b557b77..758865f5c8f 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "stream-splitter": "^0.3.2", "strip-ansi": "^6.0.0", "titanium": "^5.2.5", - "titanium-docgen": "^4.8.1" + "titanium-docgen": "^4.8.2" }, "repository": { "type": "git", From a611572591aa48c68f3fd33ff7dfa8b74c0a4d81 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 10:26:17 +0000 Subject: [PATCH 14/33] build(deps-dev): bump commitizen from 4.2.1 to 4.2.2 Bumps [commitizen](https://github.com/commitizen/cz-cli) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/commitizen/cz-cli/releases) - [Commits](https://github.com/commitizen/cz-cli/compare/v4.2.1...v4.2.2) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 23 ++++------------------- package.json | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3fb1a17604d..354929b94c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5549,13 +5549,13 @@ "dev": true }, "commitizen": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.1.tgz", - "integrity": "sha512-nZsp8IThkDu7C+93BFD/mLShb9Gd6Wsaf90tpKE3x/6u5y/Q52kzanIJpGr0qvIsJ5bCMpgKtr3Lbu3miEJfaA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.2.tgz", + "integrity": "sha512-uz+E6lGsDBDI2mYA4QfOxFeqdWUYwR1ky11YmLgg2BnEEP3YbeejpT4lxzGjkYqumnXr062qTOGavR9NtX/iwQ==", "dev": true, "requires": { "cachedir": "2.2.0", - "cz-conventional-changelog": "3.2.0", + "cz-conventional-changelog": "3.3.0", "dedent": "0.7.0", "detect-indent": "6.0.0", "find-node-modules": "2.0.0", @@ -5570,21 +5570,6 @@ "strip-json-comments": "3.0.1" }, "dependencies": { - "cz-conventional-changelog": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", - "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", - "dev": true, - "requires": { - "@commitlint/load": ">6.1.1", - "chalk": "^2.4.1", - "commitizen": "^4.0.3", - "conventional-commit-types": "^3.0.0", - "lodash.map": "^4.5.1", - "longest": "^2.0.1", - "word-wrap": "^1.0.3" - } - }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", diff --git a/package.json b/package.json index 758865f5c8f..5edc72aa693 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "chai": "^4.2.0", "clang-format": "1.4.0", "commander": "^6.1.0", - "commitizen": "^4.2.1", + "commitizen": "^4.2.2", "conventional-changelog-cli": "^2.1.0", "core-js": "^3.6.5", "cz-conventional-changelog": "^3.3.0", From 318f35a78c41a81d5a810362685927c6e0e08627 Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Tue, 20 Oct 2020 17:32:10 -0700 Subject: [PATCH 15/33] test: added new TableView/ListView tests --- tests/Resources/ti.media.videoplayer.test.js | 16 +-- tests/Resources/ti.ui.listview.test.js | 144 ++++++++++++------- tests/Resources/ti.ui.tableview.test.js | 93 ++++++++++++ 3 files changed, 188 insertions(+), 65 deletions(-) diff --git a/tests/Resources/ti.media.videoplayer.test.js b/tests/Resources/ti.media.videoplayer.test.js index 1876bc2bfe7..2681a8624ff 100644 --- a/tests/Resources/ti.media.videoplayer.test.js +++ b/tests/Resources/ti.media.videoplayer.test.js @@ -124,9 +124,7 @@ describe('Titanium.Media.VideoPlayer', function () { it.ios('playableDuration in milliseconds', function (finish) { const videoPlayer = Ti.Media.createVideoPlayer({ - // url: 'https://raw.githubusercontent.com/appcelerator/titanium_mobile/master/tests/remote/mov_bbb.mp4', - // FIXME: Use url above once this is merged to master? - url: 'https://raw.githubusercontent.com/appcelerator/titanium-mobile-mocha-suite/master/remote/mov_bbb.mp4', + url: 'https://raw.githubusercontent.com/appcelerator/titanium_mobile/master/tests/remote/mov_bbb.mp4', autoplay: true, showsControls: false, height: 200 @@ -173,15 +171,14 @@ describe('Titanium.Media.VideoPlayer', function () { should(player).have.readOnlyProperty('playbackState').which.is.a.Number(); }); - // FIXME: Skipping until TIMOB-26299 is fixed - it.allBroken('Close window containing a video player (TIMOB-25574)', function (finish) { + it('Close window containing a video player (TIMOB-25574)', function (finish) { var nav; this.timeout(15000); win = Ti.UI.createWindow({ backgroundColor: 'white' }); - nav = Ti.UI.iOS.createNavigationWindow({ + nav = Ti.UI.createNavigationWindow({ window: win }); @@ -198,7 +195,7 @@ describe('Titanium.Media.VideoPlayer', function () { }); videoPlayer = Ti.Media.createVideoPlayer({ - url: 'https://www.w3schools.com/html/mov_bbb.mp4', + url: 'https://raw.githubusercontent.com/appcelerator/titanium_mobile/master/tests/remote/mov_bbb.mp4', autoplay: true, backgroundColor: 'blue', height: 300, @@ -227,11 +224,10 @@ describe('Titanium.Media.VideoPlayer', function () { } }); - // FIXME: Skipping until TIMOB-26299 is fixed. - it.allBroken('Release video player and close window (TIMOB-26033)', function (finish) { + it('Release video player and close window (TIMOB-26033)', function (finish) { var videoWindow = Ti.UI.createWindow(); var videoPlayer = Ti.Media.createVideoPlayer({ - url: 'https://www.w3schools.com/html/mov_bbb.mp4', + url: 'https://raw.githubusercontent.com/appcelerator/titanium_mobile/master/tests/remote/mov_bbb.mp4', top: 2, autoplay: true, backgroundColor: 'blue', diff --git a/tests/Resources/ti.ui.listview.test.js b/tests/Resources/ti.ui.listview.test.js index 6ad4fe80b57..bb1a7875817 100644 --- a/tests/Resources/ti.ui.listview.test.js +++ b/tests/Resources/ti.ui.listview.test.js @@ -10,7 +10,7 @@ const should = require('./utilities/assertions'); describe('Titanium.UI.ListView', function () { - this.timeout(6e4); + this.timeout(5000); let win; afterEach(done => { // fires after every test in sub-suites too... @@ -551,9 +551,10 @@ describe('Titanium.UI.ListView', function () { win.open(); }); - // Since the tested API is iOS only, we will skip all other platforms - it.ios('ListItem.properties', function () { - var list = Ti.UI.createListView({ + describe('ListItem', function () { + // Since the tested API is iOS only, we will skip all other platforms + it.ios('properties', () => { + const listView = Ti.UI.createListView({ sections: [ Ti.UI.createListSection({ items: [ { template: Ti.UI.LIST_ITEM_TEMPLATE_CONTACTS, @@ -565,59 +566,92 @@ describe('Titanium.UI.ListView', function () { } } ] }) ] - }), - section, - items, - item, - template, - properties; + }); - win = Ti.UI.createWindow(); - win.add(list); - win.open(); + // Validate list and section + should(listView.apiName).be.eql('Ti.UI.ListView'); + const section = listView.sections[0]; + should(section.apiName).be.eql('Ti.UI.ListSection'); + + // Validate items + const items = section.items; + should(items).be.an.Array(); + should(items.length).be.a.Number(); + should(items.length).be.eql(1); + + // Validate single item + const item = items[0]; + const template = item.template; + const properties = item.properties; + + // Validate item template + should(item).have.ownProperty('template'); + should(template).not.be.undefined(); + should(template).be.a.Number(); + should(template).eql(Ti.UI.LIST_ITEM_TEMPLATE_CONTACTS); + + // Validate item properties + should(item).have.ownProperty('properties'); + should(properties).not.be.undefined(); + should(properties).be.an.Object(); + + // Validate properties subtitleColor and selectedSubtitleColor + should(properties).have.ownProperty('subtitleColor'); + should(properties.subtitleColor).be.a.String(); + should(properties.subtitleColor).be.eql('red'); + should(properties).have.ownProperty('selectedSubtitleColor'); + should(properties.selectedSubtitleColor).be.a.String(); + should(properties.selectedSubtitleColor).be.eql('green'); + + // Validate properties title & subtitle + should(properties).have.ownProperty('title'); + should(properties.title).be.a.String(); + should(properties.title).be.eql('My Title'); + should(properties).have.ownProperty('subtitle'); + should(properties.subtitle).be.a.String(); + should(properties.subtitle).be.eql('My Subtitle'); + }); - // Validate list and section - should(list.apiName).be.eql('Ti.UI.ListView'); - section = list.sections[0]; - should(section.apiName).be.eql('Ti.UI.ListSection'); - - // Validate items - items = section.items; - should(items).be.an.Array(); - should(items.length).be.a.Number(); - should(items.length).be.eql(1); - - // Validate single item - item = items[0]; - template = item.template; - properties = item.properties; - - // Validate item template - should(item).have.ownProperty('template'); - should(template).not.be.undefined(); - should(template).be.a.Number(); - should(template).eql(Ti.UI.LIST_ITEM_TEMPLATE_CONTACTS); - - // Validate item properties - should(item).have.ownProperty('properties'); - should(properties).not.be.undefined(); - should(properties).be.an.Object(); - - // Validate properties subtitleColor and selectedSubtitleColor - should(properties).have.ownProperty('subtitleColor'); - should(properties.subtitleColor).be.a.String(); - should(properties.subtitleColor).be.eql('red'); - should(properties).have.ownProperty('selectedSubtitleColor'); - should(properties.selectedSubtitleColor).be.a.String(); - should(properties.selectedSubtitleColor).be.eql('green'); - - // Validate properties title & subtitle - should(properties).have.ownProperty('title'); - should(properties.title).be.a.String(); - should(properties.title).be.eql('My Title'); - should(properties).have.ownProperty('subtitle'); - should(properties.subtitle).be.a.String(); - should(properties.subtitle).be.eql('My Subtitle'); + it('itemId', () => { + const listView = Ti.UI.createListView({ + sections: [ + Ti.UI.createListSection({ + items: [ + { properties: { title: 'Row 1', itemId: 'Foo' } }, + ] + }) + ] + }); + const section = listView.sections[0]; + const item = section.getItemAt(0); + should(item.properties.itemId).be.eql('Foo'); + item.properties.itemId = 'Bar'; + section.updateItemAt(0, item); + should(section.getItemAt(0).properties.itemId).be.eql('Bar'); + }); + + it('custom properties', () => { + const listView = Ti.UI.createListView({ + sections: [ + Ti.UI.createListSection({ + items: [ + { properties: { title: 'Row 1', myNumber: 1 } }, + ] + }) + ] + }); + const section = listView.sections[0]; + section.appendItems([ + { properties: { title: 'Row 2', myNumber: 2 } }, + ]); + should(section.getItemAt(0).properties.myNumber).be.eql(1); + should(section.getItemAt(1).properties.myNumber).be.eql(2); + + const item = section.getItemAt(0); + item.myString = 'my_string'; + section.updateItemAt(0, item); + should(section.getItemAt(0).myString).be.eql('my_string'); + }); }); // Crashes Windows 10 Desktop diff --git a/tests/Resources/ti.ui.tableview.test.js b/tests/Resources/ti.ui.tableview.test.js index 5aeb4b685eb..53f9b5dcf90 100644 --- a/tests/Resources/ti.ui.tableview.test.js +++ b/tests/Resources/ti.ui.tableview.test.js @@ -1197,6 +1197,26 @@ describe('Titanium.UI.TableView', function () { should(tableView.scrollable).be.be.true(); }); + it('refreshControl', (finish) => { + const refreshControl = Ti.UI.createRefreshControl(); + refreshControl.addEventListener('refreshstart', () => { + setTimeout(() => { + refreshControl.endRefreshing(); + }, 1000); + }); + refreshControl.addEventListener('refreshend', () => { + finish(); + }); + win = Ti.UI.createWindow(); + win.add(Ti.UI.createListView({ + refreshControl: refreshControl + })); + win.addEventListener('open', function () { + refreshControl.beginRefreshing(); + }); + win.open(); + }); + // FIXME Windows throws exception it.windowsBroken('Add and remove headerView/footerView ', function (finish) { win = Ti.UI.createWindow({ backgroundColor: 'gray' }); @@ -1356,6 +1376,79 @@ describe('Titanium.UI.TableView', function () { win.open(); }); + it('row - custom properties', () => { + const tableView = Ti.UI.createTableView({ + data: [ + Ti.UI.createTableViewRow({ title: 'Row 1', myNumber: 1 }), + { title: 'Row 2', myNumber: 2 } + ] + }); + tableView.appendRow(Ti.UI.createTableViewRow({ title: 'Row 3', myNumber: 3 })); + const sectionRows = tableView.sections[0].rows; + should(sectionRows[0].myNumber).be.eql(1); + should(sectionRows[1].myNumber).be.eql(2); + should(sectionRows[2].myNumber).be.eql(3); + + const row = sectionRows[0]; + row.myNumber = 10; + tableView.updateRow(0, row); + should(tableView.sections[0].rows[0].myNumber).be.eql(10); + }); + + it.androidBroken('row#getViewById()', (finish) => { + const section1 = Ti.UI.createTableViewSection({ headerTitle: 'My Section' }); + for (let index = 1; index <= 3; index++) { + const row = Ti.UI.createTableViewRow(); + row.add(Ti.UI.createLabel({ text: `Row ${index}`, id: 'myLabelId' })); + section1.add(row); + } + const tableView = Ti.UI.createTableView({ + data: [ section1 ] + }); + win = Ti.UI.createWindow(); + win.add(tableView); + win.addEventListener('open', () => { + try { + for (let index = 1; index <= 3; index++) { + const row = tableView.sections[0].rows[index - 1]; + const view = row.getViewById('myLabelId'); + should(view).be.a.Object(); + should(view.apiName).be.eql('Ti.UI.Label'); + should(view.text).be.eql(`Row ${index}`); + } + finish(); + } catch (err) { + finish(err); + } + }); + win.open(); + }); + + // Exercise TableViewRow "className" template handling. + it('row.className', (finish) => { + const section1 = Ti.UI.createTableViewSection({ headerTitle: 'Section 1' }); + for (let index = 1; index <= 3; index++) { + const row = Ti.UI.createTableViewRow({ className: 'rowType1' }); + row.add(Ti.UI.createLabel({ text: `Row ${index}`, left: 20 })); + section1.add(row); + } + const section2 = Ti.UI.createTableViewSection({ headerTitle: 'Section 2' }); + for (let index = 1; index <= 3; index++) { + const row = Ti.UI.createTableViewRow({ className: 'rowType2' }); + row.add(Ti.UI.createLabel({ text: `Row ${index}`, right: 20 })); + section1.add(row); + } + + win = Ti.UI.createWindow(); + win.add(Ti.UI.createTableView({ + data: [ section1, section2 ] + })); + win.addEventListener('open', () => { + finish(); + }); + win.open(); + }); + it.iosBroken('resize row with Ti.UI.SIZE on content height change', function (finish) { var heights = [ 100, 200, 50 ]; var tableView = Ti.UI.createTableView({}); From 149eb4a2bad451630651c46dc60504652394b8a3 Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Wed, 21 Oct 2020 07:32:43 -0700 Subject: [PATCH 16/33] fix(ios): TableView "sectionCount" property crash (#12193) --- iphone/Classes/TiUITableView.m | 9 +++++---- iphone/Classes/TiUITableViewProxy.h | 2 +- iphone/Classes/TiUITableViewProxy.m | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/iphone/Classes/TiUITableView.m b/iphone/Classes/TiUITableView.m index f4df5126150..0dbfb8d1e9f 100644 --- a/iphone/Classes/TiUITableView.m +++ b/iphone/Classes/TiUITableView.m @@ -555,7 +555,7 @@ - (void)replaceData:(NSMutableArray *)data animation:(UITableViewRowAnimation)an //won't have any problems in the case that it is actually nil. TiUITableViewProxy *ourProxy = (TiUITableViewProxy *)[self proxy]; - NSUInteger oldCount = [ourProxy sectionCount]; + NSUInteger oldCount = ourProxy.sectionCount.unsignedIntegerValue; for (TiUITableViewSectionProxy *section in [(TiUITableViewProxy *)[self proxy] internalSections]) { if ([section parent] == ourProxy) { @@ -1313,7 +1313,8 @@ - (void)updateSearchResultIndexes } NSEnumerator *searchResultIndexEnumerator; if (searchResultIndexes == nil) { - searchResultIndexes = [[NSMutableArray alloc] initWithCapacity:[(TiUITableViewProxy *)[self proxy] sectionCount]]; + NSUInteger sectionCount = [(TiUITableViewProxy *)[self proxy] sectionCount].unsignedIntegerValue; + searchResultIndexes = [[NSMutableArray alloc] initWithCapacity:sectionCount]; searchResultIndexEnumerator = nil; } else { searchResultIndexEnumerator = [searchResultIndexes objectEnumerator]; @@ -2124,7 +2125,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)ourTableView return 1; } // One quirk of UITableView is that it really hates having 0 sections. Instead, supply 1 section, no rows. - NSUInteger result = [(TiUITableViewProxy *)[self proxy] sectionCount]; + NSUInteger result = [(TiUITableViewProxy *)[self proxy] sectionCount].unsignedIntegerValue; return MAX(1, result); } @@ -2166,7 +2167,7 @@ - (void)tableView:(UITableView *)ourTableView commitEditingStyle:(UITableViewCel [table beginUpdates]; if (emptySection) { NSIndexSet *thisSectionSet = [NSIndexSet indexSetWithIndex:[indexPath section]]; - if ([(TiUITableViewProxy *)[self proxy] sectionCount] > 0) { + if ([(TiUITableViewProxy *)[self proxy] sectionCount].unsignedIntegerValue > 0) { [table deleteSections:thisSectionSet withRowAnimation:UITableViewRowAnimationFade]; } else //There always must be at least one section. So instead, we have it reload to clear out the header and footer, etc. { diff --git a/iphone/Classes/TiUITableViewProxy.h b/iphone/Classes/TiUITableViewProxy.h index 21b77d0df35..268425acd48 100644 --- a/iphone/Classes/TiUITableViewProxy.h +++ b/iphone/Classes/TiUITableViewProxy.h @@ -21,7 +21,7 @@ - (NSArray *)data; //Sections and Data are the sanitized version. @property (nonatomic, readwrite, copy) NSArray *sections; -- (NSUInteger)sectionCount; +- (NSNumber *)sectionCount; #pragma mark NON-JS functionality //internalSections is until TODO: Stop JS from using ValueForKey diff --git a/iphone/Classes/TiUITableViewProxy.m b/iphone/Classes/TiUITableViewProxy.m index 0df9909536b..f9b703e1286 100644 --- a/iphone/Classes/TiUITableViewProxy.m +++ b/iphone/Classes/TiUITableViewProxy.m @@ -882,9 +882,9 @@ - (void)willShow [(TiUITableView *)[self view] refreshSearchControllerUsingReload:YES]; } -- (NSUInteger)sectionCount +- (NSNumber *)sectionCount { //TODO: Shouldn't this be in the main thread, too? - return [sections count]; + return NUMUINTEGER((sections != nil) ? sections.count : 0); } - (TiUITableViewSectionProxy *)tableSectionFromArg:(id)arg From c3783d38e63e00dcae23bd40ed65660e89d75423 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 13:32:01 +0000 Subject: [PATCH 17/33] build(deps-dev): bump rollup from 2.32.0 to 2.32.1 Bumps [rollup](https://github.com/rollup/rollup) from 2.32.0 to 2.32.1. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.32.0...v2.32.1) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 354929b94c4..132f5bf15a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13530,9 +13530,9 @@ } }, "rollup": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.0.tgz", - "integrity": "sha512-0FIG1jY88uhCP2yP4CfvtKEqPDRmsUwfY1kEOOM+DH/KOGATgaIFd/is1+fQOxsvh62ELzcFfKonwKWnHhrqmw==", + "version": "2.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz", + "integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==", "dev": true, "requires": { "fsevents": "~2.1.2" diff --git a/package.json b/package.json index 5edc72aa693..94593743a1f 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "request-promise-native": "^1.0.9", - "rollup": "^2.32.0", + "rollup": "^2.32.1", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", From 6403da2453bceed654e7bb5a8c9cb43af51427ae Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Mon, 12 Oct 2020 18:58:41 -0700 Subject: [PATCH 18/33] fix(android): tabgroup crashes when using AppCompat theme Fixes TIMOB-28189 --- .../TiUIBottomNavigationTabGroup.java | 11 +++++++--- .../tabgroup/TiUITabLayoutTabGroup.java | 11 +++++++--- .../titanium/util/TiUIHelper.java | 20 +++++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUIBottomNavigationTabGroup.java b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUIBottomNavigationTabGroup.java index 327d444f8c0..5788da5e448 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUIBottomNavigationTabGroup.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUIBottomNavigationTabGroup.java @@ -292,11 +292,16 @@ public void updateBadge(int index) return; } + Object badgeValue = tabProxy.getProperty(TiC.PROPERTY_BADGE); + if ((badgeValue == null) && !TiUIHelper.isUsingMaterialTheme(this.mBottomNavigationView.getContext())) { + return; + } + int menuItemId = this.mBottomNavigationView.getMenu().getItem(index).getItemId(); BadgeDrawable badgeDrawable = this.mBottomNavigationView.getOrCreateBadge(menuItemId); - if (tabProxy.getProperty(TiC.PROPERTY_BADGE) != null) { + if (badgeValue != null) { badgeDrawable.setVisible(true); - badgeDrawable.setNumber(TiConvert.toInt(tabProxy.getProperty(TiC.PROPERTY_BADGE), 0)); + badgeDrawable.setNumber(TiConvert.toInt(badgeValue, 0)); } else { badgeDrawable.setVisible(false); } @@ -314,8 +319,8 @@ public void updateBadgeColor(int index) return; } - int menuItemId = this.mBottomNavigationView.getMenu().getItem(index).getItemId(); if (tabProxy.getProperty(TiC.PROPERTY_BADGE_COLOR) != null) { + int menuItemId = this.mBottomNavigationView.getMenu().getItem(index).getItemId(); BadgeDrawable badgeDrawable = this.mBottomNavigationView.getOrCreateBadge(menuItemId); badgeDrawable.setBackgroundColor( TiConvert.toColor((String) tabProxy.getProperty(TiC.PROPERTY_BADGE_COLOR))); diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUITabLayoutTabGroup.java b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUITabLayoutTabGroup.java index 5985bb7e16a..17e261e8ccf 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUITabLayoutTabGroup.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/tabgroup/TiUITabLayoutTabGroup.java @@ -279,10 +279,15 @@ public void updateBadge(int index) return; } + Object badgeValue = tabProxy.getProperty(TiC.PROPERTY_BADGE); + if ((badgeValue == null) && !TiUIHelper.isUsingMaterialTheme(this.mTabLayout.getContext())) { + return; + } + BadgeDrawable badgeDrawable = this.mTabLayout.getTabAt(index).getOrCreateBadge(); - if (tabProxy.getProperty(TiC.PROPERTY_BADGE) != null) { + if (badgeValue != null) { badgeDrawable.setVisible(true); - badgeDrawable.setNumber(TiConvert.toInt(tabProxy.getProperty(TiC.PROPERTY_BADGE), 0)); + badgeDrawable.setNumber(TiConvert.toInt(badgeValue, 0)); } else { badgeDrawable.setVisible(false); } @@ -300,8 +305,8 @@ public void updateBadgeColor(int index) return; } - BadgeDrawable badgeDrawable = this.mTabLayout.getTabAt(index).getOrCreateBadge(); if (tabProxy.getProperty(TiC.PROPERTY_BADGE_COLOR) != null) { + BadgeDrawable badgeDrawable = this.mTabLayout.getTabAt(index).getOrCreateBadge(); badgeDrawable.setVisible(true); badgeDrawable.setBackgroundColor( TiConvert.toColor((String) tabProxy.getProperty(TiC.PROPERTY_BADGE_COLOR))); diff --git a/android/titanium/src/java/org/appcelerator/titanium/util/TiUIHelper.java b/android/titanium/src/java/org/appcelerator/titanium/util/TiUIHelper.java index 8cf3436cdc4..c5163e2742a 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/util/TiUIHelper.java +++ b/android/titanium/src/java/org/appcelerator/titanium/util/TiUIHelper.java @@ -49,6 +49,7 @@ import android.content.DialogInterface.OnClickListener; import android.content.res.AssetManager; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; @@ -1288,6 +1289,25 @@ public static String getBackgroundColorForState(TiBackgroundDrawable backgroundD return null; } + /** + * Determines if the given context has been assigned a "Theme.MaterialComponents" derived theme. + * @param context Reference to the context such as an Activity or Application object to inspect. Can be null. + * @return Returns true if assigned a material theme. Returns false if not or argument is null. + */ + public static boolean isUsingMaterialTheme(Context context) + { + if (context == null) { + return false; + } + + TypedArray typedArray = context.obtainStyledAttributes(new int[] { + com.google.android.material.R.attr.colorPrimaryVariant + }); + boolean isMaterial = typedArray.hasValue(0); + typedArray.recycle(); + return isMaterial; + } + public static String hexStringFrom(int colorInt) { return String.format("#%08X", 0xFFFFFFFF & colorInt); From 6417307a273cab6370e0153af1583682db734ba7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2020 10:25:44 +0000 Subject: [PATCH 19/33] build(deps): bump ioslib from 1.7.21 to 1.7.22 Bumps [ioslib](https://github.com/appcelerator/ioslib) from 1.7.21 to 1.7.22. - [Release notes](https://github.com/appcelerator/ioslib/releases) - [Changelog](https://github.com/appcelerator/ioslib/blob/master/CHANGELOG.md) - [Commits](https://github.com/appcelerator/ioslib/compare/1.7.21...1.7.22) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 120 +++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 45 insertions(+), 77 deletions(-) diff --git a/package-lock.json b/package-lock.json index 132f5bf15a1..59c375d681e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8716,9 +8716,9 @@ "dev": true }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -8877,16 +8877,16 @@ } }, "ioslib": { - "version": "1.7.21", - "resolved": "https://registry.npmjs.org/ioslib/-/ioslib-1.7.21.tgz", - "integrity": "sha512-dvAdpIYSJy1ILPfBwBCe3YJpu2jrL8hc0gdNIUNrEuz73b6IYZLXw2ThocRsZVTl/Px+RVbdqHsBLVujRcUDYg==", + "version": "1.7.22", + "resolved": "https://registry.npmjs.org/ioslib/-/ioslib-1.7.22.tgz", + "integrity": "sha512-uDceJ2/nHtnboHC0pttfMJUBwEkUj+xylLYiE98R3O7P0J3v6PF+kBFXf9/PQZO3FZGUygnWuGFAwIZKuwBKhw==", "requires": { "always-tail": "0.2.0", "async": "^2.6.3", "bplist-parser": "0.1.1", - "debug": "^3.2.6", + "debug": "^4.2.0", "mkdirp": "0.5.1", - "node-appc": "^0.3.4", + "node-appc": "^1.1.2", "node-ios-device": "^1.7.0" }, "dependencies": { @@ -8898,27 +8898,12 @@ "lodash": "^4.17.14" } }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "ms": "2.1.2" } }, "mkdirp": { @@ -8933,36 +8918,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node-appc": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/node-appc/-/node-appc-0.3.4.tgz", - "integrity": "sha512-DFJCttcjDmbKS/Z2oPHugp+MjfZ/dsT25dLf2gXzujPOH+zAWOH03079dokon0/hp0zbZu3ksFmrx+JIWtV97Q==", - "requires": { - "adm-zip": "^0.4.11", - "async": "~2.6.1", - "colors": "~1.3.0", - "diff": "~3.5.0", - "fs-extra": "~7.0.0", - "optimist": "^0.6.1", - "request": "~2.88.0", - "semver": "~6.0.0", - "sprintf": "^0.1.5", - "temp": "~0.9.0", - "uglify-js": "~3.4.0", - "uuid": "~3.3.2", - "xmldom": "^0.1.27" - } - }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" - }, - "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" } } }, @@ -11196,9 +11151,9 @@ "dev": true }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "nanoid": { "version": "3.1.12", @@ -11259,9 +11214,9 @@ "dev": true }, "needle": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz", - "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -11332,13 +11287,13 @@ "dev": true }, "node-ios-device": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/node-ios-device/-/node-ios-device-1.7.1.tgz", - "integrity": "sha512-U2ua4NDazOvVMx2SMiiNyhwXcxRo1XS279Q2v2lRwvKgGz91mvjX98U1EU7LmIQnWtZCtofX7LHrWVJnBpXCVg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-ios-device/-/node-ios-device-1.8.0.tgz", + "integrity": "sha512-khSLL2Ar9sjRMzMxzuRM3XUAQXB6gMlsL8QuRjODzbfDZoutMLfOk8+VO5gVfQo+t9RrhyDjxwKQfQvhfSy4hw==", "requires": { "debug": "^4.1.1", - "nan": "^2.14.0", - "node-pre-gyp": "^0.14.0", + "nan": "^2.14.2", + "node-pre-gyp": "^0.15.0", "node-pre-gyp-init": "^1.1.0" }, "dependencies": { @@ -11395,11 +11350,11 @@ "bundled": true }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "deep-extend": { @@ -11544,7 +11499,7 @@ "bundled": true }, "needle": { - "version": "2.4.0", + "version": "2.5.2", "bundled": true, "requires": { "debug": "^3.2.6", @@ -11562,12 +11517,12 @@ } }, "node-pre-gyp": { - "version": "0.14.0", + "version": "0.15.0", "bundled": true, "requires": { "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", + "mkdirp": "^0.5.3", + "needle": "^2.5.0", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", @@ -11575,6 +11530,19 @@ "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4.4.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "bundled": true + }, + "mkdirp": { + "version": "0.5.5", + "bundled": true, + "requires": { + "minimist": "^1.2.5" + } + } } }, "nopt": { diff --git a/package.json b/package.json index 94593743a1f..09d8b77c245 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "ejs": "^3.1.5", "fields": "0.1.24", "fs-extra": "^9.0.1", - "ioslib": "^1.7.21", + "ioslib": "^1.7.22", "liveview": "^1.5.4", "lodash.merge": "^4.6.2", "markdown": "0.5.0", From c91972d68e41d24e25efd31f714b53d6e82a2e03 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2020 10:47:12 +0000 Subject: [PATCH 20/33] build(deps-dev): bump titanium-docgen from 4.8.2 to 4.8.3 Bumps [titanium-docgen](https://github.com/appcelerator/docs-devkit/tree/HEAD/packages/titanium-docgen) from 4.8.2 to 4.8.3. - [Release notes](https://github.com/appcelerator/docs-devkit/releases) - [Changelog](https://github.com/appcelerator/docs-devkit/blob/develop/packages/titanium-docgen/CHANGELOG.md) - [Commits](https://github.com/appcelerator/docs-devkit/commits/v4.8.3/packages/titanium-docgen) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 71 +++-------------------------------------------- package.json | 2 +- 2 files changed, 5 insertions(+), 68 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59c375d681e..720d86785b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14674,79 +14674,16 @@ } }, "titanium-docgen": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/titanium-docgen/-/titanium-docgen-4.8.2.tgz", - "integrity": "sha512-/gdk894JbEwsMf+c1k0fkITuAIKgihYRU2A2BqLaPVpty5rnnJXgYv/4HovOK4XeBA8O/ELtUCUH/QGHtgYrGw==", + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/titanium-docgen/-/titanium-docgen-4.8.3.tgz", + "integrity": "sha512-6P1MP+C0cMFmItmIzVFzKCxaCsj8bIj0zZ/31Ex1+W1lfB4icEuPY9ywJUMCME5TEFxH5Cd15i+/W0kd53Ltgw==", "dev": true, "requires": { "colors": "^1.4.0", "ejs": "^3.0.1", "js-yaml": "^3.13.1", "markdown-it": "^12.0.0", - "node-appc": "^0.3.4" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node-appc": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/node-appc/-/node-appc-0.3.4.tgz", - "integrity": "sha512-DFJCttcjDmbKS/Z2oPHugp+MjfZ/dsT25dLf2gXzujPOH+zAWOH03079dokon0/hp0zbZu3ksFmrx+JIWtV97Q==", - "dev": true, - "requires": { - "adm-zip": "^0.4.11", - "async": "~2.6.1", - "colors": "~1.3.0", - "diff": "~3.5.0", - "fs-extra": "~7.0.0", - "optimist": "^0.6.1", - "request": "~2.88.0", - "semver": "~6.0.0", - "sprintf": "^0.1.5", - "temp": "~0.9.0", - "uglify-js": "~3.4.0", - "uuid": "~3.3.2", - "xmldom": "^0.1.27" - }, - "dependencies": { - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - } - } - }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", - "dev": true - }, - "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", - "dev": true - } + "node-appc": "^1.1.2" } }, "tmp": { diff --git a/package.json b/package.json index 09d8b77c245..4f51418ed8c 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "stream-splitter": "^0.3.2", "strip-ansi": "^6.0.0", "titanium": "^5.2.5", - "titanium-docgen": "^4.8.2" + "titanium-docgen": "^4.8.3" }, "repository": { "type": "git", From 08a48534bd0653ba6135b8c08edf13e09002634a Mon Sep 17 00:00:00 2001 From: Jan Vennemann Date: Thu, 22 Oct 2020 20:16:54 +0200 Subject: [PATCH 21/33] fix(angular): declare missing nodejs namespace for zone.js (#12199) Fixes TIMOB-28200 --- templates/app/angular-default/template/tsconfig.json | 6 +++++- .../app/angular-default/template/typings/node/index.d.ts | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 templates/app/angular-default/template/typings/node/index.d.ts diff --git a/templates/app/angular-default/template/tsconfig.json b/templates/app/angular-default/template/tsconfig.json index 73ed0410cc3..2d2d6049efa 100644 --- a/templates/app/angular-default/template/tsconfig.json +++ b/templates/app/angular-default/template/tsconfig.json @@ -14,7 +14,11 @@ "es2018", "dom" ], - "preserveSymlinks": true + "preserveSymlinks": true, + "typeRoots": [ + "typings", + "node_modules/@types" + ] }, "files": [ "src/main.ts", diff --git a/templates/app/angular-default/template/typings/node/index.d.ts b/templates/app/angular-default/template/typings/node/index.d.ts new file mode 100644 index 00000000000..8a248144aec --- /dev/null +++ b/templates/app/angular-default/template/typings/node/index.d.ts @@ -0,0 +1,5 @@ +// Alias NodeJS.Global definition to make zone.js typings happy +// including @types/node clashes with @types/titanium +declare namespace NodeJS { + type Global = Titanium.Global +} From af6ca305b006ff5947bd7143ab8b7e5750dd5ff2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Oct 2020 10:25:48 +0000 Subject: [PATCH 22/33] build(deps): bump ioslib from 1.7.22 to 1.7.23 Bumps [ioslib](https://github.com/appcelerator/ioslib) from 1.7.22 to 1.7.23. - [Release notes](https://github.com/appcelerator/ioslib/releases) - [Changelog](https://github.com/appcelerator/ioslib/blob/master/CHANGELOG.md) - [Commits](https://github.com/appcelerator/ioslib/compare/1.7.22...1.7.23) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 720d86785b4..86568b2b77d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8877,9 +8877,9 @@ } }, "ioslib": { - "version": "1.7.22", - "resolved": "https://registry.npmjs.org/ioslib/-/ioslib-1.7.22.tgz", - "integrity": "sha512-uDceJ2/nHtnboHC0pttfMJUBwEkUj+xylLYiE98R3O7P0J3v6PF+kBFXf9/PQZO3FZGUygnWuGFAwIZKuwBKhw==", + "version": "1.7.23", + "resolved": "https://registry.npmjs.org/ioslib/-/ioslib-1.7.23.tgz", + "integrity": "sha512-j7Gd1+SzgUkexEyRvfqsshRZdjxrtkY+4qdbr8MT3XPrfK5DoVGcJKGjeqKWPZlI9E4IkbhEJ64+ZBx42P8ArQ==", "requires": { "always-tail": "0.2.0", "async": "^2.6.3", diff --git a/package.json b/package.json index 4f51418ed8c..39fc4c8e09c 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "ejs": "^3.1.5", "fields": "0.1.24", "fs-extra": "^9.0.1", - "ioslib": "^1.7.22", + "ioslib": "^1.7.23", "liveview": "^1.5.4", "lodash.merge": "^4.6.2", "markdown": "0.5.0", From a76dd05e0a12a190f44f1ceb18589439715888e2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Oct 2020 10:55:36 +0000 Subject: [PATCH 23/33] build(deps-dev): bump titanium from 5.2.5 to 5.3.0 Bumps [titanium](https://github.com/appcelerator/titanium) from 5.2.5 to 5.3.0. - [Release notes](https://github.com/appcelerator/titanium/releases) - [Changelog](https://github.com/appcelerator/titanium/blob/master/CHANGELOG.md) - [Commits](https://github.com/appcelerator/titanium/compare/5.2.5...5.3.0) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 156 ++++------------------------------------------ package.json | 2 +- 2 files changed, 12 insertions(+), 146 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86568b2b77d..6609dae9fbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12853,12 +12853,6 @@ "find-up": "^2.1.0" } }, - "pkginfo": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", - "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", - "dev": true - }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -14518,30 +14512,23 @@ } }, "titanium": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/titanium/-/titanium-5.2.5.tgz", - "integrity": "sha512-P2+0coxeYre+1Lf/k2t61W1UwcNhupQy5s5UcpDkbGiRg7EDoYVnkix1H08yg+mfKh14Jm9+6QDDKpEWM+arZQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/titanium/-/titanium-5.3.0.tgz", + "integrity": "sha512-j+Bk1jWH4Ki/7hfizhG6MvaZMEeHNdaJnzjC50CUJThfDkxr8nN1rn7smaX9Wg5W1iiBeBQyJreTExZloTRCJw==", "dev": true, "requires": { - "adm-zip": "0.4.13", "async": "^2.6.3", - "colors": "1.3.3", + "colors": "1.4.0", "fields": "0.1.24", "humanize": "0.0.9", - "moment": "^2.24.0", "node-appc": "^1.1.1", - "request": "2.88.0", + "request": "2.88.2", "sprintf": "0.1.5", - "temp": "0.9.0", - "winston": "1.1.2" + "temp": "0.9.1", + "winston": "2.4.5", + "yauzl": "^2.10.0" }, "dependencies": { - "adm-zip": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", - "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", - "dev": true - }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -14550,126 +14537,6 @@ "requires": { "lodash": "^4.17.14" } - }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "node-appc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-appc/-/node-appc-1.1.1.tgz", - "integrity": "sha512-QYOmRUq9B0LfVZ5MWQlbv8tHa4pzQ+YbagjUUvMIx6lVjhCjG9pPMRyPFK7/HXiQ+WrsiuydSbJgsBZt1p18Rg==", - "dev": true, - "requires": { - "async": "^3.2.0", - "colors": "~1.4.0", - "fs-extra": "~9.0.0", - "request": "~2.88.0", - "semver": "~7.3.2", - "sprintf": "^0.1.5", - "temp": "~0.9.0", - "uuid": "~8.3.0", - "xmldom": "^0.3.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - } - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "temp": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.0.tgz", - "integrity": "sha512-YfUhPQCJoNQE5N+FJQcdPz63O3x3sdT4Xju69Gj4iZe0lBKOtnAMi0SLj9xKhGkcGhsxThvTJ/usxtFPo438zQ==", - "dev": true, - "requires": { - "rimraf": "~2.6.2" - } - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", - "dev": true } } }, @@ -15159,9 +15026,9 @@ } }, "winston": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-1.1.2.tgz", - "integrity": "sha1-aO3Xaf951PlSjPDl2AAhqt5nSAw=", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz", + "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==", "dev": true, "requires": { "async": "~1.0.0", @@ -15169,7 +15036,6 @@ "cycle": "1.0.x", "eyes": "0.1.x", "isstream": "0.1.x", - "pkginfo": "0.3.x", "stack-trace": "0.0.x" }, "dependencies": { diff --git a/package.json b/package.json index 39fc4c8e09c..050402fefb5 100644 --- a/package.json +++ b/package.json @@ -155,7 +155,7 @@ "ssri": "^8.0.0", "stream-splitter": "^0.3.2", "strip-ansi": "^6.0.0", - "titanium": "^5.2.5", + "titanium": "^5.3.0", "titanium-docgen": "^4.8.3" }, "repository": { From 01267723b9acc6ad665451f84d5fc50413e96d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Fri, 23 Oct 2020 17:10:54 +0200 Subject: [PATCH 24/33] fix(ios): fix 'dateTimeColor' for iOS 14+ (#12167) Fixes TIMOB-28181 --- apidoc/Titanium/UI/Picker.yml | 3 +++ iphone/Classes/TiUIPicker.m | 14 +++++++++- tests/Resources/ti.ui.picker.test.js | 39 ++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/apidoc/Titanium/UI/Picker.yml b/apidoc/Titanium/UI/Picker.yml index 0882ec7e4fb..883b06de261 100644 --- a/apidoc/Titanium/UI/Picker.yml +++ b/apidoc/Titanium/UI/Picker.yml @@ -252,6 +252,9 @@ properties: Applicable to and picker types. The picker type does not support text customizing as stated in the [UIKit User Interface Catalog](https://developer.apple.com/documentation/uikit/uidatepicker). + + Important: On iOS 14+, you also have to set the to + in order to use this property. type: [String, Titanium.UI.Color] platforms: [iphone, ipad, macos] since: "5.2.0" diff --git a/iphone/Classes/TiUIPicker.m b/iphone/Classes/TiUIPicker.m index 3d06b5a00a5..66c399259e9 100644 --- a/iphone/Classes/TiUIPicker.m +++ b/iphone/Classes/TiUIPicker.m @@ -232,7 +232,19 @@ - (void)setBackgroundColor_:(id)value - (void)setDateTimeColor_:(id)value { - [[self proxy] replaceValue:value forKey:@"dateTimeColor" notification:NO]; + // Guard date picker and iOS 14+ date picker style + if (![self isDatePicker]) { + return; + } +#if IS_SDK_IOS_13_4 + if (((UIDatePicker *)[self picker]).preferredDatePickerStyle != UIDatePickerStyleWheels) { + return; + } +#endif + + [[self proxy] replaceValue:value + forKey:@"dateTimeColor" + notification:NO]; if (picker != nil) { [(UIDatePicker *)[self picker] setValue:[[TiUtils colorValue:value] _color] forKeyPath:@"textColor"]; diff --git a/tests/Resources/ti.ui.picker.test.js b/tests/Resources/ti.ui.picker.test.js index 4f8646fca07..0a9fdfd3f77 100644 --- a/tests/Resources/ti.ui.picker.test.js +++ b/tests/Resources/ti.ui.picker.test.js @@ -300,6 +300,45 @@ describe('Titanium.UI.Picker', function () { win.open(); }); + it('DatePicker dateTimeColor (invalid "type" - TIMOB-28181)', function (finish) { + const dp = Ti.UI.createPicker({ + type: Ti.UI.PICKER_TYPE_PLAIN, + dateTimeColor: 'red' + }); + + win = Ti.UI.createWindow(); + win.addEventListener('open', function () { + try { + should(dp.dateTimeColor).be.eql('red'); + finish(); + } catch (err) { + return finish(err); + } + }); + win.add(dp); + win.open(); + }); + + it('DatePicker dateTimeColor (valid "type" + "datePickerStyle" - TIMOB-28181)', function (finish) { + const dp = Ti.UI.createPicker({ + type: Ti.UI.PICKER_TYPE_DATE, + datePickerStyle: Ti.UI.iOS.DATE_PICKER_STYLE_WHEELS, + dateTimeColor: 'red' + }); + + win = Ti.UI.createWindow(); + win.addEventListener('open', function () { + try { + should(dp.dateTimeColor).be.eql('red'); + finish(); + } catch (err) { + return finish(err); + } + }); + win.add(dp); + win.open(); + }); + it('DatePicker postlayout event', function (finish) { const dp = Ti.UI.createPicker({ type: Ti.UI.PICKER_TYPE_DATE From b3ca93516b64f25ce2d63a86d3c47bffc21ee27e Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Fri, 23 Oct 2020 12:54:39 -0400 Subject: [PATCH 25/33] test: fix ti.filesystem test on ios device, clean up --- tests/Resources/ti.filesystem.test.js | 183 ++++++++++++++++---------- 1 file changed, 110 insertions(+), 73 deletions(-) diff --git a/tests/Resources/ti.filesystem.test.js b/tests/Resources/ti.filesystem.test.js index d4330b629de..6e2cb539a28 100644 --- a/tests/Resources/ti.filesystem.test.js +++ b/tests/Resources/ti.filesystem.test.js @@ -4,6 +4,7 @@ * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ +/* global OS_IOS */ /* eslint-env mocha */ /* eslint no-unused-expressions: "off" */ 'use strict'; @@ -11,55 +12,55 @@ const should = require('./utilities/assertions'); const utilities = require('./utilities/utilities'); describe('Titanium.Filesystem', () => { - it('apiName', () => { + it('.apiName', () => { should(Ti.Filesystem).have.readOnlyProperty('apiName').which.is.a.String(); should(Ti.Filesystem.apiName).be.eql('Ti.Filesystem'); }); - it('MODE_APPEND', () => { + it('.MODE_APPEND', () => { should(Ti.Filesystem).have.constant('MODE_APPEND').which.is.a.Number(); }); - it('MODE_READ', () => { + it('.MODE_READ', () => { should(Ti.Filesystem).have.constant('MODE_READ').which.is.a.Number(); }); - it('MODE_WRITE', () => { + it('.MODE_WRITE', () => { should(Ti.Filesystem).have.constant('MODE_WRITE').which.is.a.Number(); }); // Android doesn't support Ti.Filesystem.applicationDirectory - it.androidMissing('applicationDirectory', () => { + it.androidMissing('.applicationDirectory', () => { should(Ti.Filesystem).have.readOnlyProperty('applicationDirectory').which.is.a.String(); }); - it('applicationDataDirectory', () => { + it('.applicationDataDirectory', () => { should(Ti.Filesystem).have.readOnlyProperty('applicationDataDirectory').which.is.a.String(); }); - it('resourcesDirectory', () => { + it('.resourcesDirectory', () => { should(Ti.Filesystem).have.readOnlyProperty('resourcesDirectory').which.is.a.String(); }); - it.android('resRawDirectory', () => { + it.android('.resRawDirectory', () => { should(Ti.Filesystem).have.readOnlyProperty('resRawDirectory').which.is.a.String(); }); // On Windows Runtime, applicationSupportDirectory may return null if app doesn't have permission // although it should not throw exception - it.androidMissing('applicationSupportDirectory', () => { + it.androidMissing('.applicationSupportDirectory', () => { should(Ti.Filesystem.applicationSupportDirectory).not.be.undefined(); should(Ti.Filesystem).have.a.readOnlyProperty('applicationSupportDirectory').which.is.a.String(); }); // On Windows Runtime, externalStorageDirectory may return null if app doesn't have permission // although it should not throw exception - it.iosMissing('externalStorageDirectory', () => { + it.iosMissing('.externalStorageDirectory', () => { should(Ti.Filesystem.externalStorageDirectory).not.be.undefined(); should(Ti.Filesystem).have.a.readOnlyProperty('externalStorageDirectory').which.is.a.String(); }); - it('applicationCacheDirectory', () => { + it('.applicationCacheDirectory', () => { // Windows Store app doesn't support cache directory if (utilities.isWindowsDesktop()) { should(Ti.Filesystem.applicationCacheDirectory).be.undefined(); @@ -68,11 +69,11 @@ describe('Titanium.Filesystem', () => { } }); - it('tempDirectory', () => { + it('.tempDirectory', () => { should(Ti.Filesystem).have.readOnlyProperty('tempDirectory').which.is.a.String(); }); - it('separator', () => { + it('.separator', () => { should(Ti.Filesystem).have.a.readOnlyProperty('separator').which.is.a.String(); if (utilities.isWindows()) { should(Ti.Filesystem.separator).be.eql('\\'); @@ -81,7 +82,7 @@ describe('Titanium.Filesystem', () => { } }); - it('lineEnding', () => { + it('.lineEnding', () => { should(Ti.Filesystem).have.a.readOnlyProperty('lineEnding').which.is.a.String(); if (utilities.isWindows()) { should(Ti.Filesystem.lineEnding).be.eql('\r\n'); @@ -90,70 +91,106 @@ describe('Titanium.Filesystem', () => { } }); - it('getFile()', () => { - should(Ti.Filesystem.getFile).be.a.Function(); - const file = Ti.Filesystem.getFile('app.js'); - should(file).be.ok(); // not null or undefined. should(file).not.be.null causes a stack overflow somehow. - }); - - it('openStream()', () => { - should(Ti.Filesystem.openStream).not.be.undefined(); - should(Ti.Filesystem.openStream).be.a.Function(); - const stream = Ti.Filesystem.openStream(Ti.Filesystem.MODE_READ, 'app.js'); - should(stream).be.ok(); // not null or undefined. should(stream).not.be.null causes a stack overflow somehow. - stream.close(); - }); - - it('createTempDirectory()', () => { - should(Ti.Filesystem.createTempDirectory).not.be.undefined(); - should(Ti.Filesystem.createTempDirectory).be.a.Function(); - const dir = Ti.Filesystem.createTempDirectory(); - should.exist(dir); - should.exist(dir.name); - should(dir.exists()).be.true(); - should(dir.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, dir.name).nativePath); - should(dir.deleteDirectory()).be.true(); - should(dir.exists()).be.false(); + describe('#getFile()', () => { + it('is a Function', () => should(Ti.Filesystem.getFile).be.a.Function()); + + it('returns a File', () => { + const file = Ti.Filesystem.getFile('app.js'); + should(file).be.ok(); // not null or undefined. should(file).not.be.null causes a stack overflow somehow. + }); + + // TIMOB-10107 + it('handles multiLingualFilename', () => { + const msg = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, '網上廣東話輸入法.txt'); + should(msg.write('Appcelerator', true)).be.true(); + should(msg.exists()).be.true(); + should(msg.deleteFile()).be.true(); + should(msg.exists()).be.false(); + }); + + it('should handle files with spaces in path - TIMOB-18765', () => { + const f = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, '/folder with spaces/comingSoon.html'); + should(f.exists()).be.true(); + }); + + // FIXME: Should this work? It is a difference versus how some other file/url resolution works... + it.allBroken('should handle absolute-looking paths by resolving relative to resource dir', () => { + const f = Ti.Filesystem.getFile('/Logo.png'); // use absolute-looking URL, but actually relative to resources dir! + should(f.exists()).be.true(); + }); + }); + + describe('#openStream()', () => { + it('is a Function', () => should(Ti.Filesystem.openStream).be.a.Function()); + + it('should return a Stream', () => { + const stream = Ti.Filesystem.openStream(Ti.Filesystem.MODE_READ, 'app.js'); + try { + should(stream).be.ok(); // not null or undefined. should(stream).not.be.null causes a stack overflow somehow. + } finally { + stream.close(); + } + }); + }); + + /** + * On iOS device, comparing native paths can fail because + * one gives file:///private/var/..., the other file:///var/... + * but they're equivalent + * + * @param {string} fileURI file:// uri + * @returns {string} + */ + function normalizeIOSPath(fileURI) { + if (fileURI.startsWith('file:///private/var/')) { + return `file:///var/${fileURI.slice(20)}`; + } + return fileURI; + } + + describe('#createTempDirectory()', () => { + it('is a Function', () => should(Ti.Filesystem.createTempDirectory).be.a.Function()); + + it('creates directory under tempDirectory', () => { + const dir = Ti.Filesystem.createTempDirectory(); + should.exist(dir); + should.exist(dir.name); + should(dir.exists()).be.true(); + if (OS_IOS && !Ti.Platform.model.includes('(Simulator)')) { + should(normalizeIOSPath(dir.nativePath)).be.eql(normalizeIOSPath(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, dir.name).nativePath)); + } else { + should(dir.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, dir.name).nativePath); + } + should(dir.deleteDirectory()).be.true(); + should(dir.exists()).be.false(); + }); }); // Check if createTempFile exists and make sure it does not throw exception - it('createTempFile()', () => { - should(Ti.Filesystem.createTempFile).not.be.undefined(); - should(Ti.Filesystem.createTempFile).be.a.Function(); - const file = Ti.Filesystem.createTempFile(); - should(file).be.ok(); // not null or undefined. should(file).not.; causes a stack overflow somehow. - should(file.name).be.a.String(); - should(file.exists()).be.true(); - should(file.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, file.name).nativePath); - should(file.deleteFile()).be.true(); - should(file.exists()).be.false(); - }); - - // TIMOB-10107 - it('multiLingualFilename', () => { - const msg = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, '網上廣東話輸入法.txt'); - should(msg.write('Appcelerator', true)).be.true(); - should(msg.exists()).be.true(); - should(msg.deleteFile()).be.true(); - should(msg.exists()).be.false(); + describe('#createTempFile()', () => { + it('is a Function', () => should(Ti.Filesystem.createTempFile).be.a.Function()); + + it('creates file under tempDirectory', () => { + const file = Ti.Filesystem.createTempFile(); + should(file).be.ok(); // not null or undefined. should(file).not.; causes a stack overflow somehow. + should(file.name).be.a.String(); + should(file.exists()).be.true(); + if (OS_IOS && !Ti.Platform.model.includes('(Simulator)')) { + should(normalizeIOSPath(file.nativePath)).be.eql(normalizeIOSPath(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, file.name).nativePath)); + } else { + should(file.nativePath).be.eql(Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, file.name).nativePath); + } + should(file.deleteFile()).be.true(); + should(file.exists()).be.false(); + }); }); // TIMOB-23542 test getAsset() - it.ios('getAsset()', () => { - should(Ti.Filesystem.getAsset).not.be.undefined(); - should(Ti.Filesystem.getAsset).be.a.Function(); - const blob = Ti.Filesystem.getAsset('Logo.png'); - should(blob).be.an.Object(); // FIXME: fails on device! - }); - - it('#getFile() should handle files with spaces in path - TIMOB-18765', () => { - const f = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, '/folder with spaces/comingSoon.html'); - should(f.exists()).be.true(); - }); - - // FIXME: Should this work? It is a difference versus how some other file/url resolution works... - it.allBroken('#getFile() should handle absolute-looking paths by resolving relative to resource dir', () => { - const f = Ti.Filesystem.getFile('/Logo.png'); // use absolute-looking URL, but actually relative to resources dir! - should(f.exists()).be.true(); + describe.ios('#getAsset()', () => { + it('is a Function', () => should(Ti.Filesystem.getAsset).be.a.Function()); + it('should return a Ti.Blob', () => { + const blob = Ti.Filesystem.getAsset('Logo.png'); + should(blob).be.an.Object(); // FIXME: fails on device! + }); }); }); From 83b7083ef5db8ba65eb1469d62b43fb86c8cb542 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 12:57:57 -0400 Subject: [PATCH 26/33] refactor(android): use node-appc unzip, not AdmZip --- android/cli/commands/_build.js | 62 ++++++++++++++++++---------- android/cli/commands/_buildModule.js | 6 +-- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/android/cli/commands/_build.js b/android/cli/commands/_build.js index a99a3c6e9ee..cfcad993c43 100644 --- a/android/cli/commands/_build.js +++ b/android/cli/commands/_build.js @@ -14,7 +14,6 @@ 'use strict'; const ADB = require('node-titanium-sdk/lib/adb'), - AdmZip = require('adm-zip'), android = require('node-titanium-sdk/lib/android'), androidDetect = require('../lib/detect').detect, AndroidManifest = require('../lib/android-manifest'), @@ -3069,27 +3068,46 @@ AndroidBuilder.prototype.generateRequireIndex = async function generateRequireIn await fs.writeFile(cacheJsonFilePath, JSON.stringify(cacheAssets)); }; -AndroidBuilder.prototype.getNativeModuleBindings = function getNativeModuleBindings(jarFile) { - var zip = new AdmZip(jarFile), - zipEntries = zip.getEntries(), - i = 0, - len = zipEntries.length, - pathName = 'org/appcelerator/titanium/bindings/', - pathNameLen = pathName.length, - entry, name; - - for (; i < len; i++) { - entry = zipEntries[i]; - name = entry.entryName.toString(); - if (name.length > pathNameLen && name.indexOf(pathName) === 0) { - try { - return JSON.parse(entry.getData()); - } catch (e) { - // ignore +/** + * @param {string} jarFile filepath to JAR + * @returns {Promis} parsed JSON of the module's bindings + */ +AndroidBuilder.prototype.getNativeModuleBindings = async function getNativeModuleBindings(jarFile) { + return new Promise((resolve, reject) => { + const yauzl = require('yauzl'); + yauzl.open(jarFile, { lazyEntries: true }, (err, zipfile) => { + if (err) { + return reject(err); } - return; - } - } + + zipfile.once('error', reject); + zipfile.on('entry', entry => { + if (!entry.fileName.startsWith('org/appcelerator/titanium/bindings/')) { + zipfile.readEntry(); // move on + return; + } + // read the entry + zipfile.openReadStream(entry, function (err, readStream) { + if (err) { + return reject(err); + } + + // read file contents and when done, parse as JSON + const chunks = []; + readStream.once('error', reject); + readStream.on('data', chunk => chunks.push(chunk)); + readStream.on('end', () => { + try { + const str = Buffer.concat(chunks).toString('utf8'); + return resolve(JSON.parse(str)); + } catch (error) { + reject(error); + } + }); + }); + }); + }); + }); }; AndroidBuilder.prototype.generateJavaFiles = async function generateJavaFiles() { @@ -3136,7 +3154,7 @@ AndroidBuilder.prototype.generateJavaFiles = async function generateJavaFiles() const jarFilePath = path.join(module.modulePath, moduleName + '.jar'); try { if (await fs.exists(jarFilePath)) { - javaBindings = this.getNativeModuleBindings(jarFilePath); + javaBindings = await this.getNativeModuleBindings(jarFilePath); } } catch (ex) { this.logger.error(__n('The module "%s" has an invalid jar file: %s', module.id, jarFilePath)); diff --git a/android/cli/commands/_buildModule.js b/android/cli/commands/_buildModule.js index 63a83f78744..7313fe3e9a4 100644 --- a/android/cli/commands/_buildModule.js +++ b/android/cli/commands/_buildModule.js @@ -13,8 +13,7 @@ 'use strict'; -const AdmZip = require('adm-zip'), - androidDetect = require('../lib/detect').detect, +const androidDetect = require('../lib/detect').detect, AndroidManifest = require('../lib/android-manifest'), appc = require('node-appc'), archiver = require('archiver'), @@ -899,8 +898,7 @@ AndroidModuleBuilder.prototype.runModule = async function (cli) { ); // Unzip module into temp app's "modules" directory. - const zip = new AdmZip(this.moduleZipPath); - zip.extractAllTo(tmpProjectDir, true); + await util.promisify(appc.zip.unzip)(this.moduleZipPath, tmpProjectDir, null); // Emit hook so modules can also alter project before launch await new Promise(resolve => cli.emit('create.module.app.finalize', [ this, tmpProjectDir ], resolve)); From 78dd00adbc58fbe918ba1de98838e951f466cc2a Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 12:58:31 -0400 Subject: [PATCH 27/33] refactor(ios): use node-appc unzip, not AdmZip --- iphone/cli/commands/_buildModule.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/iphone/cli/commands/_buildModule.js b/iphone/cli/commands/_buildModule.js index ef638b72668..a71993f2c18 100644 --- a/iphone/cli/commands/_buildModule.js +++ b/iphone/cli/commands/_buildModule.js @@ -1046,12 +1046,8 @@ iOSModuleBuilder.prototype.runModule = function runModule(cli, next) { } ); - // 5. unzip module to the tmp dir. Use native binary on macOS, as AdmZip doesn't support symlinks used in mac catalyst frameworks - const proc = spawn('unzip', [ '-o', this.moduleZipPath, '-d', tmpProjectDir ]); - proc.stdout.on('data', data => this.logger.trace(data.toString().trimEnd())); - proc.stderr.on('data', data => this.logger.error(data.toString().trimEnd())); - proc.once('error', err => cb(err)); - proc.on('exit', () => cb()); + // 5. unzip module to the tmp dir + appc.zip.unzip(this.moduleZipPath, tmpProjectDir, null, cb); }, // Emit hook so modules can also alter project before launch From 71516f2b14f30976e19b431365c0d942d766cd60 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 12:59:02 -0400 Subject: [PATCH 28/33] build: use node-appc unzip, not native unzip binary in SDK build process --- build/lib/utils.js | 17 +---------------- build/win32/unzip.exe | Bin 164864 -> 0 bytes 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 build/win32/unzip.exe diff --git a/build/lib/utils.js b/build/lib/utils.js index 6c505b0fe50..60a3d0317c1 100644 --- a/build/lib/utils.js +++ b/build/lib/utils.js @@ -300,22 +300,7 @@ Utils.cacheExtract = async function (inFile, integrity, outDir, extractFunc) { * @returns {Promise} */ Utils.unzip = function unzip(zipfile, dest) { - return new Promise((resolve, reject) => { - console.log(`Unzipping ${zipfile} to ${dest}`); - const command = os.platform() === 'win32' ? path.join(ROOT_DIR, 'build/win32/unzip') : 'unzip'; - const child = spawn(command, [ '-o', zipfile, '-d', dest ], { stdio: [ 'ignore', 'ignore', 'pipe' ] }); - let err = ''; - child.stderr.on('data', buffer => { - err += buffer.toString(); - }); - child.on('error', err => reject(err)); - child.on('close', code => { - if (code !== 0) { - return reject(new Error(`Unzipping of ${zipfile} exited with non-zero exit code ${code}. ${err}`)); - } - resolve(); - }); - }); + return util.promisify(appc.zip.unzip)(zipfile, dest, null); }; /** diff --git a/build/win32/unzip.exe b/build/win32/unzip.exe deleted file mode 100644 index b10387734a2a5ea99f5161cfc895a57864f09792..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164864 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 CJq2$7 From b1f6c54d59faeb2573a506c8a99fa3dcf2595fd4 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 13:00:08 -0400 Subject: [PATCH 29/33] chore(deps): remove adm-zip --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 050402fefb5..0f22a3e6701 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ } }, "dependencies": { - "adm-zip": "^0.4.16", "always-tail": "^0.2.0", "ansi-escapes": "^4.3.1", "appc-tasks": "^1.0.2", From 8daed4823c55784017ed8b655449e1dac0da1ad3 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 13:00:27 -0400 Subject: [PATCH 30/33] chore(deps): add yauzl --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f22a3e6701..3f26106bb37 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,8 @@ "temp": "0.9.1", "wrap-ansi": "^7.0.0", "xcode": "^3.0.1", - "xmldom": "^0.3.0" + "xmldom": "^0.3.0", + "yauzl": "^2.10.0" }, "devDependencies": { "@commitlint/cli": "^11.0.0", From 4c5af52f7c3b1a19201af69aa3134373cd5b7712 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 21 Oct 2020 13:01:42 -0400 Subject: [PATCH 31/33] chore(deps): remove css-parse --- package-lock.json | 50 +++++++++++------------------------------------ package.json | 1 - 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6609dae9fbf..08d13ceafdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4028,11 +4028,6 @@ } } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -4548,7 +4543,8 @@ "atob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true }, "atob-lite": { "version": "2.0.0", @@ -6348,35 +6344,6 @@ } } }, - "css": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", - "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", - "requires": { - "inherits": "^2.0.1", - "source-map": "^0.1.38", - "source-map-resolve": "^0.5.1", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "requires": { - "css": "^2.0.0" - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -6546,7 +6513,8 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "dedent": { "version": "0.7.0", @@ -13459,7 +13427,8 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "restore-cursor": { "version": "2.0.0", @@ -13868,6 +13837,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -13879,7 +13849,8 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "sourcemap-codec": { "version": "1.4.6", @@ -14878,7 +14849,8 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "use": { "version": "3.1.1", diff --git a/package.json b/package.json index 3f26106bb37..8ed33e08b65 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,6 @@ "buffer-equal": "1.0.0", "clean-css": "4.2.3", "colors": "^1.4.0", - "css-parse": "2.0.0", "ejs": "^3.1.5", "fields": "0.1.24", "fs-extra": "^9.0.1", From bdf7d365edc39d9d273570996494ddbc3f9a442e Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Thu, 22 Oct 2020 18:35:15 +0100 Subject: [PATCH 32/33] fix(android): start zip read, close zipfile when done --- android/cli/commands/_build.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/cli/commands/_build.js b/android/cli/commands/_build.js index cfcad993c43..47f37132624 100644 --- a/android/cli/commands/_build.js +++ b/android/cli/commands/_build.js @@ -3070,7 +3070,7 @@ AndroidBuilder.prototype.generateRequireIndex = async function generateRequireIn /** * @param {string} jarFile filepath to JAR - * @returns {Promis} parsed JSON of the module's bindings + * @returns {Promise} parsed JSON of the module's bindings */ AndroidBuilder.prototype.getNativeModuleBindings = async function getNativeModuleBindings(jarFile) { return new Promise((resolve, reject) => { @@ -3098,6 +3098,7 @@ AndroidBuilder.prototype.getNativeModuleBindings = async function getNativeModul readStream.on('data', chunk => chunks.push(chunk)); readStream.on('end', () => { try { + zipfile.close(); const str = Buffer.concat(chunks).toString('utf8'); return resolve(JSON.parse(str)); } catch (error) { @@ -3106,6 +3107,7 @@ AndroidBuilder.prototype.getNativeModuleBindings = async function getNativeModul }); }); }); + zipfile.readEntry(); }); }); }; From b56821df9540e7dfc8c3366bd52b736ad95239a2 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Fri, 23 Oct 2020 12:57:02 -0400 Subject: [PATCH 33/33] test: limit one date picker test to ios --- tests/Resources/ti.ui.picker.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Resources/ti.ui.picker.test.js b/tests/Resources/ti.ui.picker.test.js index 0a9fdfd3f77..fd739195c21 100644 --- a/tests/Resources/ti.ui.picker.test.js +++ b/tests/Resources/ti.ui.picker.test.js @@ -319,7 +319,7 @@ describe('Titanium.UI.Picker', function () { win.open(); }); - it('DatePicker dateTimeColor (valid "type" + "datePickerStyle" - TIMOB-28181)', function (finish) { + it.ios('DatePicker dateTimeColor (valid "type" + "datePickerStyle" - TIMOB-28181)', function (finish) { const dp = Ti.UI.createPicker({ type: Ti.UI.PICKER_TYPE_DATE, datePickerStyle: Ti.UI.iOS.DATE_PICKER_STYLE_WHEELS,