From 4dfd93c1d7d1fbbaa58676d79adf0cfab3a0ca59 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Thu, 20 Sep 2018 14:23:43 -0700 Subject: [PATCH 1/3] [TS] Wait for handshake response (#2983) --- clients/ts/signalr/src/HandshakeProtocol.ts | 6 +- clients/ts/signalr/src/HubConnection.ts | 13 ++ .../ts/signalr/tests/HubConnection.test.ts | 143 ++++++++++-------- .../tests/HubConnectionBuilder.test.ts | 10 +- .../Protocol/HandshakeProtocol.cs | 2 +- 5 files changed, 105 insertions(+), 69 deletions(-) diff --git a/clients/ts/signalr/src/HandshakeProtocol.ts b/clients/ts/signalr/src/HandshakeProtocol.ts index 2b13b9870a..f5f8b47fc6 100644 --- a/clients/ts/signalr/src/HandshakeProtocol.ts +++ b/clients/ts/signalr/src/HandshakeProtocol.ts @@ -55,7 +55,11 @@ export class HandshakeProtocol { // At this point we should have just the single handshake message const messages = TextMessageFormat.parse(messageData); - responseMessage = JSON.parse(messages[0]); + const response = JSON.parse(messages[0]); + if (response.type) { + throw new Error("Expected a handshake response from the server."); + } + responseMessage = response; // multiple messages could have arrived with handshake // return additional data to be parsed as usual, or null if all parsed diff --git a/clients/ts/signalr/src/HubConnection.ts b/clients/ts/signalr/src/HubConnection.ts index 1810bc6da4..2160f21144 100644 --- a/clients/ts/signalr/src/HubConnection.ts +++ b/clients/ts/signalr/src/HubConnection.ts @@ -31,6 +31,8 @@ export class HubConnection { private id: number; private closedCallbacks: Array<(error?: Error) => void>; private receivedHandshakeResponse: boolean; + private handshakeResolver!: (value?: PromiseLike<{}>) => void; + private handshakeRejecter!: (reason?: any) => void; private connectionState: HubConnectionState; // The type of these a) doesn't matter and b) varies when building in browser and node contexts @@ -106,6 +108,11 @@ export class HubConnection { this.logger.log(LogLevel.Debug, "Starting HubConnection."); this.receivedHandshakeResponse = false; + // Set up the promise before any connection is started otherwise it could race with received messages + const handshakePromise = new Promise((resolve, reject) => { + this.handshakeResolver = resolve; + this.handshakeRejecter = reject; + }); await this.connection.start(this.protocol.transferFormat); @@ -120,6 +127,8 @@ export class HubConnection { this.resetTimeoutPeriod(); this.resetKeepAliveInterval(); + // Wait for the handshake to complete before marking connection as connected + await handshakePromise; this.connectionState = HubConnectionState.Connected; } @@ -388,19 +397,23 @@ export class HubConnection { // We don't want to wait on the stop itself. // tslint:disable-next-line:no-floating-promises this.connection.stop(error); + this.handshakeRejecter(error); throw error; } if (responseMessage.error) { const message = "Server returned handshake error: " + responseMessage.error; this.logger.log(LogLevel.Error, message); + this.handshakeRejecter(message); // We don't want to wait on the stop itself. // tslint:disable-next-line:no-floating-promises this.connection.stop(new Error(message)); + throw new Error(message); } else { this.logger.log(LogLevel.Debug, "Server handshake complete."); } + this.handshakeResolver(); return remainingData; } diff --git a/clients/ts/signalr/tests/HubConnection.test.ts b/clients/ts/signalr/tests/HubConnection.test.ts index cbd0a5fddd..6945b88dde 100644 --- a/clients/ts/signalr/tests/HubConnection.test.ts +++ b/clients/ts/signalr/tests/HubConnection.test.ts @@ -23,7 +23,7 @@ registerUnhandledRejectionHandler(); describe("HubConnection", () => { describe("start", () => { - it("sends negotiation message", async () => { + it("sends handshake message", async () => { await VerifyLogger.run(async (logger) => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); @@ -163,12 +163,16 @@ describe("HubConnection", () => { protocolCalled = true; }; - const connection = new TestConnection(); + const connection = new TestConnection(false); const hubConnection = createHubConnection(connection, logger, mockProtocol); try { + let startCompleted = false; + const startPromise = hubConnection.start().then(() => startCompleted = true); const data = "{}" + TextMessageFormat.RecordSeparator; + expect(startCompleted).toBe(false); connection.receiveText(data); + await startPromise; // message only contained handshake response expect(protocolCalled).toEqual(false); @@ -187,13 +191,18 @@ describe("HubConnection", () => { protocolCalled = true; }; - const connection = new TestConnection(); + const connection = new TestConnection(false); const hubConnection = createHubConnection(connection, logger, mockProtocol); try { + let startCompleted = false; + const startPromise = hubConnection.start().then(() => startCompleted = true); + expect(startCompleted).toBe(false); + // handshake response + message separator const data = [0x7b, 0x7d, 0x1e]; connection.receiveBinary(new Uint8Array(data).buffer); + await startPromise; // message only contained handshake response expect(protocolCalled).toEqual(false); @@ -210,9 +219,13 @@ describe("HubConnection", () => { const mockProtocol = new TestProtocol(TransferFormat.Binary); mockProtocol.onreceive = (d) => receivedProcotolData = d as ArrayBuffer; - const connection = new TestConnection(); + const connection = new TestConnection(false); const hubConnection = createHubConnection(connection, logger, mockProtocol); try { + let startCompleted = false; + const startPromise = hubConnection.start().then(() => startCompleted = true); + expect(startCompleted).toBe(false); + // handshake response + message separator + message pack message const data = [ 0x7b, 0x7d, 0x1e, 0x65, 0x95, 0x03, 0x80, 0xa1, 0x30, 0x01, 0xd9, 0x5d, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6c, @@ -224,6 +237,7 @@ describe("HubConnection", () => { ]; connection.receiveBinary(new Uint8Array(data).buffer); + await startPromise; // left over data is the message pack message expect(receivedProcotolData!.byteLength).toEqual(102); @@ -240,12 +254,17 @@ describe("HubConnection", () => { const mockProtocol = new TestProtocol(TransferFormat.Text); mockProtocol.onreceive = (d) => receivedProcotolData = d as string; - const connection = new TestConnection(); + const connection = new TestConnection(false); const hubConnection = createHubConnection(connection, logger, mockProtocol); try { + let startCompleted = false; + const startPromise = hubConnection.start().then(() => startCompleted = true); + expect(startCompleted).toBe(false); + const data = "{}" + TextMessageFormat.RecordSeparator + "{\"type\":6}" + TextMessageFormat.RecordSeparator; connection.receiveText(data); + await startPromise; expect(receivedProcotolData).toEqual("{\"type\":6}" + TextMessageFormat.RecordSeparator); } finally { @@ -259,7 +278,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const invokePromise = hubConnection.invoke("testMethod", "arg", 42); @@ -277,7 +296,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const invokePromise = hubConnection.invoke("testMethod", "arg", 42); @@ -296,7 +315,7 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); - connection.receiveHandshakeResponse(); + await hubConnection.start(); const invokePromise = hubConnection.invoke("testMethod"); await hubConnection.stop(); @@ -311,7 +330,7 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const invokePromise = hubConnection.invoke("testMethod"); // Typically this would be called by the transport @@ -340,7 +359,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, wrappingLogger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); connection.receive({ arguments: ["test"], @@ -370,7 +389,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, wrappingLogger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const handler = () => { }; hubConnection.on("message", handler); @@ -396,7 +415,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let count = 0; const handler = () => { count++; }; @@ -432,7 +451,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let count = 0; const handler = () => { count++; }; @@ -468,7 +487,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let count = 0; const handler = () => { count++; }; @@ -494,7 +513,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let value = ""; hubConnection.on("message", (v) => value = v); @@ -515,13 +534,22 @@ describe("HubConnection", () => { it("stop on handshake error", async () => { await VerifyLogger.run(async (logger) => { - const connection = new TestConnection(); + const connection = new TestConnection(false); const hubConnection = createHubConnection(connection, logger); try { let closeError: Error | undefined; hubConnection.onclose((e) => closeError = e); - connection.receiveHandshakeResponse("Error!"); + let startCompleted = false; + const startPromise = hubConnection.start().then(() => startCompleted = true); + expect(startCompleted).toBe(false); + try { + connection.receiveHandshakeResponse("Error!"); + } catch { + } + await expect(startPromise) + .rejects + .toThrow("Server returned handshake error: Error!"); expect(closeError!.message).toEqual("Server returned handshake error: Error!"); } finally { @@ -543,7 +571,7 @@ describe("HubConnection", () => { closeError = e; }); - connection.receiveHandshakeResponse(); + await hubConnection.start(); connection.receive({ type: MessageType.Close, @@ -569,7 +597,7 @@ describe("HubConnection", () => { closeError = e; }); - connection.receiveHandshakeResponse(); + await hubConnection.start(); connection.receive({ error: "Error!", @@ -589,7 +617,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let numInvocations1 = 0; let numInvocations2 = 0; @@ -616,7 +644,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); let numInvocations = 0; const callback = () => numInvocations++; @@ -674,7 +702,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, wrappingLogger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); hubConnection.on(null!, undefined!); hubConnection.on(undefined!, null!); @@ -714,11 +742,13 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); + hubConnection.stream("testStream", "arg", 42); - // Verify the message is sent - expect(connection.sentData.length).toBe(1); - expect(JSON.parse(connection.sentData[0])).toEqual({ + // Verify the message is sent (+ handshake) + expect(connection.sentData.length).toBe(2); + expect(JSON.parse(connection.sentData[1])).toEqual({ arguments: [ "arg", 42, @@ -741,7 +771,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const observer = new TestObserver(); hubConnection.stream("testMethod", "arg", 42) @@ -761,7 +791,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const observer = new TestObserver(); hubConnection.stream("testMethod", "arg", 42) @@ -782,6 +812,8 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); + const observer = new TestObserver(); hubConnection.stream("testMethod") .subscribe(observer); @@ -800,6 +832,8 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); + const observer = new TestObserver(); hubConnection.stream("testMethod") .subscribe(observer); @@ -819,7 +853,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const observer = new TestObserver(); hubConnection.stream("testMethod") @@ -848,6 +882,7 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); hubConnection.stream("testMethod").subscribe(NullSubscriber.instance); // Typically this would be called by the transport @@ -865,6 +900,7 @@ describe("HubConnection", () => { const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); hubConnection.stream("testMethod").subscribe(NullSubscriber.instance); // Send completion to trigger observer.complete() @@ -881,7 +917,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { - connection.receiveHandshakeResponse(); + await hubConnection.start(); const observer = new TestObserver(); const subscription = hubConnection.stream("testMethod") @@ -896,9 +932,9 @@ describe("HubConnection", () => { // Observer should no longer receive messages expect(observer.itemsReceived).toEqual([1]); - // Verify the cancel is sent - expect(connection.sentData.length).toBe(2); - expect(JSON.parse(connection.sentData[1])).toEqual({ + // Verify the cancel is sent (+ handshake) + expect(connection.sentData.length).toBe(3); + expect(JSON.parse(connection.sentData[2])).toEqual({ invocationId: connection.lastInvocationId, type: MessageType.CancelInvocation, }); @@ -986,6 +1022,7 @@ describe("HubConnection", () => { const connection = new TestConnection(); const hubConnection = createHubConnection(connection, logger); try { + await hubConnection.start(); const invokePromise = hubConnection.invoke("testMethod", "arg", 42); connection.receive({ type: MessageType.Ping }); @@ -1025,37 +1062,6 @@ describe("HubConnection", () => { }); }); - it("does not timeout if message was received before HubConnection.start", async () => { - await VerifyLogger.run(async (logger) => { - const connection = new TestConnection(); - const hubConnection = createHubConnection(connection, logger); - try { - hubConnection.serverTimeoutInMilliseconds = 200; - - const p = new PromiseSource(); - hubConnection.onclose((e) => p.resolve(e)); - - // send message before start to trigger timeout handler - // testing for regression where we didn't cleanup timer if request received before start created a timer - await connection.receive({ type: MessageType.Ping }); - - await hubConnection.start(); - - for (let i = 0; i < 6; i++) { - await pingAndWait(connection); - } - - await connection.stop(); - - const error = await p.promise; - - expect(error).toBeUndefined(); - } finally { - await hubConnection.stop(); - } - }); - }); - it("terminates if no messages received within timeout interval", async () => { await VerifyLogger.run(async (logger) => { const connection = new TestConnection(); @@ -1092,11 +1098,14 @@ class TestConnection implements IConnection { public sentData: any[]; public lastInvocationId: string | null; - constructor() { + private autoHandshake: boolean | null; + + constructor(autoHandshake: boolean = true) { this.onreceive = null; this.onclose = null; this.sentData = []; this.lastInvocationId = null; + this.autoHandshake = autoHandshake; } public start(): Promise { @@ -1105,7 +1114,11 @@ class TestConnection implements IConnection { public send(data: any): Promise { const invocation = TextMessageFormat.parse(data)[0]; - const invocationId = JSON.parse(invocation).invocationId; + const parsedInvocation = JSON.parse(invocation); + const invocationId = parsedInvocation.invocationId; + if (parsedInvocation.protocol && parsedInvocation.version && this.autoHandshake) { + this.receiveHandshakeResponse(); + } if (invocationId) { this.lastInvocationId = invocationId; } diff --git a/clients/ts/signalr/tests/HubConnectionBuilder.test.ts b/clients/ts/signalr/tests/HubConnectionBuilder.test.ts index 293c896a54..d2361fa41a 100644 --- a/clients/ts/signalr/tests/HubConnectionBuilder.test.ts +++ b/clients/ts/signalr/tests/HubConnectionBuilder.test.ts @@ -65,7 +65,10 @@ describe("HubConnectionBuilder", () => { // Start the connection const closed = makeClosedPromise(connection); - await connection.start(); + + // start waits for handshake before returning, we don't care in this test + // tslint:disable-next-line:no-floating-promises + connection.start(); const pollRequest = await pollSent.promise; expect(pollRequest.url).toMatch(/http:\/\/example.com\?id=abc123.*/); @@ -109,7 +112,10 @@ describe("HubConnectionBuilder", () => { // Start the connection const closed = makeClosedPromise(connection); - await connection.start(); + + // start waits for handshake before returning, we don't care in this test + // tslint:disable-next-line:no-floating-promises + connection.start(); const negotiateRequest = await negotiateReceived.promise; expect(negotiateRequest.content).toBe(`{"protocol":"${protocol.name}","version":1}\x1E`); diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs index 3c5294f286..d0c8260a9e 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Protocol/HandshakeProtocol.cs @@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol case TypePropertyName: // a handshake response does not have a type // check the incoming message was not any other type of message - throw new InvalidDataException("Handshake response should not have a 'type' value."); + throw new InvalidDataException("Expected a handshake response from the server."); case ErrorPropertyName: error = JsonUtils.ReadAsString(reader, ErrorPropertyName); break; From ef3d3b1cddebf43e6f8bbfc81519a11356d2095a Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Fri, 21 Sep 2018 08:58:54 -0700 Subject: [PATCH 2/3] [TS] Change websocket library in Node (#2989) --- clients/ts/FunctionalTests/package-lock.json | 118 ++++++++---------- clients/ts/FunctionalTests/package.json | 2 +- .../ts/FunctionalTests/ts/WebSocketTests.ts | 7 +- .../package-lock.json | 2 +- .../src/MessagePackHubProtocol.ts | 3 +- .../ts/signalr-protocol-msgpack/src/Utils.ts | 11 ++ clients/ts/signalr/package-lock.json | 70 ++--------- clients/ts/signalr/package.json | 4 +- clients/ts/signalr/src/HandshakeProtocol.ts | 3 +- clients/ts/signalr/src/HttpConnection.ts | 7 +- clients/ts/signalr/src/NodeHttpClient.ts | 3 +- clients/ts/signalr/src/Utils.ts | 13 +- clients/ts/webpack.config.base.js | 1 - 13 files changed, 99 insertions(+), 145 deletions(-) create mode 100644 clients/ts/signalr-protocol-msgpack/src/Utils.ts diff --git a/clients/ts/FunctionalTests/package-lock.json b/clients/ts/FunctionalTests/package-lock.json index 06c313f807..289832d60b 100644 --- a/clients/ts/FunctionalTests/package-lock.json +++ b/clients/ts/FunctionalTests/package-lock.json @@ -8,9 +8,13 @@ "version": "file:../signalr", "requires": { "eventsource": "^1.0.7", - "websocket": "^1.0.26" + "ws": "^6.0.0" }, "dependencies": { + "async-limiter": { + "version": "1.0.0", + "bundled": true + }, "debug": { "version": "2.6.9", "bundled": true, @@ -85,6 +89,13 @@ "yaeti": "^0.0.6" } }, + "ws": { + "version": "6.0.0", + "bundled": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, "yaeti": { "version": "0.0.6", "bundled": true @@ -1086,6 +1097,19 @@ "debug": "~3.1.0", "engine.io-parser": "~2.1.0", "ws": "~3.3.1" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } } }, "engine.io-client": { @@ -1105,6 +1129,19 @@ "ws": "~3.3.1", "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } } }, "engine.io-parser": { @@ -1523,14 +1560,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1545,20 +1580,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -1675,8 +1707,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -1688,7 +1719,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1703,7 +1733,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1711,14 +1740,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -1737,7 +1764,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -1818,8 +1844,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -1831,7 +1856,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -1953,7 +1977,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2799,7 +2822,8 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -3710,15 +3734,6 @@ "mime-types": "~2.1.18" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typescript": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz", @@ -4018,29 +4033,6 @@ } } }, - "websocket": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz", - "integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4063,14 +4055,12 @@ "dev": true }, "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", + "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "async-limiter": "~1.0.0" } }, "xmlbuilder": { @@ -4091,12 +4081,6 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true - }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/clients/ts/FunctionalTests/package.json b/clients/ts/FunctionalTests/package.json index a483ed4cc3..4e4254da95 100644 --- a/clients/ts/FunctionalTests/package.json +++ b/clients/ts/FunctionalTests/package.json @@ -32,7 +32,7 @@ "karma-summary-reporter": "^1.5.0", "ts-node": "^4.1.0", "typescript": "^3.0.1", - "websocket": " ^1.0.26" + "ws": " ^6.0.0" }, "scripts": { "clean": "node ../common/node_modules/rimraf/bin.js ./wwwroot/dist ./obj/js", diff --git a/clients/ts/FunctionalTests/ts/WebSocketTests.ts b/clients/ts/FunctionalTests/ts/WebSocketTests.ts index 152e64b8cb..26b5e9c3f8 100644 --- a/clients/ts/FunctionalTests/ts/WebSocketTests.ts +++ b/clients/ts/FunctionalTests/ts/WebSocketTests.ts @@ -20,10 +20,9 @@ describe("WebSockets", () => { return; } } else { - const websocketModule = require("websocket"); - const hasWebsocket = websocketModule && websocketModule.w3cwebsocket; - if (hasWebsocket) { - webSocket = new websocketModule.w3cwebsocket(ECHOENDPOINT_URL.replace(/^http/, "ws")); + const websocketModule = require("ws"); + if (websocketModule) { + webSocket = new websocketModule(ECHOENDPOINT_URL.replace(/^http/, "ws")); } else { // No WebSockets implementations in current environment, skip test done(); diff --git a/clients/ts/signalr-protocol-msgpack/package-lock.json b/clients/ts/signalr-protocol-msgpack/package-lock.json index db929db8fd..d18074493a 100644 --- a/clients/ts/signalr-protocol-msgpack/package-lock.json +++ b/clients/ts/signalr-protocol-msgpack/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aspnet/signalr-protocol-msgpack", - "version": "1.1.0-preview2-t000", + "version": "1.1.0-preview3-t000", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts b/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts index de51e54daf..38564d14fb 100644 --- a/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts +++ b/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts @@ -7,6 +7,7 @@ import * as msgpack5 from "msgpack5"; import { CompletionMessage, HubMessage, IHubProtocol, ILogger, InvocationMessage, LogLevel, MessageHeaders, MessageType, NullLogger, StreamInvocationMessage, StreamItemMessage, TransferFormat } from "@aspnet/signalr"; import { BinaryMessageFormat } from "./BinaryMessageFormat"; +import { isArrayBuffer } from "./Utils"; // TypeDoc's @inheritDoc and @link don't work across modules :( @@ -31,7 +32,7 @@ export class MessagePackHubProtocol implements IHubProtocol { */ public parseMessages(input: ArrayBuffer | Buffer, logger: ILogger): HubMessage[] { // The interface does allow "string" to be passed in, but this implementation does not. So let's throw a useful error. - if (!(input instanceof ArrayBuffer) && !(input instanceof Buffer)) { + if (!(input instanceof Buffer) && !(isArrayBuffer(input))) { throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer."); } diff --git a/clients/ts/signalr-protocol-msgpack/src/Utils.ts b/clients/ts/signalr-protocol-msgpack/src/Utils.ts new file mode 100644 index 0000000000..f0994cf0b3 --- /dev/null +++ b/clients/ts/signalr-protocol-msgpack/src/Utils.ts @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +// Copied from signalr/Utils.ts +/** @private */ +export function isArrayBuffer(val: any): val is ArrayBuffer { + return val && typeof ArrayBuffer !== "undefined" && + (val instanceof ArrayBuffer || + // Sometimes we get an ArrayBuffer that doesn't satisfy instanceof + (val.constructor && val.constructor.name === "ArrayBuffer")); +} diff --git a/clients/ts/signalr/package-lock.json b/clients/ts/signalr/package-lock.json index 032046031d..b374782b01 100644 --- a/clients/ts/signalr/package-lock.json +++ b/clients/ts/signalr/package-lock.json @@ -1,15 +1,9 @@ { "name": "@aspnet/signalr", - "version": "1.1.0-preview2-t000", + "version": "1.1.0-preview3-t000", "lockfileVersion": 1, "requires": true, "dependencies": { - "@types/events": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", - "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", - "dev": true - }, "@types/eventsource": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.0.2.tgz", @@ -22,23 +16,10 @@ "integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==", "dev": true }, - "@types/websocket": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-0.0.40.tgz", - "integrity": "sha512-ldteZwWIgl9cOy7FyvYn+39Ah4+PfpVE72eYKw75iy2L0zTbhbcwvzeJ5IOu6DQP93bjfXq0NGHY6FYtmYoqFQ==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/node": "*" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "es6-promise": { "version": "4.2.2", @@ -54,21 +35,6 @@ "original": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", - "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==" - }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -87,14 +53,6 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, "url-parse": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", @@ -104,21 +62,13 @@ "requires-port": "^1.0.0" } }, - "websocket": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.26.tgz", - "integrity": "sha512-fjcrYDPIQxpTnqFQ9JjxUQcdvR89MFAOjPBlF+vjOt49w/XW4fJknUoMz/mDIn2eK1AdslVojcaOxOqyZZV8rw==", + "ws": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", + "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", "requires": { - "debug": "^2.2.0", - "nan": "^2.3.3", - "typedarray-to-buffer": "^3.1.2", - "yaeti": "^0.0.6" + "async-limiter": "~1.0.0" } - }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" } } } diff --git a/clients/ts/signalr/package.json b/clients/ts/signalr/package.json index 3f3e272028..b0f1e562e0 100644 --- a/clients/ts/signalr/package.json +++ b/clients/ts/signalr/package.json @@ -37,11 +37,11 @@ ], "devDependencies": { "es6-promise": "^4.2.2", - "@types/websocket": "^0.0.40", + "@types/node": "^10.9.4", "@types/eventsource": "^1.0.2" }, "dependencies": { - "websocket": "^1.0.26", + "ws": "^6.0.0", "eventsource": "^1.0.7" } } diff --git a/clients/ts/signalr/src/HandshakeProtocol.ts b/clients/ts/signalr/src/HandshakeProtocol.ts index f5f8b47fc6..af4bf7ca52 100644 --- a/clients/ts/signalr/src/HandshakeProtocol.ts +++ b/clients/ts/signalr/src/HandshakeProtocol.ts @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. import { TextMessageFormat } from "./TextMessageFormat"; +import { isArrayBuffer } from "./Utils"; /** @private */ export interface HandshakeRequestMessage { @@ -26,7 +27,7 @@ export class HandshakeProtocol { let messageData: string; let remainingData: any; - if (data instanceof ArrayBuffer || (typeof Buffer !== "undefined" && data instanceof Buffer)) { + if (isArrayBuffer(data) || (typeof Buffer !== "undefined" && data instanceof Buffer)) { // Format is binary but still need to read JSON text from handshake response const binaryData = new Uint8Array(data); const separatorIndex = binaryData.indexOf(TextMessageFormat.RecordSeparatorCode); diff --git a/clients/ts/signalr/src/HttpConnection.ts b/clients/ts/signalr/src/HttpConnection.ts index 99a013c2e4..1dbe24b846 100644 --- a/clients/ts/signalr/src/HttpConnection.ts +++ b/clients/ts/signalr/src/HttpConnection.ts @@ -39,7 +39,7 @@ let WebSocketModule: any = null; let EventSourceModule: any = null; if (typeof window === "undefined" && typeof require !== "undefined") { // tslint:disable-next-line:no-var-requires - WebSocketModule = require("websocket"); + WebSocketModule = require("ws"); // tslint:disable-next-line:no-var-requires EventSourceModule = require("eventsource"); } @@ -73,9 +73,8 @@ export class HttpConnection implements IConnection { if (!isNode && typeof WebSocket !== "undefined" && !options.WebSocket) { options.WebSocket = WebSocket; } else if (isNode && !options.WebSocket) { - const websocket = WebSocketModule && WebSocketModule.w3cwebsocket; - if (websocket) { - options.WebSocket = WebSocketModule.w3cwebsocket; + if (WebSocketModule) { + options.WebSocket = WebSocketModule; } } diff --git a/clients/ts/signalr/src/NodeHttpClient.ts b/clients/ts/signalr/src/NodeHttpClient.ts index 557f037192..3412085dc8 100644 --- a/clients/ts/signalr/src/NodeHttpClient.ts +++ b/clients/ts/signalr/src/NodeHttpClient.ts @@ -7,6 +7,7 @@ import { URL } from "url"; import { AbortError, HttpError, TimeoutError } from "./Errors"; import { HttpClient, HttpRequest, HttpResponse } from "./HttpClient"; import { ILogger, LogLevel } from "./ILogger"; +import { isArrayBuffer } from "./Utils"; export class NodeHttpClient extends HttpClient { private readonly logger: ILogger; @@ -80,7 +81,7 @@ export class NodeHttpClient extends HttpClient { reject(e); }); - if (request.content instanceof ArrayBuffer) { + if (isArrayBuffer(request.content)) { req.write(Buffer.from(request.content)); } else { req.write(request.content || ""); diff --git a/clients/ts/signalr/src/Utils.ts b/clients/ts/signalr/src/Utils.ts index 2099811678..159219d613 100644 --- a/clients/ts/signalr/src/Utils.ts +++ b/clients/ts/signalr/src/Utils.ts @@ -25,7 +25,7 @@ export class Arg { /** @private */ export function getDataDetail(data: any, includeContent: boolean): string { let detail = ""; - if (data instanceof ArrayBuffer) { + if (isArrayBuffer(data)) { detail = `Binary data of length ${data.byteLength}`; if (includeContent) { detail += `. Content: '${formatArrayBuffer(data)}'`; @@ -54,6 +54,15 @@ export function formatArrayBuffer(data: ArrayBuffer): string { return str.substr(0, str.length - 1); } +// Also in signalr-protocol-msgpack/Utils.ts +/** @private */ +export function isArrayBuffer(val: any): val is ArrayBuffer { + return val && typeof ArrayBuffer !== "undefined" && + (val instanceof ArrayBuffer || + // Sometimes we get an ArrayBuffer that doesn't satisfy instanceof + (val.constructor && val.constructor.name === "ArrayBuffer")); +} + /** @private */ export async function sendMessage(logger: ILogger, transportName: string, httpClient: HttpClient, url: string, accessTokenFactory: (() => string | Promise) | undefined, content: string | ArrayBuffer, logMessageContent: boolean): Promise { let headers; @@ -68,7 +77,7 @@ export async function sendMessage(logger: ILogger, transportName: string, httpCl logger.log(LogLevel.Trace, `(${transportName} transport) sending data. ${getDataDetail(content, logMessageContent)}.`); - const responseType = content instanceof ArrayBuffer ? "arraybuffer" : "text"; + const responseType = isArrayBuffer(content) ? "arraybuffer" : "text"; const response = await httpClient.post(url, { content, headers, diff --git a/clients/ts/webpack.config.base.js b/clients/ts/webpack.config.base.js index 43f3d5f633..6779afc2ff 100644 --- a/clients/ts/webpack.config.base.js +++ b/clients/ts/webpack.config.base.js @@ -74,7 +74,6 @@ module.exports = function (modulePath, browserBaseName, options) { new webpack.IgnorePlugin(/vertx/), new webpack.IgnorePlugin(/NodeHttpClient/), new webpack.IgnorePlugin(/eventsource/), - new webpack.IgnorePlugin(/websocket/), ], externals: options.externals, }; From e5470d923914debf706be9a2739d250904ac69fb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 19:31:13 +0000 Subject: [PATCH 3/3] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 98 ++++++++++++++++++++-------------------- korebuild-lock.txt | 4 +- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 11bca983ea..f925ccecaa 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,57 +5,57 @@ 0.10.13 3.1.0 - 2.2.0-preview3-35252 - 2.2.0-preview1-20180911.1 + 2.2.0-preview3-35301 + 2.2.0-preview1-20180918.1 1.7.3.4 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 4.5.0 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 2.2.0-preview2-26905-02 15.6.1 4.7.49 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1090ad6a92..8491de70e6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180911.1 -commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 +version:2.2.0-preview1-20180918.1 +commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800