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/cli/commands/_build.js b/android/cli/commands/_build.js index a99a3c6e9ee..47f37132624 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,48 @@ 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 {Promise} 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 { + zipfile.close(); + const str = Buffer.concat(chunks).toString('utf8'); + return resolve(JSON.parse(str)); + } catch (error) { + reject(error); + } + }); + }); + }); + zipfile.readEntry(); + }); + }); }; AndroidBuilder.prototype.generateJavaFiles = async function generateJavaFiles() { @@ -3136,7 +3156,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)); diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar index 490fda8577d..62d4c053550 100644 Binary files a/android/gradle/wrapper/gradle-wrapper.jar and b/android/gradle/wrapper/gradle-wrapper.jar differ 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/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/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/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", 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/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 deleted file mode 100644 index 58bcbaf05db..00000000000 --- a/android/runtime/common/src/java/org/appcelerator/kroll/util/TiTempFileHelper.java +++ /dev/null @@ -1,196 +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; - -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; - } -} 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' diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java index 81108c546d8..c656a5ba07c 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,156 @@ 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() + { + 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 = { + // 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); + } + } + } + + // 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 { + 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 { - File cacheDir = new File(tempFileHelper.getTempDirectory(), "remote-cache"); - if (!cacheDir.exists()) { - cacheDir.mkdirs(); - tempFileHelper.excludeFileOnCleanup(cacheDir); + // 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; + } } - return cacheDir.getAbsoluteFile(); + + // Delete the given directory/file. + return (wasDeleted && file.delete()); } public void setRootActivity(TiRootActivity rootActivity) @@ -511,8 +643,6 @@ public void setRootActivity(TiRootActivity rootActivity) break; } } - - tempFileHelper.scheduleCleanTempDir(); } /** @@ -836,12 +966,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 +1033,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); 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); 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/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/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/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/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/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; diff --git a/build/win32/unzip.exe b/build/win32/unzip.exe deleted file mode 100644 index b10387734a2..00000000000 Binary files a/build/win32/unzip.exe and /dev/null differ 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]; 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/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 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 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-lock.json b/package-lock.json index c6945731470..08d13ceafdd 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", @@ -4022,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", @@ -4481,71 +4482,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", @@ -4607,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", @@ -5428,12 +5365,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" } }, @@ -5609,13 +5545,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", @@ -5630,21 +5566,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", @@ -6423,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", @@ -6621,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", @@ -6868,86 +6761,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 +7663,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", @@ -8882,9 +8684,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" } @@ -9043,16 +8845,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.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", "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": { @@ -9064,27 +8866,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": { @@ -9099,36 +8886,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==" } } }, @@ -9141,12 +8898,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 +9000,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 +9066,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 +9315,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", @@ -9842,18 +9565,18 @@ "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" } }, "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", @@ -9874,12 +9597,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" } }, @@ -9929,12 +9651,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": { @@ -10097,12 +9819,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" } }, @@ -10567,12 +10288,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" } }, @@ -10774,16 +10494,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": { @@ -11164,15 +10892,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 +10912,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 +10970,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 +10995,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 +11042,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", @@ -11348,9 +11119,15 @@ "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", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -11405,9 +11182,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", @@ -11478,13 +11255,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": { @@ -11541,11 +11318,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": { @@ -11690,7 +11467,7 @@ "bundled": true }, "needle": { - "version": "2.4.0", + "version": "2.5.2", "bundled": true, "requires": { "debug": "^3.2.6", @@ -11708,12 +11485,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", @@ -11721,6 +11498,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": { @@ -13031,12 +12821,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", @@ -13138,72 +12922,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 +13120,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", @@ -13700,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", @@ -13733,9 +13461,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.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" @@ -13906,9 +13634,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" @@ -14109,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", @@ -14120,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", @@ -14753,30 +14483,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", @@ -14785,203 +14508,20 @@ "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 } } }, "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.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": "^10.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 - } + "markdown-it": "^12.0.0", + "node-appc": "^1.1.2" } }, "tmp": { @@ -15309,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", @@ -15457,9 +14998,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", @@ -15467,7 +15008,6 @@ "cycle": "1.0.x", "eyes": "0.1.x", "isstream": "0.1.x", - "pkginfo": "0.3.x", "stack-trace": "0.0.x" }, "dependencies": { @@ -15497,9 +15037,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 +15295,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..8ed33e08b65 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", @@ -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", @@ -95,11 +94,10 @@ "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", - "ioslib": "^1.7.21", + "ioslib": "^1.7.23", "liveview": "^1.5.4", "lodash.merge": "^4.6.2", "markdown": "0.5.0", @@ -117,7 +115,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", @@ -130,7 +129,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", @@ -142,21 +141,21 @@ "folder-hash": "^4.0.0", "glob": "^7.1.6", "husky": "^4.3.0", - "lint-staged": "^10.4.0", - "mocha": "^8.1.3", + "lint-staged": "^10.4.2", + "mocha": "^8.2.0", "mocha-jenkins-reporter": "^0.4.5", "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "request-promise-native": "^1.0.9", - "rollup": "^2.31.0", + "rollup": "^2.32.1", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "ssri": "^8.0.0", "stream-splitter": "^0.3.2", "strip-ansi": "^6.0.0", - "titanium": "^5.2.5", - "titanium-docgen": "^4.8.1" + "titanium": "^5.3.0", + "titanium-docgen": "^4.8.3" }, "repository": { "type": "git", 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 +} diff --git a/tests/Resources/ti.filesystem.test.js b/tests/Resources/ti.filesystem.test.js index cd4d3dc9834..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,69 +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(); - }); - - // FIXME Get working on Android. Either exists() or deleteDirectory() is returning false - it.androidBroken('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.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.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! + }); }); }); 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.picker.test.js b/tests/Resources/ti.ui.picker.test.js index 4f8646fca07..fd739195c21 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.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, + 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 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({});