Android console improved to support circular objects.

This commit is contained in:
Nedyalko Nikolov
2015-06-08 10:25:56 +03:00
parent 0236e470dc
commit d335fae123
7 changed files with 94 additions and 90 deletions

View File

@ -241,16 +241,9 @@
<DependentUpon>color.d.ts</DependentUpon> <DependentUpon>color.d.ts</DependentUpon>
</TypeScriptCompile> </TypeScriptCompile>
<TypeScriptCompile Include="color\known-colors.ts" /> <TypeScriptCompile Include="color\known-colors.ts" />
<TypeScriptCompile Include="console\console-native.android.ts">
<DependentUpon>console-native.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="console\console-native.ios.ts">
<DependentUpon>console-native.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="console\console.ts"> <TypeScriptCompile Include="console\console.ts">
<DependentUpon>console.d.ts</DependentUpon> <DependentUpon>console.d.ts</DependentUpon>
</TypeScriptCompile> </TypeScriptCompile>
<TypeScriptCompile Include="console\console-native.d.ts" />
<TypeScriptCompile Include="declarations.d.ts" /> <TypeScriptCompile Include="declarations.d.ts" />
<TypeScriptCompile Include="declarations.android.d.ts"> <TypeScriptCompile Include="declarations.android.d.ts">
<DependentUpon>declarations.d.ts</DependentUpon> <DependentUpon>declarations.d.ts</DependentUpon>

View File

@ -5,7 +5,6 @@ import labelModule = require("ui/label");
import trace = require("trace"); import trace = require("trace");
import enums = require("ui/enums"); import enums = require("ui/enums");
import fps = require("fps-meter"); import fps = require("fps-meter");
import cn = require("console/console-native");
export function createPage() { export function createPage() {
fps.addCallback(function (fps, minFps) { fps.addCallback(function (fps, minFps) {
@ -29,7 +28,7 @@ export function createPage() {
var childStackLayout; var childStackLayout;
var childStackLayoutCount = count / buttonsPerRow; var childStackLayoutCount = count / buttonsPerRow;
trace.write("Creating " + count + " buttons.", trace.categories.Test, trace.messageType.info); trace.write("Creating " + count + " buttons.", trace.categories.Test, trace.messageType.info);
var startTime = cn.timeMillis() console.time("creatingButtons");
for (var i = 0; i < childStackLayoutCount; i++) { for (var i = 0; i < childStackLayoutCount; i++) {
childStackLayout = new stackLayoutModule.StackLayout(); childStackLayout = new stackLayoutModule.StackLayout();
childStackLayout.orientation = enums.Orientation.horizontal; childStackLayout.orientation = enums.Orientation.horizontal;
@ -43,8 +42,8 @@ export function createPage() {
childStackLayout.addChild(button); childStackLayout.addChild(button);
} }
} }
var elapsedTime = Math.round(cn.timeMillis() - startTime); console.timeEnd("creatingButtons");
var message = "Created " + count + " buttons in " + elapsedTime + " ms."; var message = "Created " + count + " buttons";
trace.write(message, trace.categories.Test, trace.messageType.info); trace.write(message, trace.categories.Test, trace.messageType.info);
label.text = message; label.text = message;
@ -52,4 +51,3 @@ export function createPage() {
page.content = mainStackLayout; page.content = mainStackLayout;
return page; return page;
} }
//export var Page = page;

View File

@ -2,7 +2,6 @@ import pages = require("ui/page");
import labelModule = require("ui/label"); import labelModule = require("ui/label");
import common = require("../common"); import common = require("../common");
import trace = require("trace"); import trace = require("trace");
import cn = require("console/console-native");
export function createPage() { export function createPage() {
var count = 2000000; var count = 2000000;
@ -13,12 +12,12 @@ export function createPage() {
page.content = label; page.content = label;
trace.write("Creating " + count + " objects.", trace.categories.Test, trace.messageType.info); trace.write("Creating " + count + " objects.", trace.categories.Test, trace.messageType.info);
var startTime = cn.timeMillis(); console.time("creatingObjects");
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
people[i] = new common.Person("John Doe", 33, 1234.56); people[i] = new common.Person("John Doe", 33, 1234.56);
} }
var elapsedTime = Math.round(cn.timeMillis() - startTime); console.timeEnd("creatingObjects");
var message = "Created " + people.length + " objects in " + elapsedTime + " ms."; var message = "Created " + people.length + " objects";
trace.write(message, trace.categories.Test, trace.messageType.info); trace.write(message, trace.categories.Test, trace.messageType.info);
label.text = message; label.text = message;
return page; return page;

View File

@ -1,22 +0,0 @@
var TAG = 'JS';
export var helper_log = function (message: string) {
android.util.Log.v(TAG, message);
}
export var info = function (message: string) {
android.util.Log.i(TAG, message);
}
export var error = function (message: string) {
android.util.Log.e(TAG, message);
}
export var warn = function (message: string) {
android.util.Log.w(TAG, message);
}
export var timeMillis = function (): number {
// NOTE: we might need to use currentTimeMillis if we have troubles with the long size
return java.lang.System.nanoTime() / 1000000; // 1 ms = 1000000 ns
}

View File

@ -1,6 +0,0 @@
//@private
export declare var helper_log: (message: string) => void;
export declare var info: (message: string) => void;
export declare var error: (message: string) => void;
export declare var warn: (message: string) => void;
export declare var timeMillis: () => number;

View File

@ -1,24 +0,0 @@
function nslog(prefix: string, message: string)
{
//(<any>NSLog)(prefix + ": " + message);
}
export var helper_log = function (message: string) {
nslog('log', message);
}
export var info = function (message: string) {
nslog('info', message);
}
export var error = function (message: string) {
nslog('error', message);
}
export var warn = function (message: string) {
nslog('warning', message);
}
export var timeMillis = function (): number {
return CACurrentMediaTime() * 1000;
}

View File

@ -1,7 +1,8 @@
import helperModule = require("console/console-native");
import definition = require("console"); import definition = require("console");
import trace = require("trace");
export class Console implements definition.Console { export class Console implements definition.Console {
private TAG: string = "JS";
private _timers: any; private _timers: any;
private _stripFirstTwoLinesRegEx: RegExp; private _stripFirstTwoLinesRegEx: RegExp;
@ -33,7 +34,7 @@ export class Console implements definition.Console {
// example 5: sprintf('%-03s', 'E'); // example 5: sprintf('%-03s', 'E');
// returns 5: 'E00' // returns 5: 'E00'
var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgG])/g; var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgGj])/g;
var a = arguments; var a = arguments;
var i = 0; var i = 0;
var format = a[i++]; var format = a[i++];
@ -81,7 +82,7 @@ export class Console implements definition.Console {
} }
return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar); return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
}; };
var that = this;
// doFormat() // doFormat()
var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) { var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
var number, prefix, method, textTransform, value; var number, prefix, method, textTransform, value;
@ -192,6 +193,8 @@ export class Console implements definition.Console {
textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
value = prefix + Math.abs(number)[method](precision); value = prefix + Math.abs(number)[method](precision);
return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform](); return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
case 'j':
return that.createDump(value);
default: default:
return substring; return substring;
} }
@ -213,10 +216,14 @@ export class Console implements definition.Console {
return res; return res;
} }
private timeMillis() {
return java.lang.System.nanoTime() / 1000000; // 1 ms = 1000000 ns
}
public time(reportName: string): void { public time(reportName: string): void {
var name = reportName ? '__' + reportName : '__internal_console_time__'; var name = reportName ? '__' + reportName : '__internal_console_time__';
if (('undefined' === typeof (this._timers[name])) || (this._timers.hasOwnProperty(name))) { if (('undefined' === typeof (this._timers[name])) || (this._timers.hasOwnProperty(name))) {
this._timers[name] = helperModule.timeMillis(); this._timers[name] = this.timeMillis();
} }
else { else {
this.warn('invalid name for timer console.time(' + reportName + ')'); this.warn('invalid name for timer console.time(' + reportName + ')');
@ -228,8 +235,8 @@ export class Console implements definition.Console {
if (this._timers.hasOwnProperty(name)) { if (this._timers.hasOwnProperty(name)) {
var val = this._timers[name]; var val = this._timers[name];
if (val) { if (val) {
var time = helperModule.timeMillis(); var time = this.timeMillis();
this.info('console.time(' + reportName + '): %.6f ms', (time - val)); this.info('console.time(' + reportName + '): %.6f ms',(time - val));
this._timers[name] = undefined; this._timers[name] = undefined;
} }
else { else {
@ -241,7 +248,7 @@ export class Console implements definition.Console {
public assert(test: boolean, message: string, ...formatParams: any[]): void { public assert(test: boolean, message: string, ...formatParams: any[]): void {
if (!test) { if (!test) {
Array.prototype.shift.apply(arguments); Array.prototype.shift.apply(arguments);
helperModule.error(this.formatParams.apply(this, arguments)); this.error(this.formatParams.apply(this, arguments));
// duplicating trace code here because android version shows only 2 frames and if we call trace() // duplicating trace code here because android version shows only 2 frames and if we call trace()
// this would be assert() and trace() which leaves all important stack frames out of our view // this would be assert() and trace() which leaves all important stack frames out of our view
@ -269,19 +276,52 @@ export class Console implements definition.Console {
} }
public info(message: any, ...formatParams: any[]): void { public info(message: any, ...formatParams: any[]): void {
helperModule.info(this.formatParams.apply(this, arguments)); this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.info);
} }
public warn(message: any, ...formatParams: any[]): void { public warn(message: any, ...formatParams: any[]): void {
helperModule.warn(this.formatParams.apply(this, arguments)); this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.warn);
} }
public error(message: any, ...formatParams: any[]): void { public error(message: any, ...formatParams: any[]): void {
helperModule.error(this.formatParams.apply(this, arguments)); this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.error);
} }
public log(message: any, ...formatParams: any[]): void { public log(message: any, ...formatParams: any[]): void {
helperModule.helper_log(this.formatParams.apply(this, arguments)); this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.log);
}
private logMessage(message: string, messageType: number): void {
var arrayToLog = [];
if (message.length > 4000) {
var i;
for (i = 0; i * 4000 < message.length; i++) {
arrayToLog.push(message.substr((i * 4000), 4000));
}
}
else {
arrayToLog.push(message);
}
for (i = 0; i < arrayToLog.length; i++) {
switch (messageType) {
case trace.messageType.log: {
android.util.Log.v(this.TAG, arrayToLog[i]);
break;
}
case trace.messageType.warn: {
android.util.Log.w(this.TAG, arrayToLog[i]);
break;
}
case trace.messageType.error: {
android.util.Log.e(this.TAG, arrayToLog[i]);
break;
}
case trace.messageType.info: {
android.util.Log.i(this.TAG, arrayToLog[i]);
break;
}
}
}
} }
public trace(): void { public trace(): void {
@ -292,29 +332,55 @@ export class Console implements definition.Console {
this.log(stack); this.log(stack);
} }
public dump(obj: any): void { private createDump(obj: any): string {
var result = [];
if (null == obj) { if (null == obj) {
this.log("=== dump(): object is 'null' ==="); result.push("=== dump(): object is 'null' ===");
return; return result.join('');
} }
if ("undefined" === typeof obj) { if ("undefined" === typeof obj) {
this.log("=== dump(): object is 'undefined' ==="); result.push("=== dump(): object is 'undefined' ===");
return; return result.join('');
} }
var result = ['=== dump(): dumping members ===']; result.push('=== dump(): dumping members ===\n');
result.push(JSON.stringify(obj, null, 4)); var stringifyValueCache = [];
result.push('=== dump(): dumping function names ==='); var stringifyKeyCache = [];
result.push(JSON.stringify(obj, function (k, v) {
stringifyKeyCache.push(k);
if (typeof v === 'object' && v !== null) {
if (stringifyValueCache.indexOf(v) !== -1) {
return "#CR:" + (v.toString ? v.toString() : v);
}
stringifyValueCache.push(v);
}
if (typeof v === 'function') {
return k + "()" + v;
}
return v;
}, 4));
result.push('\n=== dump(): dumping function and properties names ===\n');
for (var id in obj) { for (var id in obj) {
try { try {
if (typeof (obj[id]) === 'function') { if (typeof (obj[id]) === 'function') {
result.push(id + '()'); result.push(id + '()\n');
}
else {
if (typeof (obj[id]) !== 'object' && stringifyKeyCache.indexOf(id) === -1) {
result.push(id + ": " + (obj[id] + '\n'));
}
} }
} catch (err) { } catch (err) {
result.push(id + ': inaccessible'); result.push(id + ': inaccessible');
} }
} }
stringifyValueCache = null;
stringifyKeyCache = null;
result.push('=== dump(): finished ==='); result.push('=== dump(): finished ===');
this.log(result.join('\n')); return result.join('');
}
public dump(obj: any): void {
this.log(this.createDump(obj));
} }
public dir = this.dump; public dir = this.dump;