ranuts 0.1.0-alpha.1 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/assets/img/sort/bubble.gif +0 -0
- package/assets/img/sort/complexity.png +0 -0
- package/assets/img/sort/select.gif +0 -0
- package/assets/img/sort/sort.png +0 -0
- package/assets/img/tree/balanceTree.png +0 -0
- package/dist/index.js.map +0 -1
- package/dist/index.umd.cjs.map +0 -1
- package/dist/src/file/fileInfo.d.ts +0 -7
- package/dist/src/file/fs.d.ts +0 -2
- package/dist/src/file/readDir.d.ts +0 -6
- package/dist/src/file/readFile.d.ts +0 -8
- package/dist/src/file/watchFile.d.ts +0 -8
- package/dist/src/file/writeFile.d.ts +0 -8
- package/dist/src/mode/subscribe.d.ts +0 -16
- package/dist/src/ranlog/behavior.d.ts +0 -1
- package/dist/src/ranlog/env.d.ts +0 -5
- package/dist/src/ranlog/error.d.ts +0 -2
- package/dist/src/ranlog/index.d.ts +0 -26
- package/dist/src/ranlog/performance.d.ts +0 -21
- package/dist/src/ranlog/report.d.ts +0 -7
- package/dist/src/ranlog/request.d.ts +0 -18
- package/dist/src/ranlog/utils.d.ts +0 -19
- package/dist/src/utils/filterObj.d.ts +0 -8
- package/dist/src/utils/str2Xml.d.ts +0 -8
- package/dist/src/vnode/h.d.ts +0 -6
- package/dist/src/vnode/hooks.d.ts +0 -23
- package/dist/src/vnode/htmlDomApi.d.ts +0 -33
- package/dist/src/vnode/init.d.ts +0 -2
- package/dist/src/vnode/is.d.ts +0 -5
- package/dist/src/vnode/modules/attributes.d.ts +0 -8
- package/dist/src/vnode/modules/class.d.ts +0 -8
- package/dist/src/vnode/modules/index.d.ts +0 -7
- package/dist/src/vnode/modules/listeners.d.ts +0 -14
- package/dist/src/vnode/modules/props.d.ts +0 -8
- package/dist/src/vnode/modules/style.d.ts +0 -14
- package/dist/src/vnode/vnode.d.ts +0 -31
- package/src/astParser/Parser.ts +0 -654
- package/src/astParser/Tokenizer.ts +0 -447
- package/src/astParser/nodeTypes.ts +0 -194
- package/src/astParser/utils.ts +0 -27
- package/src/babel/parser.ts +0 -10
- package/src/colors/fmt.ts +0 -29
- package/src/colors/isColorSupported.ts +0 -13
- package/src/file/appendFile.ts +0 -29
- package/src/file/fileInfo.ts +0 -22
- package/src/file/fs.ts +0 -9
- package/src/file/readDir.ts +0 -18
- package/src/file/readFile.ts +0 -26
- package/src/file/watchFile.ts +0 -31
- package/src/file/writeFile.ts +0 -38
- package/src/mode/subscribe.ts +0 -89
- package/src/ran/commit.ts +0 -0
- package/src/ran/dom.ts +0 -0
- package/src/ran/hooks.ts +0 -0
- package/src/ran/reconcile.ts +0 -0
- package/src/ran/schedule.ts +0 -0
- package/src/ranlog/behavior.ts +0 -5
- package/src/ranlog/console.ts +0 -16
- package/src/ranlog/env.ts +0 -29
- package/src/ranlog/error.ts +0 -11
- package/src/ranlog/performance.ts +0 -65
- package/src/ranlog/report.ts +0 -33
- package/src/ranlog/request.ts +0 -60
- package/src/ranlog/utils.ts +0 -92
- package/src/ranpack/ast/Declaration.ts +0 -120
- package/src/ranpack/ast/Node.ts +0 -7
- package/src/ranpack/ast/Reference.ts +0 -32
- package/src/ranpack/ast/Scope.ts +0 -80
- package/src/ranpack/bundle.ts +0 -50
- package/src/ranpack/graph.ts +0 -143
- package/src/ranpack/module.ts +0 -431
- package/src/ranpack/moduleLoader.ts +0 -73
- package/src/ranpack/plugins.ts +0 -70
- package/src/ranpack/statement.ts +0 -66
- package/src/ranpack/utils/buildScope.ts +0 -77
- package/src/ranpack/utils/findReference.ts +0 -36
- package/src/ranpack/utils/isFunctionDeclaration.ts +0 -41
- package/src/ranpack/utils/makeLegalIdentifier.ts +0 -18
- package/src/ranpack/utils/object.ts +0 -8
- package/src/ranpack/utils/resolve.ts +0 -32
- package/src/ranpack/utils/walk.ts +0 -66
- package/src/ranpack/ws.ts +0 -269
- package/src/server/connectType.ts +0 -9
- package/src/server/encodeUrl.ts +0 -46
- package/src/server/escapeHtml.ts +0 -46
- package/src/server/get.ts +0 -36
- package/src/server/jitter.ts +0 -77
- package/src/server/mimeType.ts +0 -858
- package/src/server/paresUrl.ts +0 -40
- package/src/server/send.ts +0 -89
- package/src/server/server.ts +0 -67
- package/src/server/status.ts +0 -191
- package/src/server/traverse.ts +0 -54
- package/src/server/websocket.ts +0 -200
- package/src/sort/bubble.ts +0 -21
- package/src/sort/bucket.ts +0 -11
- package/src/sort/count.ts +0 -10
- package/src/sort/heap.ts +0 -10
- package/src/sort/insert.ts +0 -20
- package/src/sort/merge.ts +0 -35
- package/src/sort/quick.ts +0 -50
- package/src/sort/radix.ts +0 -11
- package/src/sort/randomArray.ts +0 -21
- package/src/sort/select.ts +0 -23
- package/src/sort/shell.ts +0 -22
- package/src/utils/compose.ts +0 -37
- package/src/utils/filterObj.ts +0 -21
- package/src/utils/mergeObj.ts +0 -12
- package/src/utils/startTask.ts +0 -15
- package/src/utils/str2Xml.ts +0 -26
- package/src/utils/taskEnd.ts +0 -14
- package/src/vnode/h.ts +0 -108
- package/src/vnode/hooks.ts +0 -25
- package/src/vnode/htmlDomApi.ts +0 -199
- package/src/vnode/init.ts +0 -429
- package/src/vnode/is.ts +0 -17
- package/src/vnode/modules/attributes.ts +0 -70
- package/src/vnode/modules/class.ts +0 -46
- package/src/vnode/modules/listeners.ts +0 -123
- package/src/vnode/modules/props.ts +0 -41
- package/src/vnode/modules/style.ts +0 -118
- package/src/vnode/vnode.ts +0 -65
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { Scope } from '../ast/Scope';
|
|
2
|
-
import type { Statement } from '../statement';
|
|
3
|
-
import type {
|
|
4
|
-
FunctionDeclaration,
|
|
5
|
-
Node,
|
|
6
|
-
VariableDeclaration
|
|
7
|
-
, VariableDeclarator } from '../../astParser';
|
|
8
|
-
import {
|
|
9
|
-
NodeType
|
|
10
|
-
} from '../../astParser';
|
|
11
|
-
import { walk } from './walk';
|
|
12
|
-
/**
|
|
13
|
-
* @description: 构建作用域链
|
|
14
|
-
* @param {Statement} statement
|
|
15
|
-
* @return {*}
|
|
16
|
-
*/
|
|
17
|
-
export function buildScope(statement: Statement):void {
|
|
18
|
-
const { node, scope: initialScope } = statement;
|
|
19
|
-
let scope = initialScope;
|
|
20
|
-
// 遍历 AST
|
|
21
|
-
walk(node, {
|
|
22
|
-
// 遵循深度优先的原则,每进入和离开一个节点会触发 enter 和 leave 钩子
|
|
23
|
-
// 如 a 的子节点为 b,那么触发顺序为 a-enter、b-enter、b-leave、a-leave
|
|
24
|
-
enter(node: Node) {
|
|
25
|
-
// function foo () {...}
|
|
26
|
-
if (node.type === NodeType.FunctionDeclaration) {
|
|
27
|
-
scope.addDeclaration(node, false);
|
|
28
|
-
}
|
|
29
|
-
// var let const
|
|
30
|
-
if (node.type === NodeType.VariableDeclaration) {
|
|
31
|
-
const currentNode = node as VariableDeclaration;
|
|
32
|
-
const isBlockDeclaration = currentNode.kind !== 'var';
|
|
33
|
-
currentNode.declarations.forEach((declarator: VariableDeclarator) => {
|
|
34
|
-
scope.addDeclaration(declarator, isBlockDeclaration);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
let newScope;
|
|
39
|
-
|
|
40
|
-
// function scope
|
|
41
|
-
if (node.type === NodeType.FunctionDeclaration) {
|
|
42
|
-
const currentNode = node as FunctionDeclaration;
|
|
43
|
-
newScope = new Scope({
|
|
44
|
-
parent: scope,
|
|
45
|
-
block: false,
|
|
46
|
-
paramNodes: currentNode.params,
|
|
47
|
-
statement
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// new block state
|
|
52
|
-
if (node.type === NodeType.BlockStatement) {
|
|
53
|
-
newScope = new Scope({
|
|
54
|
-
parent: scope,
|
|
55
|
-
block: true,
|
|
56
|
-
statement
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
// 记录 Scope 父子关系
|
|
60
|
-
if (newScope) {
|
|
61
|
-
Object.defineProperty(node, '_scope', {
|
|
62
|
-
value: newScope,
|
|
63
|
-
configurable: true
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
scope = newScope;
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
leave(node: Node) {
|
|
70
|
-
// 更新当前作用域
|
|
71
|
-
// 当前 scope 即 node._scope
|
|
72
|
-
if (node._scope && scope.parent) {
|
|
73
|
-
scope = scope.parent;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Statement } from '../statement';
|
|
2
|
-
import { Reference } from '../ast/Declaration';
|
|
3
|
-
import type { Node } from '../ast/Node'
|
|
4
|
-
import { walk } from './walk';
|
|
5
|
-
|
|
6
|
-
function isReference(node: any, parent: any): boolean {
|
|
7
|
-
if (node.type === 'MemberExpression' && parent.type !== 'MemberExpression') {
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
if (node.type === 'Identifier') {
|
|
11
|
-
// export { foo as bar }
|
|
12
|
-
if (parent.type === 'ExportSpecifier' && node !== parent.local)
|
|
13
|
-
return false;
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function findReference(statement: Statement):void {
|
|
20
|
-
const { references, scope: initialScope, node } = statement;
|
|
21
|
-
let scope = initialScope;
|
|
22
|
-
walk(node, {
|
|
23
|
-
enter(node: Node, parent: Node | undefined) {
|
|
24
|
-
if (node._scope) scope = node._scope;
|
|
25
|
-
if (isReference(node, parent)) {
|
|
26
|
-
const reference = new Reference(node, scope, statement);
|
|
27
|
-
references.push(reference);
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
leave(node: Node) {
|
|
31
|
-
if (node._scope && scope.parent) {
|
|
32
|
-
scope = scope.parent;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Declaration, ExportDeclaration} from '../../astParser';
|
|
2
|
-
import { NodeType } from '../../astParser';
|
|
3
|
-
/**
|
|
4
|
-
* @description: 是否为函数节点
|
|
5
|
-
* @param {Declaration} node
|
|
6
|
-
* @return {*}
|
|
7
|
-
*/
|
|
8
|
-
export function isFunctionDeclaration(node: Declaration): boolean {
|
|
9
|
-
if (!node) return false;
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
// function foo() {}
|
|
13
|
-
node.type === 'FunctionDeclaration' ||
|
|
14
|
-
// const foo = function() {}
|
|
15
|
-
(node.type === NodeType.VariableDeclarator &&
|
|
16
|
-
node.init &&
|
|
17
|
-
node.init.type === NodeType.FunctionExpression) ||
|
|
18
|
-
// export function ...
|
|
19
|
-
// export default function
|
|
20
|
-
((node.type === NodeType.ExportNamedDeclaration ||
|
|
21
|
-
node.type === NodeType.ExportDefaultDeclaration) &&
|
|
22
|
-
!!node.declaration &&
|
|
23
|
-
node.declaration.type === NodeType.FunctionDeclaration)
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* @description: 是否为 export 声明节点
|
|
28
|
-
* @param {ExportDeclaration} node
|
|
29
|
-
* @return {*}
|
|
30
|
-
*/
|
|
31
|
-
export function isExportDeclaration(node: ExportDeclaration): boolean {
|
|
32
|
-
return /^Export/.test(node.type);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* @description: 是否为 import 声明节点
|
|
36
|
-
* @param {any} node
|
|
37
|
-
* @return {*}
|
|
38
|
-
*/
|
|
39
|
-
export function isImportDeclaration(node: any):boolean {
|
|
40
|
-
return node.type === 'ImportDeclaration';
|
|
41
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const reservedWords =
|
|
2
|
-
'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public'.split(
|
|
3
|
-
' '
|
|
4
|
-
);
|
|
5
|
-
const builtins =
|
|
6
|
-
'Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl'.split(
|
|
7
|
-
' '
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
export default function makeLegalIdentifier(str: string):string {
|
|
11
|
-
str = str
|
|
12
|
-
.replace(/-(\w)/g, (_, letter) => letter.toUpperCase())
|
|
13
|
-
.replace(/[^$\w]/g, '_');
|
|
14
|
-
if (reservedWords.concat(builtins).includes(str)) {
|
|
15
|
-
str = `_${str}`;
|
|
16
|
-
}
|
|
17
|
-
return str;
|
|
18
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { dirname, extname, isAbsolute, resolve } from 'node:path';
|
|
2
|
-
|
|
3
|
-
export function removeExtension(p: string): string {
|
|
4
|
-
return p.replace(extname(p), '');
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
const extensions = '.js'
|
|
8
|
-
|
|
9
|
-
const getFileType = (val: string): string => {
|
|
10
|
-
return val.substring(val.lastIndexOf(".") + 1);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* @description: 返回完整的路径
|
|
14
|
-
* @param {string} id
|
|
15
|
-
* @param {string} importer
|
|
16
|
-
*/
|
|
17
|
-
export function defaultResolver(id: string, importer: string | null): string | false {
|
|
18
|
-
|
|
19
|
-
// // 处理文件名不以js结尾的情况,补全.js
|
|
20
|
-
if (getFileType(id) !== 'js') {
|
|
21
|
-
id += '.js'
|
|
22
|
-
}
|
|
23
|
-
// 如果是绝对路径,直接返回绝对路径
|
|
24
|
-
if (isAbsolute(id)) {
|
|
25
|
-
return id
|
|
26
|
-
}
|
|
27
|
-
// 如果不是绝对路径,那必然是相对路径,必燃以 . 开头,如果不是,则返回false
|
|
28
|
-
if (!id.startsWith('.')) return false;
|
|
29
|
-
// 返回完整的路径
|
|
30
|
-
const resolvedPath = importer ? resolve(dirname(importer), id) : resolve(id);
|
|
31
|
-
return resolvedPath;
|
|
32
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Statement } from '../../astParser';
|
|
3
|
-
import type { Node } from '../ast/Node'
|
|
4
|
-
|
|
5
|
-
let shouldSkip;
|
|
6
|
-
let shouldAbort: boolean;
|
|
7
|
-
|
|
8
|
-
type WalkOperate = (node: Node, parent?: Node, prop?: string) => void
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @description: 无论是构建作用域链还是记录引用节点,都离不开一个最基本的操作,那就是对 AST 进行遍历操作
|
|
12
|
-
* @param {any} ast
|
|
13
|
-
* @param {object} param2
|
|
14
|
-
* @return {*}
|
|
15
|
-
*/
|
|
16
|
-
export function walk(ast: Statement, { enter, leave }: { enter: WalkOperate; leave: WalkOperate }): void {
|
|
17
|
-
shouldAbort = false;
|
|
18
|
-
visit(ast, undefined, enter, leave);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const context = {
|
|
22
|
-
skip: () => (shouldSkip = true),
|
|
23
|
-
abort: () => (shouldAbort = true)
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const childKeys = {} as Record<string, string[]>;
|
|
27
|
-
|
|
28
|
-
const toString = Object.prototype.toString;
|
|
29
|
-
|
|
30
|
-
function isArray(thing: any) {
|
|
31
|
-
return toString.call(thing) === '[object Array]';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function visit(node: Node, parent: Node | undefined, enter: WalkOperate, leave: WalkOperate, prop?: string) {
|
|
35
|
-
if (!node || shouldAbort) return;
|
|
36
|
-
|
|
37
|
-
if (enter) {
|
|
38
|
-
shouldSkip = false;
|
|
39
|
-
enter.call(context, node, parent, prop);
|
|
40
|
-
if (shouldSkip || shouldAbort) return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const keys =
|
|
44
|
-
childKeys[node.type] ||
|
|
45
|
-
(childKeys[node.type] = Object.keys(node).filter(
|
|
46
|
-
(key) => typeof node[key as keyof Node] === 'object'
|
|
47
|
-
));
|
|
48
|
-
|
|
49
|
-
let key, value: any;
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < keys.length; i++) {
|
|
52
|
-
key = keys[i];
|
|
53
|
-
value = node[key as keyof Node];
|
|
54
|
-
if (Array.isArray(value)) {
|
|
55
|
-
for (let j = 0; j < value.length; j++) {
|
|
56
|
-
visit(value[j], node, enter, leave, key);
|
|
57
|
-
}
|
|
58
|
-
} else if (value && value.type) {
|
|
59
|
-
visit(value, node, enter, leave, key);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (leave && !shouldAbort) {
|
|
64
|
-
leave(node, parent, prop);
|
|
65
|
-
}
|
|
66
|
-
}
|
package/src/ranpack/ws.ts
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'node:buffer'
|
|
2
|
-
import type http from 'node:http'
|
|
3
|
-
import crypto from 'node:crypto'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Create a text Frame for ws server
|
|
7
|
-
* see Frame format in readme.md
|
|
8
|
-
* @param { String | Buffer } content content of frame
|
|
9
|
-
* @param { Object } options options
|
|
10
|
-
* @param { Number } options.opcode
|
|
11
|
-
* @returns { Buffer } frame buffer
|
|
12
|
-
*/
|
|
13
|
-
function createFrame(content: string, options: { opcode: any; }) {
|
|
14
|
-
|
|
15
|
-
const len = Buffer.byteLength(content); // length of the content
|
|
16
|
-
|
|
17
|
-
let buf = null;
|
|
18
|
-
if (len > 65535) { // 65536 is the max of 16 bits
|
|
19
|
-
|
|
20
|
-
buf = Buffer.alloc(10 + len);
|
|
21
|
-
buf[1] = 127; // 127 = 01111111 means using more 64 bits to save the length, using no masks. `len7` is this byte.
|
|
22
|
-
buf.writeUInt32BE(len, 6); // skip the 127 and 4 bytes to write the content length in 32 bits (32 bits = 4 bytes)
|
|
23
|
-
buf.write(content, 10); // write content here, 10 = 6 + 4
|
|
24
|
-
|
|
25
|
-
} else if (len > 125) {
|
|
26
|
-
|
|
27
|
-
buf = Buffer.alloc(4 + len);
|
|
28
|
-
buf[1] = 126; // 126 = 01111110 means using more 16 bit
|
|
29
|
-
buf.writeUInt16BE(len, 2); // skip the 126 and write length in 16 bits (16 bits = 2 bytes)
|
|
30
|
-
buf.write(content, 4);
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
|
|
34
|
-
buf = Buffer.alloc(2 + len);
|
|
35
|
-
buf[1] = len; // if len7 !== 126 or len7 !== 127, len7 is the content length.
|
|
36
|
-
buf.write(content, 2);
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (options) {
|
|
41
|
-
|
|
42
|
-
const opcode = options.opcode;
|
|
43
|
-
if (opcode && opcode < 15 && opcode >= 0) buf[0] = 128 | opcode; // 128 = 10000000, opcode is of the last 4 bits
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
else buf[0] = 129; // 129 = 10000001, opcode = 0x1
|
|
48
|
-
|
|
49
|
-
return buf;
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Parse meta of a frame from client
|
|
55
|
-
* @param {Buffer} source client buffer Source
|
|
56
|
-
* @returns { Object }
|
|
57
|
-
*/
|
|
58
|
-
function parseFrameMeta(source: Buffer) {
|
|
59
|
-
|
|
60
|
-
const src = Buffer.from(source);
|
|
61
|
-
|
|
62
|
-
const len7 = src[1] & 127; // 127 = 01111111, len7 is of the last 7 bits from the second byte.
|
|
63
|
-
let len = 0; // content length
|
|
64
|
-
let lenMeta = 0; // total length of the frame without the content
|
|
65
|
-
const masked = src[1] >= 128; // 128 = 10000000, the first bit is `masked`, if true it is >= 128
|
|
66
|
-
if (len7 === 127) {
|
|
67
|
-
|
|
68
|
-
len = src.readUInt32BE(6);
|
|
69
|
-
lenMeta = 10;
|
|
70
|
-
|
|
71
|
-
} else if (len7 === 126) {
|
|
72
|
-
|
|
73
|
-
len = src.readUInt16BE(2);
|
|
74
|
-
lenMeta = 4;
|
|
75
|
-
|
|
76
|
-
} else {
|
|
77
|
-
|
|
78
|
-
len = len7;
|
|
79
|
-
lenMeta = 2;
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
fin: src[0] >= 128,
|
|
85
|
-
opcode: src[0] & 15,
|
|
86
|
-
mask: masked,
|
|
87
|
-
maskKey: masked ? src.subarray(lenMeta, lenMeta + (masked ? 4 : 0)) : null,
|
|
88
|
-
len7: len7,
|
|
89
|
-
len: len,
|
|
90
|
-
lenMeta: lenMeta + (masked ? 4 : 0)
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* ws inverse mask
|
|
97
|
-
* @param {String} data source data
|
|
98
|
-
* @param {Buffer|Array} key 4 bytes masking key
|
|
99
|
-
* @returns {String}
|
|
100
|
-
*/
|
|
101
|
-
function iMask(data: Uint8Array, key: Buffer | null) {
|
|
102
|
-
|
|
103
|
-
if (!key) return data;
|
|
104
|
-
|
|
105
|
-
const d = Buffer.from(data);
|
|
106
|
-
for (let i = 0; i < d.length; ++i) d[i] = d[i] ^ key[i % 4]; // 4 in a group to run XOR
|
|
107
|
-
return d;
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* rewrited EventEmitter
|
|
113
|
-
* @constructor
|
|
114
|
-
*/
|
|
115
|
-
function Event(this: any) {
|
|
116
|
-
|
|
117
|
-
const listeners:any = {};
|
|
118
|
-
this.on = (event: string | number, callback: any) => {
|
|
119
|
-
|
|
120
|
-
if (listeners[event]) listeners[event].push(callback);
|
|
121
|
-
else listeners[event] = [callback];
|
|
122
|
-
|
|
123
|
-
};
|
|
124
|
-
this.off = (event: string | number, callback: any) => {
|
|
125
|
-
|
|
126
|
-
const e = listeners[event];
|
|
127
|
-
const i = e.indexOf(callback);
|
|
128
|
-
if (e && i !== -1) e.splice(i, 1);
|
|
129
|
-
|
|
130
|
-
};
|
|
131
|
-
this.emit = (event: string | number, param: any) => {
|
|
132
|
-
|
|
133
|
-
if (listeners[event]) listeners[event].forEach((callback: (arg0: any) => any) => callback(param));
|
|
134
|
-
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
interface DateList {
|
|
139
|
-
l: number;
|
|
140
|
-
f: (d: Uint8Array) => false | void;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Create a WebSocket Server
|
|
144
|
-
* @constructor
|
|
145
|
-
* @param { http.Server } server server from http(s).createServer()
|
|
146
|
-
*/
|
|
147
|
-
function WSS(this: any, server: http.Server) {
|
|
148
|
-
|
|
149
|
-
Event.call(this); // bind WSS to Event to get event feature
|
|
150
|
-
|
|
151
|
-
const clients: { send: any; ping: any; pong: any; close: any; socket: any; }[] = [];
|
|
152
|
-
|
|
153
|
-
this.server = server;
|
|
154
|
-
this.clients = clients;
|
|
155
|
-
|
|
156
|
-
this.broadcast = (data: any) => {
|
|
157
|
-
|
|
158
|
-
clients.forEach((v) => { v.send(data) });
|
|
159
|
-
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
server.on("upgrade", (req, socket) => {
|
|
163
|
-
|
|
164
|
-
socket.write([
|
|
165
|
-
"HTTP/1.1 101 Switching Protocols",
|
|
166
|
-
"Upgrade: websocket",
|
|
167
|
-
"Connection: Upgrade",
|
|
168
|
-
"Sec-WebSocket-Accept: " + crypto.createHash("sha1").update(req.headers['sec-websocket-key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64")
|
|
169
|
-
].join("\n") + "\n\n");
|
|
170
|
-
|
|
171
|
-
const cli:any = { // this is the `cli` parameter when you `connect`
|
|
172
|
-
send(data: string, options: any) {
|
|
173
|
-
|
|
174
|
-
socket.write(createFrame(data, options));
|
|
175
|
-
|
|
176
|
-
},
|
|
177
|
-
ping() {
|
|
178
|
-
|
|
179
|
-
socket.write(createFrame("", { opcode: 9 }));
|
|
180
|
-
|
|
181
|
-
},
|
|
182
|
-
pong() {
|
|
183
|
-
|
|
184
|
-
socket.write(createFrame("", { opcode: 10 }));
|
|
185
|
-
|
|
186
|
-
},
|
|
187
|
-
close() {
|
|
188
|
-
|
|
189
|
-
const cliI = clients.indexOf(cli);
|
|
190
|
-
if (cliI === -1) return false;
|
|
191
|
-
clients.splice(clients.indexOf(cli), 1); // remove client from clients' list
|
|
192
|
-
socket.write(createFrame("", { opcode: 8 })); // send close message to client
|
|
193
|
-
cli.emit("close");
|
|
194
|
-
socket.destroy();
|
|
195
|
-
|
|
196
|
-
},
|
|
197
|
-
socket: socket // you can use `cli.socket` to get the socket object
|
|
198
|
-
};
|
|
199
|
-
Event.call(cli);
|
|
200
|
-
|
|
201
|
-
this.emit("connect", cli); // trigger `connect` event in ws
|
|
202
|
-
clients.push(cli); // push client to clients' list
|
|
203
|
-
|
|
204
|
-
let buf = Buffer.allocUnsafe(0); // unprocessed buffer data
|
|
205
|
-
let messageData = Buffer.allocUnsafe(0); // when a `fin(al)` frame processes, the processed data sends to `message` event
|
|
206
|
-
const dataList: Array<DateList> = []; // unprocessed data list for consuming `buf`
|
|
207
|
-
let frameEnd = true;
|
|
208
|
-
function nextFrame() {
|
|
209
|
-
|
|
210
|
-
const meta = parseFrameMeta(buf);
|
|
211
|
-
dataList.push({
|
|
212
|
-
l: meta.lenMeta, f: () => { // consume `meta.lenMeta` bytes
|
|
213
|
-
|
|
214
|
-
frameEnd = false; // means it is processing meta data, this frame is not completely processed
|
|
215
|
-
dataList.push({
|
|
216
|
-
l: meta.len, f: (d: Uint8Array) => { // consume `meta.len` bytes
|
|
217
|
-
|
|
218
|
-
messageData = Buffer.concat([messageData, iMask(d, meta.maskKey)]); // message += inverse masked data
|
|
219
|
-
frameEnd = true; // set true to start processing a new frame when next `data` comes
|
|
220
|
-
if (meta.fin) { // sometimes you get fragments, before `fin(al)` is true, the message is not completely processed.
|
|
221
|
-
|
|
222
|
-
if (meta.opcode === 8) return cli.close();
|
|
223
|
-
if (meta.opcode === 9) return cli.pong();
|
|
224
|
-
cli.emit("message", messageData); // trigger message event, you finally get this message
|
|
225
|
-
messageData = Buffer.allocUnsafe(0);
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
socket.on("data", (chunk) => { // chunk is the unprocessed data
|
|
238
|
-
|
|
239
|
-
buf = Buffer.concat([buf, chunk]); // buf += chunk
|
|
240
|
-
if (frameEnd) nextFrame();
|
|
241
|
-
while (dataList[0] && buf.byteLength >= dataList[0].l) { // consume `buf` by `dataList`
|
|
242
|
-
|
|
243
|
-
const l = dataList[0].l; // consuming length
|
|
244
|
-
dataList[0].f(buf.subarray(0, l)); // run callback before consuming
|
|
245
|
-
buf = buf.subarray(l); // consume `buf`
|
|
246
|
-
dataList.splice(0, 1); // remove this consume data
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
socket.on("end", () => {
|
|
253
|
-
|
|
254
|
-
cli.close();
|
|
255
|
-
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
socket.on("error", (err) => {
|
|
259
|
-
|
|
260
|
-
cli.emit("error", err);
|
|
261
|
-
cli.close();
|
|
262
|
-
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
module.exports = WSS;
|
package/src/server/encodeUrl.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RegExp to match non-URL code points, *after* encoding (i.e. not including "%")
|
|
3
|
-
* and including invalid escape sequences.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const ENCODE_CHARS_REGEXP =
|
|
7
|
-
/(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^\dA-Fa-f]|[\dA-Fa-f][^\dA-Fa-f]|$))+/g
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* RegExp to match unmatched surrogate pair.
|
|
11
|
-
* @private
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const UNMATCHED_SURROGATE_PAIR_REGEXP =
|
|
15
|
-
/(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* String to replace unmatched surrogate pair with.
|
|
19
|
-
* @private
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
const UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2'
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Encode a URL to a percent-encoded form, excluding already-encoded sequences.
|
|
26
|
-
*
|
|
27
|
-
* This function will take an already-encoded URL and encode all the non-URL
|
|
28
|
-
* code points. This function will not encode the "%" character unless it is
|
|
29
|
-
* not part of a valid sequence (`%20` will be left as-is, but `%foo` will
|
|
30
|
-
* be encoded as `%25foo`).
|
|
31
|
-
*
|
|
32
|
-
* This encode is meant to be "safe" and does not throw errors. It will try as
|
|
33
|
-
* hard as it can to properly encode the given URL, including replacing any raw,
|
|
34
|
-
* unpaired surrogate pairs with the Unicode replacement character prior to
|
|
35
|
-
* encoding.
|
|
36
|
-
*
|
|
37
|
-
* @param {string} url
|
|
38
|
-
* @return {string}
|
|
39
|
-
* @public
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
export default function encodeUrl(url: string): string {
|
|
43
|
-
return String(url)
|
|
44
|
-
.replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE)
|
|
45
|
-
.replace(ENCODE_CHARS_REGEXP, encodeURI)
|
|
46
|
-
}
|
package/src/server/escapeHtml.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const matchHtmlRegExp = /["'&<>]/
|
|
2
|
-
|
|
3
|
-
export default function escapeHtml(string?: string | number | null): string {
|
|
4
|
-
const str = '' + string
|
|
5
|
-
const match = matchHtmlRegExp.exec(str)
|
|
6
|
-
|
|
7
|
-
if (!match) {
|
|
8
|
-
return str
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let escape
|
|
12
|
-
let html = ''
|
|
13
|
-
let index = 0
|
|
14
|
-
let lastIndex = 0
|
|
15
|
-
|
|
16
|
-
for (index = match.index; index < str.length; index++) {
|
|
17
|
-
switch (str.charCodeAt(index)) {
|
|
18
|
-
case 34: // "
|
|
19
|
-
escape = '"'
|
|
20
|
-
break
|
|
21
|
-
case 38: // &
|
|
22
|
-
escape = '&'
|
|
23
|
-
break
|
|
24
|
-
case 39: // '
|
|
25
|
-
escape = '''
|
|
26
|
-
break
|
|
27
|
-
case 60: // <
|
|
28
|
-
escape = '<'
|
|
29
|
-
break
|
|
30
|
-
case 62: // >
|
|
31
|
-
escape = '>'
|
|
32
|
-
break
|
|
33
|
-
default:
|
|
34
|
-
continue
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (lastIndex !== index) {
|
|
38
|
-
html += str.substring(lastIndex, index)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
lastIndex = index + 1
|
|
42
|
-
html += escape
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return lastIndex !== index ? html + str.substring(lastIndex, index) : html
|
|
46
|
-
}
|
package/src/server/get.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import https from 'node:https'
|
|
2
|
-
|
|
3
|
-
interface Request {
|
|
4
|
-
url: string
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
interface Response {
|
|
8
|
-
success: Boolean
|
|
9
|
-
data: unknown
|
|
10
|
-
message: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const get = ({ url }: Request): Promise<Response> => {
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
https
|
|
16
|
-
.get(url, (res) => {
|
|
17
|
-
const list: Array<any> = []
|
|
18
|
-
res.on('data', (chunk) => {
|
|
19
|
-
list.push(chunk)
|
|
20
|
-
})
|
|
21
|
-
res.on('end', () => {
|
|
22
|
-
const { data = [] } = JSON.parse(Buffer.concat(list).toString())
|
|
23
|
-
data.forEach((item: any) => {
|
|
24
|
-
console.log(item)
|
|
25
|
-
})
|
|
26
|
-
resolve({ success: true, data, message: 'request success' })
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
.on('error', (err) => {
|
|
30
|
-
console.log('Error: ', err.message)
|
|
31
|
-
reject({ success: false, data: err, message: err.message })
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default get
|