diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index b28460f743e..cf0f5aef4a4 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -4,119 +4,43 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import objects = require('vs/base/common/objects'); -import types = require('vs/base/common/types'); - -export interface IMarshallingContribution { - - canSerialize(obj:any): boolean; - - serialize(obj:any, serialize:(obj:any)=>any): any; - - canDeserialize(obj:any): boolean; - - deserialize(obj:any, deserialize:(obj:any)=>any): any; +import URI from 'vs/base/common/uri'; +export function stringify(obj: any): string { + return JSON.stringify(obj, replacer); } -var marshallingContributions:IMarshallingContribution[] = []; - -export function registerMarshallingContribution(contribution:IMarshallingContribution): void { - marshallingContributions.push(contribution); +export function parse(text: string): any { + return JSON.parse(text, reviver) } -export function canSerialize(obj: any): boolean { - for (let contrib of marshallingContributions) { - if (contrib.canSerialize(obj)) { - return true; - } - } +interface MarshalledObject { + $mid: number; } -export function serialize(obj:any): any { - return objects.cloneAndChange(obj, (orig:any) => { - if (typeof orig === 'object') { - for (var i = 0; i < marshallingContributions.length; i++) { - var contrib = marshallingContributions[i]; - if (contrib.canSerialize(orig)) { - return contrib.serialize(orig, serialize); - } - } - } - return undefined; - }); -} - -export function deserialize(obj:any): any { - return objects.cloneAndChange(obj, (orig:any) => { - if (types.isObject(orig)) { - for (var i = 0; i < marshallingContributions.length; i++) { - var contrib = marshallingContributions[i]; - if (contrib.canDeserialize(orig)) { - return contrib.deserialize(orig, deserialize); - } - } - } - return undefined; - }); -} - -// RegExp marshaller - -interface ISerializedRegExp { - $isRegExp: boolean; - source: string; - flags: string; -} - -registerMarshallingContribution({ - - canSerialize: (obj:any): boolean => { - return obj instanceof RegExp; - }, - - serialize: (regex:RegExp, serialize:(obj:any)=>any): ISerializedRegExp => { - var flags = ''; - - if (regex.global) { - flags += 'g'; - } else if (regex.ignoreCase) { - flags += 'i'; - } else if (regex.multiline) { - flags += 'm'; - } - +function replacer(key: string, value: any): any { + // URI is done via toJSON-member + if (value instanceof RegExp) { return { - $isRegExp: true, - source: regex.source, - flags: flags - }; - }, - - canDeserialize: (obj:ISerializedRegExp): boolean => { - return obj.$isRegExp; - }, - - deserialize: (obj:ISerializedRegExp, deserialize:(obj:any)=>any): any => { - return new RegExp(obj.source, obj.flags); + $mid: 2, + source: (value).source, + flags: ((value).global ? 'g' : '') + ((value).ignoreCase ? 'i' : '') + ((value).multiline ? 'm' : ''), + } } - -}); - - - -export function marshallObject(obj: any): string { - return serialize(obj); + return value; } -export function marshallObjectAndStringify(obj: any): string { - return JSON.stringify(marshallObject(obj)); -} -export function demarshallObject(data: any) { - return deserialize(data); +function reviver(key: string, value: any): any { + let marshallingConst: number; + if (value !== void 0 && value !== null) { + marshallingConst = (value).$mid; + } + if (marshallingConst === 1) { + return URI.revive(value); + } else if (marshallingConst === 2) { + return new RegExp(value.source, value.flags); + } else { + return value; + } } - -export function parseAndDemarshallObject(serialized: string): any { - return demarshallObject(JSON.parse(serialized)); -} \ No newline at end of file diff --git a/src/vs/base/common/remote.ts b/src/vs/base/common/remote.ts index 83257ef42ca..7824a05868a 100644 --- a/src/vs/base/common/remote.ts +++ b/src/vs/base/common/remote.ts @@ -5,7 +5,6 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {IMarshallingContribution} from 'vs/base/common/marshalling'; export interface IManyHandler { handle(rpcId:string, method:string, args:any[]): any; diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 88fdc54b34d..6aa41d3d165 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import marshalling = require('vs/base/common/marshalling'); import platform = require('vs/base/common/platform'); // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent @@ -292,12 +291,12 @@ export default class URI { fsPath: this.fsPath, query: this.query, fragment: this.fragment.replace(/URL_MARSHAL_REMOVE.*$/, ''), // TODO@Alex: implement derived resources (embedded mirror models) better - formatted: this.toString().replace(/#?URL_MARSHAL_REMOVE.*$/, ''), // TODO@Alex: implement derived resources (embedded mirror models) better - $isURI: true, + external: this.toString().replace(/#?URL_MARSHAL_REMOVE.*$/, ''), // TODO@Alex: implement derived resources (embedded mirror models) better + $mid: 1 }; } - static _fromSerialized(data: any): URI { + static revive(data: any): URI { let result = new URI(); result._scheme = (<_ISerializedURI> data).scheme; result._authority = (<_ISerializedURI> data).authority; @@ -305,39 +304,19 @@ export default class URI { result._query = (<_ISerializedURI> data).query; result._fragment = (<_ISerializedURI> data).fragment; result._fsPath = (<_ISerializedURI> data).fsPath; - result._formatted = (<_ISerializedURI>data).formatted; + result._formatted = (<_ISerializedURI>data).external; URI._validate(result); return result; } } interface _ISerializedURI { - $isURI: boolean; - + $mid: number; scheme: string; authority: string; path: string; fsPath: string; query: string; fragment: string; - formatted: string; + external: string; } - -marshalling.registerMarshallingContribution({ - - canSerialize: (obj:any): boolean => { - return obj instanceof URI; - }, - - serialize: (url: URI, serialize: (obj: any) => any): _ISerializedURI => { - return url.toJSON(); - }, - - canDeserialize: (obj:_ISerializedURI): boolean => { - return obj.$isURI; - }, - - deserialize: (obj:_ISerializedURI, deserialize:(obj:any)=>any): any => { - return URI._fromSerialized(obj); - } -}); diff --git a/src/vs/base/common/worker/workerClient.ts b/src/vs/base/common/worker/workerClient.ts index 66925733cc6..a78ce41ec30 100644 --- a/src/vs/base/common/worker/workerClient.ts +++ b/src/vs/base/common/worker/workerClient.ts @@ -252,13 +252,13 @@ export class WorkerClient { } private _postMessage(msg:any): void { - this._worker.postMessage(marshalling.marshallObjectAndStringify(msg)); + this._worker.postMessage(marshalling.stringify(msg)); } private _onSerializedMessage(msg:string): void { var message:protocol.IServerMessage = null; try { - message = marshalling.parseAndDemarshallObject(msg); + message = marshalling.parse(msg); } catch (e) { // nothing } diff --git a/src/vs/base/common/worker/workerServer.ts b/src/vs/base/common/worker/workerServer.ts index 8433bfc9be5..de3592c9c39 100644 --- a/src/vs/base/common/worker/workerServer.ts +++ b/src/vs/base/common/worker/workerServer.ts @@ -120,11 +120,11 @@ export class WorkerServer { } public onmessage(msg:string): void { - this._onmessage(marshalling.parseAndDemarshallObject(msg)); + this._onmessage(marshalling.parse(msg)); } private _postMessage(msg:protocol.IServerMessage): void { - this._postSerializedMessage(marshalling.marshallObjectAndStringify(msg)); + this._postSerializedMessage(marshalling.stringify(msg)); } private _onmessage(msg:protocol.IClientMessage): void { diff --git a/src/vs/base/test/common/network.test.ts b/src/vs/base/test/common/network.test.ts index 49628900d92..8bbb8dbb3e4 100644 --- a/src/vs/base/test/common/network.test.ts +++ b/src/vs/base/test/common/network.test.ts @@ -7,7 +7,6 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; import { URL, ParsedUrl } from 'vs/base/common/network'; -import { serialize, deserialize } from 'vs/base/common/marshalling'; function assertUrl(raw:string, scheme:string, domain:string, port:string, path:string, queryString:string, fragmentId:string): void { var url = new ParsedUrl(raw); @@ -218,8 +217,4 @@ suite('Network', () => { assert.equal(url.toUnique(), 'inmemory://model/1'); }); - test('Bug 16793:# in folder name => mirror models get out of sync', function () { - var uri = URI.parse('file:///C:/model/1#css'); - assert.equal(deserialize(serialize(uri)).toString(), uri.toString()); - }); }); diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 2ac7abb4c44..838ef94848e 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import { serialize, deserialize } from 'vs/base/common/marshalling'; +import { parse, stringify } from 'vs/base/common/marshalling'; import { normalize } from 'vs/base/common/paths'; suite('URI', () => { @@ -133,7 +133,7 @@ suite('URI', () => { test('Bug 16793:# in folder name => mirror models get out of sync', () => { var uri1 = URI.file('C:\\C#\\file.txt'); - assert.equal(deserialize(serialize(uri1.toString())), uri1.toString()); + assert.equal(parse(stringify(uri1)).toString(), uri1.toString()); }); test('URI#parse', () => { @@ -353,7 +353,7 @@ suite('URI', () => { // while (c-- > 0) { for(let value of values) { let data = value.toJSON(); - let clone = URI._fromSerialized(data); + let clone = URI.revive(data); assert.equal(clone.scheme, value.scheme); assert.equal(clone.authority, value.authority); diff --git a/src/vs/platform/plugins/common/ipcRemoteCom.ts b/src/vs/platform/plugins/common/ipcRemoteCom.ts index 34835eee868..9ab7fbb4066 100644 --- a/src/vs/platform/plugins/common/ipcRemoteCom.ts +++ b/src/vs/platform/plugins/common/ipcRemoteCom.ts @@ -68,7 +68,7 @@ export function create(send: (obj: string) => void): IPluginsIPC { bigHandler = _bigHandler; }, handle: (rawmsg) => { - var msg = marshalling.demarshallObject(rawmsg); + var msg = marshalling.parse(rawmsg); if (msg.seq) { if (!pendingRPCReplies.hasOwnProperty(msg.seq)) { @@ -133,7 +133,7 @@ export function create(send: (obj: string) => void): IPluginsIPC { }; function marshallAndSend(msg:any): void { - send(marshalling.marshallObject(msg)); + send(marshalling.stringify(msg)); } function invokeHandler(rpcId:string, method:string, args:any[]): winjs.TPromise { diff --git a/src/vs/workbench/node/pluginHostMain.ts b/src/vs/workbench/node/pluginHostMain.ts index 093700726e7..c40c137f897 100644 --- a/src/vs/workbench/node/pluginHostMain.ts +++ b/src/vs/workbench/node/pluginHostMain.ts @@ -25,7 +25,6 @@ import {IInstantiationService } from 'vs/platform/instantiation/common/instantia import InstantiationService = require('vs/platform/instantiation/common/instantiationService'); import {PluginHostPluginService} from 'vs/platform/plugins/common/nativePluginService'; import {PluginHostThreadService} from 'vs/platform/thread/common/pluginHostThreadService'; -import marshalling = require('vs/base/common/marshalling'); import {ExtHostTelemetryService} from 'vs/workbench/api/node/extHostTelemetry'; import {BaseRequestService} from 'vs/platform/request/common/baseRequestService'; import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService'; @@ -59,9 +58,7 @@ export function exit(code?: number) { } export function createServices(remoteCom: IPluginsIPC, initData: IInitData, sharedProcessClient: Client): IInstantiationService { - // the init data is not demarshalled - initData = marshalling.deserialize(initData); - + let contextService = new BaseWorkspaceContextService(initData.contextService.workspace, initData.contextService.configuration, initData.contextService.options); let threadService = new PluginHostThreadService(remoteCom); threadService.setInstantiationService(InstantiationService.create({ threadService: threadService })); diff --git a/src/vs/workbench/node/pluginHostProcess.ts b/src/vs/workbench/node/pluginHostProcess.ts index fd953078f68..3bc4b2ec1ce 100644 --- a/src/vs/workbench/node/pluginHostProcess.ts +++ b/src/vs/workbench/node/pluginHostProcess.ts @@ -10,6 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { PluginHostMain, createServices, IInitData, exit } from 'vs/workbench/node/pluginHostMain'; import { Client, connect } from 'vs/base/node/service.net'; import { create as createIPC, IPluginsIPC } from 'vs/platform/plugins/common/ipcRemoteCom'; +import marshalling = require('vs/base/common/marshalling'); interface IRendererConnection { remoteCom: IPluginsIPC; @@ -27,7 +28,10 @@ function connectToRenderer(): TPromise { const stats: number[] = []; // Listen init data message - process.once('message', msg => { + process.once('message', raw => { + + let msg = marshalling.parse(raw); + const remoteCom = createIPC(data => { process.send(data); stats.push(data.length); diff --git a/src/vs/workbench/services/thread/electron-browser/threadService.ts b/src/vs/workbench/services/thread/electron-browser/threadService.ts index 291b6b8c752..3ab2ea33cad 100644 --- a/src/vs/workbench/services/thread/electron-browser/threadService.ts +++ b/src/vs/workbench/services/thread/electron-browser/threadService.ts @@ -162,7 +162,7 @@ class PluginHostProcessManager { window.clearTimeout(this.initializeTimer); } - let initPayload = marshalling.serialize({ + let initPayload = marshalling.stringify({ parentPid: process.pid, contextService: { workspace: this.contextService.getWorkspace(), diff --git a/src/vs/workbench/test/node/api/extHostTypes.test.ts b/src/vs/workbench/test/node/api/extHostTypes.test.ts index 7ec97b178db..52ec8552854 100644 --- a/src/vs/workbench/test/node/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/node/api/extHostTypes.test.ts @@ -22,14 +22,14 @@ suite('ExtHostTypes', function() { let uri = URI.parse('file:///path/test.file'); let data = uri.toJSON(); assert.deepEqual(data, { - $isURI: true, + $mid: 1, scheme: 'file', authority: '', path: '/path/test.file', fsPath: '/path/test.file', query: '', fragment: '', - formatted: 'file:///path/test.file' + external: 'file:///path/test.file' }); });