Skip to content

Commit

Permalink
Merge branch 'master' into TIMOB-25678
Browse files Browse the repository at this point in the history
  • Loading branch information
garymathews committed Oct 18, 2018
2 parents a7e7f2f + 86233e2 commit d222025
Show file tree
Hide file tree
Showing 16 changed files with 727 additions and 264 deletions.
4 changes: 3 additions & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ def unitTests(os, nodeVersion, npmVersion, testSuiteBranch) {
if ('ios'.equals(os)) {
// Gather the crash report(s)
def home = sh(returnStdout: true, script: 'printenv HOME').trim()
// wait 1 minute, sometimes it's delayed in writing out crash reports to disk...
sleep time: 1, unit: 'MINUTES'
def crashFiles = sh(returnStdout: true, script: "ls -1 ${home}/Library/Logs/DiagnosticReports/").trim().readLines()
for (int i = 0; i < crashFiles.size(); i++) {
def crashFile = crashFiles[i]
Expand Down Expand Up @@ -460,7 +462,7 @@ timestamps {
withEnv(['ghprbGhRepository=appcelerator/titanium_mobile',"ghprbPullId=${env.CHANGE_ID}", "ZIPFILE=${basename}-osx.zip", "BUILD_STATUS=${currentBuild.currentResult}"]) {
// FIXME Can't pass along env variables properly, so we cheat and write them as a JSON file we can require
sh 'node -p \'JSON.stringify(process.env)\' > env.json'
sh returnStatus: true, script: 'npx danger' // Don't fail build if danger fails. We want to retain existing build status.
sh returnStatus: true, script: 'npx danger ci' // Don't fail build if danger fails. We want to retain existing build status.
} // withEnv
} // nodejs
deleteDir()
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ see the LICENSE file for specific details.
*[Download Pre-built Titanium](http://builds.appcelerator.com/#master)*

# Table of Contents

[![Greenkeeper badge](https://badges.greenkeeper.io/appcelerator/titanium_mobile.svg)](https://greenkeeper.io/)

1. [Features](#features)
2. [Hyperloop](#hyperloop)
3. [Alloy](#alloy)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,25 @@ public void hide()
}
}

@Kroll.method
public void pin()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && shortcut != null) {
if (shortcutManager.isRequestPinShortcutSupported()) {
boolean shortcutExists = false;
for (ShortcutInfo shortcut : shortcutManager.getPinnedShortcuts()) {
if (shortcut.getId().equals(this.shortcut.getId())) {
shortcutExists = true;
break;
}
}
if (!shortcutExists) {
shortcutManager.requestPinShortcut(this.shortcut, null);
}
}
}
}

@Kroll.getProperty
public String getId()
{
Expand Down Expand Up @@ -174,4 +193,4 @@ public String getApiName()
{
return "Ti.UI.ShortcutItem";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,19 @@ protected void onResume()
tiApp.setCurrentActivity(this, this);
TiApplication.updateActivityTransitionState(false);

// handle shortcut intents
Intent intent = getIntent();
String shortcutId =
intent.hasExtra(TiC.EVENT_PROPERTY_SHORTCUT) ? intent.getStringExtra(TiC.EVENT_PROPERTY_SHORTCUT) : null;
if (shortcutId != null) {
KrollModule appModule = TiApplication.getInstance().getModuleByName("App");
if (appModule != null) {
KrollDict data = new KrollDict();
data.put(TiC.PROPERTY_ID, shortcutId);
appModule.fireEvent(TiC.EVENT_SHORTCUT_ITEM_CLICK, data);
}
}

if (activityProxy != null) {
activityProxy.fireEvent(TiC.EVENT_RESUME, null);
}
Expand Down
9 changes: 9 additions & 0 deletions apidoc/Titanium/App/Android/Android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ properties:
permission: read-only
since: 3.3.0

events:
- name: shortcutitemclick
summary: Fired when a <Titanium.UI.ShortcutItem> is clicked.
properties:
- name: id
summary: Identifier of the clicked shortcut item.
type: String
since: 7.5.0

examples:
- title: Custom String Resource
example: |
Expand Down
7 changes: 6 additions & 1 deletion apidoc/Titanium/UI/ShortcutItem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: |
Use the <Titanium.UI.createShortcutItem> method to create a shortcut.
extends: Titanium.Proxy
since: "7.4.0"
since: "7.5.0"
methods:
- name: show
summary: Allow the shortcut to show.
Expand All @@ -18,6 +18,11 @@ methods:
summary: Hide the shortcut.
platforms: [android, iphone, ipad]

- name: pin
description: Pin shortcut to launcher.
platforms: [android]
osver: {android: {min: "8.0"}}

properties:
- name: id
summary: Determines shortcut id.
Expand Down
2 changes: 1 addition & 1 deletion build/android.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Android.prototype.package = function (packager, next) {
// Copy over module resources
function (cb) {
const filterRegExp = new RegExp('\\' + path.sep + 'android(\\' + path.sep + 'titanium-(.+)?.(jar|res.zip|respackage))?$'); // eslint-disable-line security/detect-non-literal-regexp
fs.copy(DIST_ANDROID, ANDROID_MODULES, { filter: filterRegExp }, cb);
fs.copy(DIST_ANDROID, ANDROID_MODULES, { filter: src => filterRegExp.test(src) }, cb);
}
], next);
};
Expand Down
16 changes: 16 additions & 0 deletions greenkeeper.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"groups": {
"default": {
"packages": [
"android/package.json",
"iphone/package.json",
"package.json"
]
},
"templates": {
"packages": [
"templates/app/angular-default/template/app/package.json"
]
}
}
}
4 changes: 3 additions & 1 deletion iphone/Classes/KrollBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,9 @@ - (id)registerProxy:(id)proxy
ourKrollObject = [[KrollObject alloc] initWithTarget:proxy context:context];
#endif
#ifdef USE_JSCORE_FRAMEWORK
[ourKrollObject protectJsobject];
if (![proxy isKindOfClass:[TiModule class]]) {
[ourKrollObject applyGarbageCollectionSafeguard];
}
#endif

[self registerProxy:proxy
Expand Down
5 changes: 5 additions & 0 deletions iphone/Classes/KrollObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ bool KrollDeleteProperty(TiContextRef ctx, TiObjectRef object, TiStringRef prope
- (void)removeListener:(KrollCallback *)eventCallback forEvent:(NSString *)eventName;
- (void)triggerEvent:(NSString *)eventName withObject:(NSDictionary *)eventData thisObject:(KrollObject *)thisObject;

#ifdef USE_JSCORE_FRAMEWORK
- (void)applyGarbageCollectionSafeguard;
- (void)removeGarbageCollectionSafeguard;
#endif

@end
75 changes: 75 additions & 0 deletions iphone/Classes/KrollObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,16 @@ bool KrollHasInstance(TiContextRef ctx, TiObjectRef constructor, TiValueRef poss
return false;
}

@interface KrollObject ()

/**
Boolean flag indicating whether the underlying JSObjectRef was safeguarded against
being GC'ed during the proxy creation flow.
*/
@property (nonatomic, assign, getter=isGcSafeguarded) BOOL gcSafeguarded;

@end

@implementation KrollObject

@synthesize propsObject, finalized, bridge;
Expand Down Expand Up @@ -445,6 +455,8 @@ - (id)initWithTarget:(id)target_ context:(KrollContext *)context_
bridge = (KrollBridge *)[context_ delegate];
jsobject = TiObjectMake(jsContext, [[self class] jsClassRef], self);
targetable = [target conformsToProtocol:@protocol(KrollTargetable)];

self.gcSafeguarded = NO;
}
return self;
}
Expand Down Expand Up @@ -1398,4 +1410,67 @@ - (void)triggerEvent:(NSString *)eventName withObject:(NSDictionary *)eventData
}
}

#ifdef USE_JSCORE_FRAMEWORK
/**
Protects the underlying JSObjectRef from being accidentally GC'ed.
Upon proxy creation there is a small timeframe between creating the KrollObject
with its JSObject and the JSObject actually getting referenced in the JS object graph.
If JSC's garbage collection happens during this time the JSObject is lost and eventually
leads to a crash inside the JSC runtime.
*/
- (void)applyGarbageCollectionSafeguard
{
if (self.isGcSafeguarded == YES) {
return;
}

if (finalized == YES || jsContext == NULL || jsobject == NULL) {
return;
}

#ifdef TI_USE_KROLL_THREAD
if (![context isKJSThread]) {
NSOperation *safeProtect = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(applyGarbageCollectionSafeguard) object:nil];
[context enqueue:safeProtect];
[safeProtect release];
return;
}
#endif

TiValueProtect(jsContext, jsobject);
self.gcSafeguarded = YES;
}

/**
Removes the garbage collection safeguard by unprotecting the JSObjectRef again.
This must only be called immediately before the JSObjectRef gets inserted into the JS object
graph. Even better would be after the insertion but there is currently no viable place to do
that in our proxy creation flow.
*/
- (void)removeGarbageCollectionSafeguard
{
if (self.isGcSafeguarded == NO) {
return;
}

if (finalized == YES || jsContext == NULL || jsobject == NULL) {
return;
}

#ifdef TI_USE_KROLL_THREAD
if (![context isKJSThread]) {
NSOperation *safeUnprotect = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(removeGarbageCollectionSafeguard) object:nil];
[context enqueue:safeUnprotect];
[safeUnprotect release];
return;
}
#endif

TiValueUnprotect(jsContext, jsobject);
self.gcSafeguarded = NO;
}
#endif

@end
2 changes: 1 addition & 1 deletion iphone/Classes/TiBindingTiValue.m
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ TiValueRef TiBindingTiValueFromProxy(TiContextRef jsContext, TiProxy *obj)
}
KrollObject *objKrollObject = [ourBridge krollObjectForProxy:obj];
#ifdef USE_JSCORE_FRAMEWORK
[objKrollObject unprotectJsobject];
[objKrollObject removeGarbageCollectionSafeguard];
#endif
return [objKrollObject jsobject];
}
Expand Down
15 changes: 11 additions & 4 deletions iphone/cli/commands/_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2553,10 +2553,15 @@ iOSBuilder.prototype.determineLogServerPort = function determineLogServerPort(ne

let client = null;

function die() {
function die(error) {
client && client.destroy();
_t.logger.error(__('Another process is currently bound to port %d', _t.tiLogServerPort));
_t.logger.error(__('Set a unique <log-server-port> between 1024 and 65535 in the <ios> section of the tiapp.xml') + '\n');
if (error.code === 'ENOTFOUND') {
_t.logger.error(__('Unable to connect to log server on localhost'));
_t.logger.error(__('Please ensure your /etc/hosts file contains a valid entry for `localhost`'));
} else {
_t.logger.error(__('Another process is currently bound to port %d', _t.tiLogServerPort));
_t.logger.error(__('Set a unique <log-server-port> between 1024 and 65535 in the <ios> section of the tiapp.xml') + '\n');
}
process.exit(1);
}

Expand All @@ -2567,6 +2572,8 @@ iOSBuilder.prototype.determineLogServerPort = function determineLogServerPort(ne
// then we will fail out
// - if the port is bound by another process that expects data before the
// response is returned, then we will just timeout and fail out
// - if localhost cannot be resolved then we will fail out and inform
// the user of that
client = net.connect({
host: 'localhost',
port: _t.tiLogServerPort,
Expand All @@ -2584,7 +2591,7 @@ iOSBuilder.prototype.determineLogServerPort = function determineLogServerPort(ne
process.exit(1);
}
} catch (e) {
die();
die(e);
}
_t.logger.debug(__('The log server port is being used by the app being built, continuing'));
next();
Expand Down

0 comments on commit d222025

Please sign in to comment.