This commit is contained in:
Rob Lourens 2015-11-03 15:45:42 -08:00
Родитель d5c2724a3b
Коммит a2817c565d
6 изменённых файлов: 130 добавлений и 50 удалений

Просмотреть файл

@ -16,30 +16,32 @@ suite('ConsoleHelper', () => {
}
suite('console.log()', () => {
test('handles simple log', () => {
test('simple log', () => {
doAssert(Console.makeLog('Hello'), 'Hello');
doAssert(Console.makeLog('Hello', 123, 'world!'), 'Hello 123 world!');
});
test('handles basic format specifiers', () => {
test('basic format specifiers', () => {
doAssert(Console.makeLog('%s, %d', 'test', 123), 'test, 123');
});
test('handles numeric format specifiers correctly', () => {
test('numeric format specifiers correctly', () => {
doAssert(Console.makeLog('%d %i %f', 1.9, 324, 9.4), '1 324 9.4');
doAssert(Console.makeLog('%d %i %f', -19, -32.5, -9.4), '-19 -33 -9.4');
doAssert(Console.makeLog('%d %i %f', 'not', 'a', 'number'), 'NaN NaN NaN');
});
test('handles unmatched format specifiers', () => {
test('unmatched format specifiers', () => {
doAssert(Console.makeLog('%s %s %s', 'test'), 'test %s %s');
doAssert(Console.makeLog('%s %s end', 'test1', 'test2', 'test3'), 'test1 test2 end test3');
});
test('weird cases', () => {
test('null/undefined cases', () => {
doAssert(Console.makeLog('%s %s %s', null, undefined, 'test'), 'null undefined test');
doAssert(Console.makeLog('test', null, undefined), 'test null undefined');
});
test('objects- waiting on VS Code bug 20343');
});
suite('console.assert()', () => {
@ -71,7 +73,12 @@ namespace Console {
url: 'file:///c:/page/script.js',
executionContextId: 2,
parameters: params.map(param => {
return { type: typeof param, value: param }
const remoteObj = { type: typeof param, value: param };
if (param === null) {
remoteObj['subtype'] = 'null';
}
return remoteObj;
})
};

Просмотреть файл

@ -59,6 +59,8 @@ function evalDebugger() {
}
function consoleAPIs() {
console.log({ a: 1, b: 'asdf', c: { d: 4 } });
console.log({ a: 1}, {b: 2});
console.time('timing');
console.group('my group');
console.log('hello', 'world!');
@ -68,7 +70,6 @@ function consoleAPIs() {
console.timeEnd('timing');
console.trace();
console.dir({ a: 1, b: 2 });
(<any>console).table([1, 2, 3]);
console.assert(1 == 2, '1 is not 2');
}

Просмотреть файл

@ -3,6 +3,7 @@
*--------------------------------------------------------*/
import * as url from 'url';
import * as Utilities from './utilities';
export function formatConsoleMessage(m: WebKitProtocol.Console.Message): { text: string, isError: boolean } {
let outputText: string;
@ -23,22 +24,29 @@ export function formatConsoleMessage(m: WebKitProtocol.Console.Message): { text:
}
} else if (m.type === 'endGroup') {
outputText = 'End group'
} else {
// Some types we have to ignore
outputText = 'Unimplemented console API: ' + m.type;
}
return { text: outputText, isError: m.level === 'error' };
}
function resolveParams(m: WebKitProtocol.Console.Message): string {
let text = m.text;
if (!m.parameters || m.parameters.length === 1) {
return text;
if (!m.parameters || !m.parameters.length) {
return m.text;
}
m.parameters.shift(); // The first param is 'text'
const textParam = m.parameters[0];
let text = remoteObjectToString(textParam);
m.parameters.shift();
// Find all %s, %i, etc. Strip %
let formatSpecifiers = text.match(/\%[sidfoOc]/g) || [];
formatSpecifiers = formatSpecifiers.map(spec => spec[1]);
// Find all %s, %i, etc in the first parameter, which is always the main text. Strip %
let formatSpecifiers: string[] = [];
if (textParam.type === 'string') {
formatSpecifiers = textParam.value.match(/\%[sidfoOc]/g) || [];
formatSpecifiers = formatSpecifiers.map(spec => spec[1]);
}
// Append all parameters, formatting properly if there's a format specifier
m.parameters.forEach((param, i) => {
@ -59,13 +67,43 @@ function resolveParams(m: WebKitProtocol.Console.Message): string {
if (formatSpecifiers[i]) {
text = text.replace('%' + formatSpecifiers[i], formatted);
} else {
text += ' ' + param.value;
text += ' ' + remoteObjectToString(param);
}
});
return text;
}
function remoteObjectToString(obj: WebKitProtocol.Runtime.RemoteObject): string {
const result = Utilities.remoteObjectToValue(obj, /*stringify=*/false);
if (result.variableHandleRef) {
// The DebugProtocol console API doesn't support returning a variable reference, so do our best to
// build a useful string out of this object.
if (obj.preview && obj.preview.properties) {
let props: string = obj.preview.properties
.map(prop => {
let propStr = prop.name + ': ';
if (prop.type === 'string') {
propStr += `"${prop.value}"`;
} else {
propStr += prop.value;
}
return propStr;
})
.join(', ');
if (obj.preview.overflow) {
props += '…';
}
return `${obj.className} {${props}}`;
}
} else {
return result.value;
}
}
function stackTraceToString(stackTrace: WebKitProtocol.Console.StackTrace): string {
return stackTrace
.map(frame => `${frame.functionName} @${url.parse(frame.url).pathname}:${frame.lineNumber}`)

Просмотреть файл

@ -39,7 +39,7 @@ export function getPlatform(): Platform {
const platform = os.platform();
return platform === 'darwin' ? Platform.OSX :
platform === 'win32' ? Platform.Windows :
Platform.Linux;
Platform.Linux;
}
/**
@ -69,7 +69,7 @@ export class DebounceHelper {
this.waitToken = null;
fn();
},
this.timeoutMs);
this.timeoutMs);
}
}
@ -162,7 +162,7 @@ export class Logger {
if (this._isServer && Logger.ALLOW_LOGGING) {
if (timestamp) {
const d = new Date();
const timeStamp = `[${d.getMinutes()}:${d.getSeconds()}:${d.getMilliseconds()}]`;
const timeStamp = `[${d.getMinutes() }:${d.getSeconds() }:${d.getMilliseconds() }]`;
console.log(timeStamp + msg);
} else {
console.log(msg);
@ -242,3 +242,41 @@ export function canonicalizeUrl(url: string): string {
return url;
}
export function remoteObjectToValue(object: WebKitProtocol.Runtime.RemoteObject, stringify = true): { value: string, variableHandleRef: string } {
let value = '';
let variableHandleRef: string;
if (object) { // just paranoia?
if (object && object.type === 'object') {
if (object.subtype === 'null') {
value = 'null';
} else {
// If it's a non-null object, create a variable reference so the client can ask for its props
variableHandleRef = object.objectId;
value = object.description;
}
} else if (object && object.type === 'undefined') {
value = 'undefined';
} else if (object.type === 'function') {
const firstBraceIdx = object.description.indexOf('{');
if (firstBraceIdx >= 0) {
value = object.description.substring(0, firstBraceIdx) + '{ … }';
} else {
const firstArrowIdx = object.description.indexOf('=>');
value = firstArrowIdx >= 0 ?
object.description.substring(0, firstArrowIdx + 2) + ' …' :
object.description;
}
} else {
// The value is a primitive value, or something that has a description (not object, primitive, or undefined). And force to be string
if (typeof object.value === 'undefined') {
value = object.description;
} else {
value = stringify ? JSON.stringify(object.value) : object.value;
}
}
}
return { value, variableHandleRef };
}

Просмотреть файл

@ -215,9 +215,11 @@ export class WebKitDebugAdapter implements IDebugAdapter {
private onConsoleMessage(params: WebKitProtocol.Console.MessageAddedParams): void {
const formattedMessage = formatConsoleMessage(params.message);
this.fireEvent(new OutputEvent(
formattedMessage.text + '\n',
formattedMessage.isError ? 'stderr' : 'console'));
if (formattedMessage) {
this.fireEvent(new OutputEvent(
formattedMessage.text + '\n',
formattedMessage.isError ? 'stderr' : 'console'));
}
}
public disconnect(): Promise<void> {
@ -485,38 +487,18 @@ export class WebKitDebugAdapter implements IDebugAdapter {
}
}
/**
* Run the object through Utilities.remoteObjectToValue, and if it returns a variableHandle reference,
* use it with this instance's variableHandles to create a variable handle.
*/
private remoteObjectToValue(object: WebKitProtocol.Runtime.RemoteObject): { value: string, variablesReference: number } {
let value = '';
let variablesReference = 0;
if (object) { // just paranoia?
if (object && object.type === 'object') {
if (object.subtype === 'null') {
value = 'null';
} else {
// If it's a non-null object, create a variable reference so the client can ask for its props
variablesReference = this._variableHandles.create(object.objectId);
value = object.description;
}
} else if (object && object.type === 'undefined') {
value = 'undefined';
} else if (object.type === 'function') {
const firstBraceIdx = object.description.indexOf('{');
if (firstBraceIdx >= 0) {
value = object.description.substring(0, firstBraceIdx) + '{ … }';
} else {
const firstArrowIdx = object.description.indexOf('=>');
value = firstArrowIdx >= 0 ?
object.description.substring(0, firstArrowIdx + 2) + ' …' :
object.description;
}
} else {
// The value is a primitive value, or something that has a description (not object, primitive, or undefined). And force to be string
value = typeof object.value === 'undefined' ? object.description : JSON.stringify(object.value);
}
const { value, variableHandleRef } = Utilities.remoteObjectToValue(object);
const result = { value, variablesReference: 0 };
if (variableHandleRef) {
result.variablesReference = this._variableHandles.create(variableHandleRef);
}
return { value, variablesReference };
return result;
}
}

14
webkit/webKitProtocol.d.ts поставляемый
Просмотреть файл

@ -167,6 +167,20 @@ declare namespace WebKitProtocol {
subtype?: string;
type: string;
value?: any;
preview?: {
type: string;
description: string;
lossless: boolean;
overflow: boolean;
properties: PropertyPreview[];
};
}
interface PropertyPreview {
name: string;
type: string;
subtype?: string;
value: string;
}
interface EvaluateParams {