Skip to content

Commit 76c330c

Browse files
author
Benjamin Pasero
committed
electron 5 - bootstrap a nodeless configuration (microsoft#68302)
1 parent 65ede5e commit 76c330c

55 files changed

Lines changed: 3638 additions & 971 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/tsconfig.strictNullChecks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,10 @@
406406
"./vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts",
407407
"./vs/workbench/services/extensions/electron-browser/extensionHost.ts",
408408
"./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts",
409+
"./vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts",
409410
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
410411
"./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts",
411412
"./vs/workbench/services/extensions/node/extensionHostProtocol.ts",
412-
"./vs/workbench/services/extensions/node/extensionManagementServerService.ts",
413413
"./vs/workbench/services/extensions/node/extensionPoints.ts",
414414
"./vs/workbench/services/extensions/node/lazyPromise.ts",
415415
"./vs/workbench/services/extensions/node/proxyIdentifier.ts",

src/vs/base/common/hash.ts

Lines changed: 344 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { isString } from 'vs/base/common/types';
7+
68
/**
79
* Return a hash value for an object.
810
*/
@@ -69,4 +71,345 @@ export class Hasher {
6971
this._value = hash(obj, this._value);
7072
return this._value;
7173
}
72-
}
74+
}
75+
76+
//#region SHA1
77+
78+
export function computeSHA1Hash(value: string): string {
79+
const data = encodeToArrayBuffer(value);
80+
const hash = new SHA1();
81+
82+
if (data.byteLength) {
83+
hash.update(data);
84+
}
85+
86+
return hash.digest();
87+
}
88+
89+
class SHA1 {
90+
91+
// Reference: http://en.wikipedia.org/wiki/SHA-1
92+
93+
private static BLOCK_SIZE = 64; // 512 / 8
94+
95+
private length: number;
96+
private buffer: Uint8Array | null;
97+
private bufferDV: DataView | null;
98+
private bufferLength: number;
99+
100+
private bigBlock32: DataView;
101+
private h0 = 0x67452301;
102+
private h1 = 0xEFCDAB89;
103+
private h2 = 0x98BADCFE;
104+
private h3 = 0x10325476;
105+
private h4 = 0xC3D2E1F0;
106+
107+
static digest(data: string): string;
108+
static digest(data: Uint8Array): string;
109+
static digest(data: ArrayBuffer): string;
110+
static digest(data: DataView): string;
111+
static digest(data: any): string {
112+
let sha = new SHA1();
113+
sha.update(data);
114+
115+
return sha.digest();
116+
}
117+
118+
constructor() {
119+
this.length = 0;
120+
121+
this.buffer = new Uint8Array(SHA1.BLOCK_SIZE);
122+
this.bufferDV = new DataView(this.buffer.buffer);
123+
this.bufferLength = 0;
124+
125+
this.bigBlock32 = new DataView(new ArrayBuffer(320)); // 80 * 4 = 320;
126+
}
127+
128+
update(data: string): void;
129+
update(data: Uint8Array): void;
130+
update(data: ArrayBuffer): void;
131+
update(data: DataView): void;
132+
update(arg: any): void {
133+
if (!this.buffer || !this.bufferDV) {
134+
throw new Error('Digest already computed.');
135+
}
136+
137+
let data: Uint8Array;
138+
139+
if (isString(arg)) {
140+
data = new Uint8Array(encodeToArrayBuffer(<string>arg));
141+
} else if (arg instanceof ArrayBuffer) {
142+
data = new Uint8Array(arg);
143+
} else if (arg instanceof DataView) {
144+
data = new Uint8Array((<DataView>arg).buffer);
145+
} else {
146+
data = <Uint8Array>arg;
147+
}
148+
149+
let bytesRead = 0, totalBytesRead = 0;
150+
151+
while (totalBytesRead < data.byteLength) {
152+
bytesRead = copy(this.buffer, this.bufferLength, data, totalBytesRead, data.byteLength);
153+
154+
this.bufferLength += bytesRead;
155+
totalBytesRead += bytesRead;
156+
157+
if (this.bufferLength === SHA1.BLOCK_SIZE) {
158+
this.step(this.bufferDV);
159+
this.bufferLength = 0;
160+
}
161+
}
162+
163+
this.length += totalBytesRead;
164+
}
165+
166+
digest(): string {
167+
if (this.buffer) {
168+
this.wrapUp();
169+
}
170+
171+
return toHexString(this.h0) + toHexString(this.h1) + toHexString(this.h2) + toHexString(this.h3) + toHexString(this.h4);
172+
}
173+
174+
private wrapUp(): void {
175+
if (!this.buffer || !this.bufferDV) {
176+
return; // already wrapped up
177+
}
178+
179+
this.buffer[this.bufferLength++] = 0x80;
180+
fill(this.buffer, this.bufferLength);
181+
182+
if (this.bufferLength > 56) {
183+
this.step(this.bufferDV);
184+
fill(this.buffer);
185+
}
186+
187+
let ml = multiply64(8, this.length);
188+
this.bufferDV.setUint32(56, ml[0], false);
189+
this.bufferDV.setUint32(60, ml[1], false);
190+
191+
this.step(this.bufferDV);
192+
193+
this.buffer = null;
194+
this.bufferDV = null;
195+
this.bufferLength = -1;
196+
}
197+
198+
private step(data: DataView): void {
199+
for (let j = 0; j < 64 /* 16*4 */; j += 4) {
200+
this.bigBlock32.setUint32(j, data.getUint32(j, false), false);
201+
}
202+
203+
for (let j = 64; j < 320 /* 80*4 */; j += 4) {
204+
this.bigBlock32.setUint32(j, leftRotate((this.bigBlock32.getUint32(j - 12, false) ^ this.bigBlock32.getUint32(j - 32, false) ^ this.bigBlock32.getUint32(j - 56, false) ^ this.bigBlock32.getUint32(j - 64, false)), 1), false);
205+
}
206+
207+
let a = this.h0;
208+
let b = this.h1;
209+
let c = this.h2;
210+
let d = this.h3;
211+
let e = this.h4;
212+
213+
let f: number, k: number;
214+
let temp: number;
215+
216+
for (let j = 0; j < 80; j++) {
217+
if (j < 20) {
218+
f = (b & c) | ((~b) & d);
219+
k = 0x5A827999;
220+
} else if (j < 40) {
221+
f = b ^ c ^ d;
222+
k = 0x6ED9EBA1;
223+
} else if (j < 60) {
224+
f = (b & c) | (b & d) | (c & d);
225+
k = 0x8F1BBCDC;
226+
} else {
227+
f = b ^ c ^ d;
228+
k = 0xCA62C1D6;
229+
}
230+
231+
temp = (leftRotate(a, 5) + f + e + k + this.bigBlock32.getUint32(j * 4, false)) & 0xFFFFFFFF;
232+
e = d;
233+
d = c;
234+
c = leftRotate(b, 30);
235+
b = a;
236+
a = temp;
237+
}
238+
239+
this.h0 = (this.h0 + a) & 0xFFFFFFFF;
240+
this.h1 = (this.h1 + b) & 0xFFFFFFFF;
241+
this.h2 = (this.h2 + c) & 0xFFFFFFFF;
242+
this.h3 = (this.h3 + d) & 0xFFFFFFFF;
243+
this.h4 = (this.h4 + e) & 0xFFFFFFFF;
244+
}
245+
}
246+
247+
function leftPad(value: string, length: number, char: string = '0'): string {
248+
return new Array(length - value.length + 1).join(char) + value;
249+
}
250+
251+
function toHexString(value: number, bitsize: number = 32): string {
252+
return leftPad((value >>> 0).toString(16), bitsize / 4);
253+
}
254+
255+
function leftRotate(value: number, bits: number, totalBits: number = 32): number {
256+
257+
// delta + bits = totalBits
258+
let delta = totalBits - bits;
259+
260+
// All ones, expect `delta` zeros aligned to the right
261+
let mask = ~((1 << delta) - 1);
262+
263+
// Join (value left-shifted `bits` bits) with (masked value right-shifted `delta` bits)
264+
return ((value << bits) | ((mask & value) >>> delta)) >>> 0;
265+
}
266+
267+
function multiply64(a: number, b: number): number[] {
268+
/* A1 A0 => A
269+
* B1 B0 => B
270+
* B0 * A1 B0 * A0
271+
* B1 * A1 B1 * A0
272+
* C3 C2 C1 C0 => C
273+
*/
274+
275+
let a0 = a & 0xFFFF, a1 = a >>> 16;
276+
let b0 = b & 0xFFFF, b1 = b >>> 16;
277+
let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
278+
279+
let x = b0 * a0;
280+
c0 += x & 0xFFFF;
281+
c1 += x >>> 16;
282+
283+
x = b0 * a1;
284+
c1 += x & 0xFFFF;
285+
c2 += x >>> 16;
286+
287+
x = b1 * a0;
288+
c1 += x & 0xFFFF;
289+
c2 += x >>> 16;
290+
291+
c2 += c1 >>> 16;
292+
c1 = c1 & 0xFFFF;
293+
294+
x = b1 * a1;
295+
c2 += x & 0xFFFF;
296+
c3 += x >>> 16;
297+
298+
c3 += c2 >>> 16;
299+
c2 = c2 & 0xFFFF;
300+
301+
return [(c3 << 16 | c2) >>> 0, (c1 << 16 | c0) >>> 0];
302+
}
303+
304+
function encodeToArrayBuffer(str: string): ArrayBuffer {
305+
let i: number, len: number, length = 0, charCode = 0, trailCharCode = 0, codepoint = 0;
306+
307+
// First pass, for the size
308+
for (i = 0, len = str.length; i < len; i++) {
309+
charCode = str.charCodeAt(i);
310+
311+
// Surrogate pair
312+
if (charCode >= 0xD800 && charCode < 0xDC00) {
313+
trailCharCode = str.charCodeAt(++i);
314+
315+
if (!(trailCharCode >= 0xDC00 && trailCharCode < 0xE000)) {
316+
throw new Error('Invalid char code');
317+
}
318+
319+
// Code point can be obtained by subtracting 0xD800 and 0xDC00 from both char codes respectively
320+
// and joining the 10 least significant bits from each, finally adding 0x10000.
321+
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
322+
323+
} else {
324+
codepoint = charCode;
325+
}
326+
327+
length += byteSizeInUTF8(codepoint);
328+
}
329+
330+
let result = new ArrayBuffer(length);
331+
let view = new Uint8Array(result);
332+
let pos = 0;
333+
334+
// Second pass, for the data
335+
for (i = 0, len = str.length; i < len; i++) {
336+
charCode = str.charCodeAt(i);
337+
338+
if (charCode >= 0xD800 && charCode < 0xDC00) {
339+
trailCharCode = str.charCodeAt(++i);
340+
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
341+
} else {
342+
codepoint = charCode;
343+
}
344+
345+
pos += writeUTF8(codepoint, view, pos);
346+
}
347+
348+
return result;
349+
}
350+
351+
function byteSizeInUTF8(codePoint: number): number {
352+
codePoint = codePoint >>> 0;
353+
354+
if (codePoint < 0x80) {
355+
return 1;
356+
} else if (codePoint < 0x800) {
357+
return 2;
358+
} else if (codePoint < 0x10000) {
359+
return 3;
360+
} else if (codePoint < 0x200000) {
361+
return 4;
362+
} else if (codePoint < 0x4000000) {
363+
return 5;
364+
} else if (codePoint < 0x80000000) {
365+
return 6;
366+
} else {
367+
throw new Error('Code point 0x' + toHexString(codePoint) + ' not encodable in UTF8.');
368+
}
369+
}
370+
371+
function writeUTF8(codePoint: number, buffer: Uint8Array, pos: number): number {
372+
373+
// How many bits needed for codePoint
374+
let byteSize = byteSizeInUTF8(codePoint);
375+
376+
// 0xxxxxxx
377+
if (byteSize === 1) {
378+
buffer[pos] = codePoint;
379+
return 1;
380+
}
381+
382+
// 110xxxxx 10xxxxxx
383+
// 1110xxxx 10xxxxxx 10xxxxxx
384+
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
385+
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
386+
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
387+
388+
// first byte
389+
buffer[pos] = ((0xFC << (6 - byteSize)) | (codePoint >>> (6 * (byteSize - 1)))) & 0xFF;
390+
391+
// successive bytes
392+
for (let i = 1; i < byteSize; i++) {
393+
buffer[pos + i] = (0x80 | (0x3F & (codePoint >>> (6 * (byteSize - i - 1))))) & 0xFF;
394+
}
395+
396+
return byteSize;
397+
}
398+
399+
function copy(dest: Uint8Array, destIndex: number, src: Uint8Array, srcIndex: number, count: number): number {
400+
const len = Math.min(dest.byteLength - destIndex, src.byteLength - srcIndex, count);
401+
402+
for (let i = 0; i < len; i++) {
403+
dest[destIndex + i] = src[srcIndex + i];
404+
}
405+
406+
return len;
407+
}
408+
409+
function fill(dest: Uint8Array, index: number = 0, count: number = dest.byteLength, value: number = 0): void {
410+
for (let i = 0; i < count; i++) {
411+
dest[index + i] = value;
412+
}
413+
}
414+
415+
//#endregion

src/vs/base/test/common/hash.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55
import * as assert from 'assert';
6-
import { hash } from 'vs/base/common/hash';
6+
import { hash, computeSHA1Hash } from 'vs/base/common/hash';
77

88
suite('Hash', () => {
99
test('string', () => {
@@ -43,4 +43,12 @@ suite('Hash', () => {
4343
assert.notEqual(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar2' }));
4444
assert.notEqual(hash({}), hash([]));
4545
});
46+
47+
test('computeSHA1Hash', () => {
48+
assert.equal(computeSHA1Hash(''), 'da39a3ee5e6b4b0d3255bfef95601890afd80709');
49+
assert.equal(computeSHA1Hash('hello world'), '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed');
50+
assert.equal(computeSHA1Hash('da39a3ee5e6b4b0d3255bfef95601890afd80709'), '10a34637ad661d98ba3344717656fcc76209c2f8');
51+
assert.equal(computeSHA1Hash('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'), 'd6b0d82cea4269b51572b8fab43adcee9fc3cf9a');
52+
assert.equal(computeSHA1Hash('öäü_?ß()<>ÖÄÜ'), 'b64beaeff9e317b0193c8e40a2431b210388eba9');
53+
});
4654
});

0 commit comments

Comments
 (0)