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>
</TypeScriptCompile>
<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">
<DependentUpon>console.d.ts</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="console\console-native.d.ts" />
<TypeScriptCompile Include="declarations.d.ts" />
<TypeScriptCompile Include="declarations.android.d.ts">
<DependentUpon>declarations.d.ts</DependentUpon>

View File

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

View File

@ -2,7 +2,6 @@ import pages = require("ui/page");
import labelModule = require("ui/label");
import common = require("../common");
import trace = require("trace");
import cn = require("console/console-native");
export function createPage() {
var count = 2000000;
@ -13,12 +12,12 @@ export function createPage() {
page.content = label;
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++) {
people[i] = new common.Person("John Doe", 33, 1234.56);
}
var elapsedTime = Math.round(cn.timeMillis() - startTime);
var message = "Created " + people.length + " objects in " + elapsedTime + " ms.";
console.timeEnd("creatingObjects");
var message = "Created " + people.length + " objects";
trace.write(message, trace.categories.Test, trace.messageType.info);
label.text = message;
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 trace = require("trace");
export class Console implements definition.Console {
private TAG: string = "JS";
private _timers: any;
private _stripFirstTwoLinesRegEx: RegExp;
@ -33,7 +34,7 @@ export class Console implements definition.Console {
// example 5: sprintf('%-03s', 'E');
// 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 i = 0;
var format = a[i++];
@ -81,7 +82,7 @@ export class Console implements definition.Console {
}
return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
};
var that = this;
// doFormat()
var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
var number, prefix, method, textTransform, value;
@ -192,6 +193,8 @@ export class Console implements definition.Console {
textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
value = prefix + Math.abs(number)[method](precision);
return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
case 'j':
return that.createDump(value);
default:
return substring;
}
@ -213,10 +216,14 @@ export class Console implements definition.Console {
return res;
}
private timeMillis() {
return java.lang.System.nanoTime() / 1000000; // 1 ms = 1000000 ns
}
public time(reportName: string): void {
var name = reportName ? '__' + reportName : '__internal_console_time__';
if (('undefined' === typeof (this._timers[name])) || (this._timers.hasOwnProperty(name))) {
this._timers[name] = helperModule.timeMillis();
this._timers[name] = this.timeMillis();
}
else {
this.warn('invalid name for timer console.time(' + reportName + ')');
@ -228,7 +235,7 @@ export class Console implements definition.Console {
if (this._timers.hasOwnProperty(name)) {
var val = this._timers[name];
if (val) {
var time = helperModule.timeMillis();
var time = this.timeMillis();
this.info('console.time(' + reportName + '): %.6f ms',(time - val));
this._timers[name] = undefined;
}
@ -241,7 +248,7 @@ export class Console implements definition.Console {
public assert(test: boolean, message: string, ...formatParams: any[]): void {
if (!test) {
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()
// 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 {
helperModule.info(this.formatParams.apply(this, arguments));
this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.info);
}
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 {
helperModule.error(this.formatParams.apply(this, arguments));
this.logMessage(this.formatParams.apply(this, arguments), trace.messageType.error);
}
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 {
@ -292,29 +332,55 @@ export class Console implements definition.Console {
this.log(stack);
}
public dump(obj: any): void {
private createDump(obj: any): string {
var result = [];
if (null == obj) {
this.log("=== dump(): object is 'null' ===");
return;
result.push("=== dump(): object is 'null' ===");
return result.join('');
}
if ("undefined" === typeof obj) {
this.log("=== dump(): object is 'undefined' ===");
return;
result.push("=== dump(): object is 'undefined' ===");
return result.join('');
}
var result = ['=== dump(): dumping members ==='];
result.push(JSON.stringify(obj, null, 4));
result.push('=== dump(): dumping function names ===');
result.push('=== dump(): dumping members ===\n');
var stringifyValueCache = [];
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) {
try {
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) {
result.push(id + ': inaccessible');
}
}
stringifyValueCache = null;
stringifyKeyCache = null;
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;