Skip to content

Commit df32277

Browse files
refactor: import single-file 3rd party modules
This commit allows to: - provide an ESM version of those modules ([1]) - reduce the attack surface in case of supply chain attacks - reduce the size of the bundle with tree-shaking As a downside, we won't receive security updates for those modules anymore. [1]: socketio/socket.io-client#1536
1 parent b4b3ed5 commit df32277

File tree

13 files changed

+197
-63
lines changed

13 files changed

+197
-63
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
test/support/public/engine.io.min.js
2+
lib/contrib/*

lib/contrib/has-cors.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// imported from https://github.com/component/has-cors
2+
let value = false;
3+
4+
try {
5+
value = typeof XMLHttpRequest !== 'undefined' &&
6+
'withCredentials' in new XMLHttpRequest();
7+
} catch (err) {
8+
// if XMLHttp support is disabled in IE then it will throw
9+
// when trying to create
10+
}
11+
12+
export const hasCORS = value;

lib/contrib/parseqs.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// imported from https://github.com/galkn/querystring
2+
/**
3+
* Compiles a querystring
4+
* Returns string representation of the object
5+
*
6+
* @param {Object}
7+
* @api private
8+
*/
9+
10+
export function encode (obj) {
11+
let str = '';
12+
13+
for (let i in obj) {
14+
if (obj.hasOwnProperty(i)) {
15+
if (str.length) str += '&';
16+
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
17+
}
18+
}
19+
20+
return str;
21+
}
22+
23+
/**
24+
* Parses a simple querystring into an object
25+
*
26+
* @param {String} qs
27+
* @api private
28+
*/
29+
30+
export function decode (qs) {
31+
let qry = {};
32+
let pairs = qs.split('&');
33+
for (let i = 0, l = pairs.length; i < l; i++) {
34+
let pair = pairs[i].split('=');
35+
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
36+
}
37+
return qry;
38+
}

lib/contrib/parseuri.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// imported from https://github.com/galkn/parseuri
2+
/**
3+
* Parses an URI
4+
*
5+
* @author Steven Levithan <stevenlevithan.com> (MIT license)
6+
* @api private
7+
*/
8+
const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
9+
10+
const parts = [
11+
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
12+
];
13+
14+
export function parse(str) {
15+
const src = str,
16+
b = str.indexOf('['),
17+
e = str.indexOf(']');
18+
19+
if (b != -1 && e != -1) {
20+
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
21+
}
22+
23+
let m = re.exec(str || ''),
24+
uri = {} as any,
25+
i = 14;
26+
27+
while (i--) {
28+
uri[parts[i]] = m[i] || '';
29+
}
30+
31+
if (b != -1 && e != -1) {
32+
uri.source = src;
33+
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
34+
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
35+
uri.ipv6uri = true;
36+
}
37+
38+
uri.pathNames = pathNames(uri, uri['path']);
39+
uri.queryKey = queryKey(uri, uri['query']);
40+
41+
return uri;
42+
}
43+
44+
function pathNames(obj, path) {
45+
const regx = /\/{2,9}/g,
46+
names = path.replace(regx, "/").split("/");
47+
48+
if (path.substr(0, 1) == '/' || path.length === 0) {
49+
names.splice(0, 1);
50+
}
51+
if (path.substr(path.length - 1, 1) == '/') {
52+
names.splice(names.length - 1, 1);
53+
}
54+
55+
return names;
56+
}
57+
58+
function queryKey(uri, query) {
59+
const data = {};
60+
61+
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
62+
if ($1) {
63+
data[$1] = $2;
64+
}
65+
});
66+
67+
return data;
68+
}

lib/contrib/yeast.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// imported from https://github.com/unshiftio/yeast
2+
'use strict';
3+
4+
const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
5+
, length = 64
6+
, map = {};
7+
let seed = 0
8+
, i = 0
9+
, prev;
10+
11+
/**
12+
* Return a string representing the specified number.
13+
*
14+
* @param {Number} num The number to convert.
15+
* @returns {String} The string representation of the number.
16+
* @api public
17+
*/
18+
export function encode(num) {
19+
let encoded = '';
20+
21+
do {
22+
encoded = alphabet[num % length] + encoded;
23+
num = Math.floor(num / length);
24+
} while (num > 0);
25+
26+
return encoded;
27+
}
28+
29+
/**
30+
* Return the integer value specified by the given string.
31+
*
32+
* @param {String} str The string to convert.
33+
* @returns {Number} The integer value represented by the string.
34+
* @api public
35+
*/
36+
export function decode(str) {
37+
let decoded = 0;
38+
39+
for (i = 0; i < str.length; i++) {
40+
decoded = decoded * length + map[str.charAt(i)];
41+
}
42+
43+
return decoded;
44+
}
45+
46+
/**
47+
* Yeast: A tiny growing id generator.
48+
*
49+
* @returns {String} A unique id.
50+
* @api public
51+
*/
52+
export function yeast() {
53+
const now = encode(+new Date());
54+
55+
if (now !== prev) return seed = 0, prev = now;
56+
return now +'.'+ encode(seed++);
57+
}
58+
59+
//
60+
// Map each character to its index.
61+
//
62+
for (; i < length; i++) map[alphabet[i]] = i;

lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export const protocol = Socket.protocol;
66
export { Transport } from "./transport.js";
77
export { transports } from "./transports/index.js";
88
export { installTimerFunctions } from "./util.js";
9+
export { parse } from "./contrib/parseuri";

lib/socket.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { transports } from "./transports/index.js";
22
import { installTimerFunctions, byteLength } from "./util.js";
3-
import parseqs from "parseqs";
4-
import parseuri from "parseuri";
3+
import { decode } from "./contrib/parseqs.js";
4+
import { parse } from "./contrib/parseuri.js";
55
import debugModule from "debug"; // debug()
66
import { Emitter } from "@socket.io/component-emitter";
77
import { protocol } from "engine.io-parser";
@@ -277,13 +277,13 @@ export class Socket extends Emitter<{}, {}, SocketReservedEvents> {
277277
}
278278

279279
if (uri) {
280-
uri = parseuri(uri);
280+
uri = parse(uri);
281281
opts.hostname = uri.host;
282282
opts.secure = uri.protocol === "https" || uri.protocol === "wss";
283283
opts.port = uri.port;
284284
if (uri.query) opts.query = uri.query;
285285
} else if (opts.host) {
286-
opts.hostname = parseuri(opts.host).host;
286+
opts.hostname = parse(opts.host).host;
287287
}
288288

289289
installTimerFunctions(this, opts);
@@ -335,7 +335,7 @@ export class Socket extends Emitter<{}, {}, SocketReservedEvents> {
335335
this.opts.path = this.opts.path.replace(/\/$/, "") + "/";
336336

337337
if (typeof this.opts.query === "string") {
338-
this.opts.query = parseqs.decode(this.opts.query);
338+
this.opts.query = decode(this.opts.query);
339339
}
340340

341341
// set on handshake

lib/transports/polling.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Transport } from "../transport.js";
22
import debugModule from "debug"; // debug()
3-
import yeast from "yeast";
4-
import parseqs from "parseqs";
3+
import { yeast } from "../contrib/yeast.js";
4+
import { encode } from "../contrib/parseqs.js";
55
import { encodePayload, decodePayload, RawData } from "engine.io-parser";
66
import XMLHttpRequest from "./xmlhttprequest.js";
77
import { Emitter } from "@socket.io/component-emitter";
@@ -235,7 +235,7 @@ export class Polling extends Transport {
235235
port = ":" + this.opts.port;
236236
}
237237

238-
const encodedQuery = parseqs.encode(query);
238+
const encodedQuery = encode(query);
239239
const ipv6 = this.opts.hostname.indexOf(":") !== -1;
240240

241241
return (

lib/transports/websocket.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Transport } from "../transport.js";
2-
import parseqs from "parseqs";
3-
import yeast from "yeast";
2+
import { encode } from "../contrib/parseqs.js";
3+
import { yeast } from "../contrib/yeast.js";
44
import { pick } from "../util.js";
55
import {
66
defaultBinaryType,
@@ -220,7 +220,7 @@ export class WS extends Transport {
220220
query.b64 = 1;
221221
}
222222

223-
const encodedQuery = parseqs.encode(query);
223+
const encodedQuery = encode(query);
224224
const ipv6 = this.opts.hostname.indexOf(":") !== -1;
225225

226226
return (

lib/transports/xmlhttprequest.browser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// browser shim for xmlhttprequest module
22

3-
import hasCORS from "has-cors";
3+
import { hasCORS } from "../contrib/has-cors.js";
44
import globalThis from "../globalThis.js";
55

66
export default function(opts) {

0 commit comments

Comments
 (0)