Skip to content

Commit ed4a95d

Browse files
committed
chore: refactor compiler fns
1 parent e4d6287 commit ed4a95d

File tree

1 file changed

+44
-57
lines changed

1 file changed

+44
-57
lines changed

src/compiler.ts

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,57 @@ import type { MatchedRoute, MethodData, Node, RouterContext } from "./types.ts";
66
// m: method
77
// e: Empty group
88

9+
/**
10+
* Compiles the router instance into a faster route-matching function.
11+
*
12+
* **IMPORTANT:** Compiler is an experimental feature, may contain issues and the API may change between versions.
13+
*
14+
* **IMPORTANT:** This function requires eval (`new Function`) support in the runtime environment for JIT (Just-In-Time)
15+
* compilation.
16+
*
17+
* @example
18+
* import { createRouter, addRoute } from "rou3";
19+
* import { compileRouter } from "rou3/experimental-compiler";
20+
* const router = createRouter();
21+
* // [add some routes]
22+
* const findRoute = compileRouter(router);
23+
* findRoute("GET", "/path/foo/bar");
24+
*
25+
* @param router - The router context to compile.
26+
*/
27+
export function compileRouter<T>(
28+
router: RouterContext<T>,
29+
): (method: string, path: string) => MatchedRoute<T> | undefined {
30+
const deps: any[] = [];
31+
const compiled = _compileRouteMatch(router, deps);
32+
return new Function(
33+
...deps.map((_, i) => "d" + (i + 1)),
34+
`let e={groups:{}};return(m,p)=>{${compiled}}`,
35+
)(...deps);
36+
}
37+
38+
// ------- internal functions -------
39+
940
/**
1041
* Whether the current node has children nodes
1142
* @param n
1243
*/
13-
const _hasChild = (n: Node<any>): boolean =>
14-
n.static != null || n.param != null || n.wildcard != null;
15-
16-
// Skip a native call for common methods
17-
const _fastMethodStringify = (m: string) =>
18-
m === "GET"
19-
? '"GET"'
20-
: m === "POST"
21-
? '"POST"'
22-
: // eslint-disable-next-line
23-
m === "PUT"
24-
? '"PUT"'
25-
: m === "DELETE"
26-
? '"DELETE"'
27-
: JSON.stringify(m);
28-
29-
const _compileMethodMatch = (
44+
function _hasChild(n: Node<any>): boolean {
45+
return n.static != null || n.param != null || n.wildcard != null;
46+
}
47+
48+
function _compileMethodMatch(
3049
methods: Record<string, MethodData<any>[] | undefined>,
3150
params: string[],
3251
deps: any[],
3352
currentIdx: number, // Set to -1 for non-param node
34-
): string => {
53+
): string {
3554
let str = "";
3655
for (const key in methods) {
3756
const data = methods[key];
3857
if (data != null && data.length > 0) {
3958
// Don't check for all method handler
40-
if (key !== "") str += `if(m===${_fastMethodStringify(key)})`;
59+
if (key !== "") str += `if(m==="${key}")`;
4160
let returnData = `return{data:d${deps.push(data[0].data)}`;
4261

4362
// Add param properties
@@ -65,18 +84,18 @@ const _compileMethodMatch = (
6584
}
6685
}
6786
return str;
68-
};
87+
}
6988

7089
/**
7190
* Compile a node to matcher logic
7291
*/
73-
const _compileNode = (
92+
function _compileNode(
7493
node: Node<any>,
7594
params: string[],
7695
startIdx: number,
7796
deps: any[],
7897
isParamNode: boolean,
79-
): string => {
98+
): string {
8099
let str = "";
81100

82101
if (node.methods != null)
@@ -116,17 +135,14 @@ const _compileNode = (
116135
}
117136

118137
return str;
119-
};
138+
}
120139

121140
/**
122141
* Compile a router to pattern matching statements
123142
* @param router
124143
* @param deps - Dependencies of the function scope
125144
*/
126-
const _compileRouteMatch = (
127-
router: RouterContext<any>,
128-
deps: any[],
129-
): string => {
145+
function _compileRouteMatch(router: RouterContext<any>, deps: any[]): string {
130146
// Support trailing slash
131147
let str = "if(p[p.length-1]==='/')p=p.slice(0,-1);";
132148

@@ -141,33 +157,4 @@ const _compileRouteMatch = (
141157
"let s=p.split('/').filter(q=>q!==''),l=s.length;" +
142158
_compileNode(router.root, [], 0, deps, false)
143159
);
144-
};
145-
146-
/**
147-
* Compiles the router instance into a faster route-matching function.
148-
*
149-
* **IMPORTANT:** Compiler is an experimental feature, may contain issues and the API may change between versions.
150-
*
151-
* **IMPORTANT:** This function requires eval (`new Function`) support in the runtime environment for JIT (Just-In-Time)
152-
* compilation.
153-
*
154-
* @example
155-
* import { createRouter, addRoute } from "rou3";
156-
* import { compileRouter } from "rou3/experimental-compiler";
157-
* const router = createRouter();
158-
* // [add some routes]
159-
* const findRoute = compileRouter(router);
160-
* findRoute("GET", "/path/foo/bar");
161-
*
162-
* @param router - The router context to compile.
163-
*/
164-
export const compileRouter = <T>(
165-
router: RouterContext<T>,
166-
): ((method: string, path: string) => MatchedRoute<T> | undefined) => {
167-
const deps: any[] = [];
168-
const compiled = _compileRouteMatch(router, deps);
169-
return new Function(
170-
...deps.map((_, i) => "d" + (i + 1)),
171-
`let e={groups:{}};return(m,p)=>{${compiled}}`,
172-
)(...deps);
173-
};
160+
}

0 commit comments

Comments
 (0)