Skip to content

Commit e23b670

Browse files
committed
perf: optimize predicates for base namespace
Refs #691
1 parent 24a1e25 commit e23b670

File tree

3 files changed

+124
-177
lines changed

3 files changed

+124
-177
lines changed

packages/apidom-core/README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,9 @@ import { createPredicate } from '@swagger-api/apidom-core';
5252

5353
const isMyElement = createPredicate(
5454
({ hasBasicElementProps, isElementType, primitiveEq }) => {
55-
const isElementTypeMyElement = isElementType('myElement');
56-
const primitiveEqObject = primitiveEq('object');
57-
58-
return either(
59-
is(MyElement),
60-
allPass([hasBasicElementProps, isElementTypeMyElement, primitiveEqObject]),
61-
);
55+
return (element) =>
56+
element instanceof MyElement ||
57+
(hasBasicElementProps(element) && isElementType('myElement', element) && primitiveEq('object', element));
6258
},
6359
);
6460
```
Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
1-
import { both, curry, has, pathSatisfies, curryN, pathEq, Pred } from 'ramda';
2-
import { isFunction, invokeArgs } from 'ramda-adjunct';
1+
const hasMethod = (name: string, obj: Record<string, unknown>): boolean =>
2+
typeof obj?.[name] === 'function';
33

4-
const hasMethod = curry((name: string, obj: Record<string, unknown>): boolean =>
5-
pathSatisfies(isFunction, [name], obj),
6-
);
4+
const hasBasicElementProps = (element: any) =>
5+
element != null &&
6+
Object.prototype.hasOwnProperty.call(element, '_storedElement') &&
7+
Object.prototype.hasOwnProperty.call(element, '_content');
78

8-
const hasBasicElementProps = both(has('_storedElement'), has('_content'));
9+
const primitiveEq = (val: unknown, obj: any): boolean => obj?.primitive?.() === val;
910

10-
const primitiveEq = curry(
11-
(val: unknown, obj: Record<string, unknown>): boolean =>
12-
invokeArgs(['primitive'], [], obj) === val,
13-
);
11+
const hasClass = (cls: string, obj: any): boolean => obj?.classes?.includes?.(cls) || false;
1412

15-
const hasClass = curry((cls: string, obj: Record<string, unknown>): boolean =>
16-
invokeArgs(['classes', 'includes'], [cls], obj),
17-
);
18-
19-
export const isElementType = pathEq(['element']);
13+
export const isElementType = (name: string, element: any): boolean => element?.element === name;
2014

2115
interface PredicateHelpers {
2216
hasMethod: typeof hasMethod;
@@ -26,20 +20,17 @@ interface PredicateHelpers {
2620
hasClass: typeof hasClass;
2721
}
2822

29-
type PredicateCreator = (helpers: PredicateHelpers) => Pred;
23+
type PredicateCreator = (helpers: PredicateHelpers) => (element: any) => boolean;
3024

31-
const createPredicate = (predicateCreator: PredicateCreator): Pred => {
25+
const createPredicate = (predicateCreator: PredicateCreator) => {
3226
// @ts-ignore
33-
return curryN(
34-
1,
35-
predicateCreator({
36-
hasMethod,
37-
hasBasicElementProps,
38-
primitiveEq,
39-
isElementType,
40-
hasClass,
41-
}),
42-
);
27+
return predicateCreator({
28+
hasMethod,
29+
hasBasicElementProps,
30+
primitiveEq,
31+
isElementType,
32+
hasClass,
33+
});
4334
};
4435

4536
export default createPredicate;

packages/apidom-core/src/predicates/index.ts

Lines changed: 103 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
LinkElement,
1111
RefElement,
1212
} from 'minim';
13-
import { all, isEmpty, either, curry, allPass, is, both, anyPass } from 'ramda';
13+
import { all } from 'ramda';
1414
import { included } from 'ramda-adjunct';
1515

1616
import AnnotationElement from '../elements/Annotation';
@@ -20,204 +20,164 @@ import SourceMapElement from '../elements/SourceMap';
2020
import createPredicate, { isElementType as isElementTypeHelper } from './helpers';
2121

2222
export const isElement = createPredicate(({ hasBasicElementProps, primitiveEq }) => {
23-
const primitiveEqUndefined = primitiveEq(undefined);
24-
25-
return either(is(Element), both(hasBasicElementProps, primitiveEqUndefined));
23+
return (element: any) =>
24+
element instanceof Element ||
25+
(hasBasicElementProps(element) && primitiveEq(undefined, element));
2626
});
2727

2828
export const isStringElement = createPredicate(({ hasBasicElementProps, primitiveEq }) => {
29-
const primitiveEqString = primitiveEq('string');
30-
31-
return either(is(StringElement), allPass([hasBasicElementProps, primitiveEqString]));
29+
return (element: any) =>
30+
element instanceof StringElement ||
31+
(hasBasicElementProps(element) && primitiveEq('string', element));
3232
});
3333

3434
export const isNumberElement = createPredicate(({ hasBasicElementProps, primitiveEq }) => {
35-
const primitiveEqNumber = primitiveEq('number');
36-
37-
return either(is(NumberElement), allPass([hasBasicElementProps, primitiveEqNumber]));
35+
return (element: any) =>
36+
element instanceof NumberElement ||
37+
(hasBasicElementProps(element) && primitiveEq('number', element));
3838
});
3939

4040
export const isNullElement = createPredicate(({ hasBasicElementProps, primitiveEq }) => {
41-
const primitiveEqNull = primitiveEq('null');
42-
43-
return either(is(NullElement), allPass([hasBasicElementProps, primitiveEqNull]));
41+
return (element: any) =>
42+
element instanceof NullElement ||
43+
(hasBasicElementProps(element) && primitiveEq('null', element));
4444
});
4545

4646
export const isBooleanElement = createPredicate(({ hasBasicElementProps, primitiveEq }) => {
47-
const primitiveEqBoolean = primitiveEq('boolean');
48-
49-
return either(is(BooleanElement), allPass([hasBasicElementProps, primitiveEqBoolean]));
47+
return (element: any) =>
48+
element instanceof BooleanElement ||
49+
(hasBasicElementProps(element) && primitiveEq('boolean', element));
5050
});
5151

5252
export const isArrayElement = createPredicate(
5353
({ hasBasicElementProps, primitiveEq, hasMethod }) => {
54-
const primitiveEqArray = primitiveEq('array');
55-
const hasMethodPush = hasMethod('push');
56-
const hasMethodUnshift = hasMethod('unshift');
57-
const hasMethodMap = hasMethod('map');
58-
const hasMethodReduce = hasMethod('reduce');
59-
60-
return either(
61-
is(ArrayElement),
62-
allPass([
63-
hasBasicElementProps,
64-
primitiveEqArray,
65-
hasMethodPush,
66-
hasMethodUnshift,
67-
hasMethodMap,
68-
hasMethodReduce,
69-
]),
70-
);
54+
return (element: any) =>
55+
element instanceof ArrayElement ||
56+
(hasBasicElementProps(element) &&
57+
primitiveEq('array', element) &&
58+
hasMethod('push', element) &&
59+
hasMethod('unshift', element) &&
60+
hasMethod('map', element) &&
61+
hasMethod('reduce', element));
7162
},
7263
);
7364

7465
export const isObjectElement = createPredicate(
7566
({ hasBasicElementProps, primitiveEq, hasMethod }) => {
76-
const primitiveEqObject = primitiveEq('object');
77-
const hasMethodKeys = hasMethod('keys');
78-
const hasMethodValues = hasMethod('values');
79-
const hasMethodItems = hasMethod('items');
80-
81-
return either(
82-
is(ObjectElement),
83-
allPass([
84-
hasBasicElementProps,
85-
primitiveEqObject,
86-
hasMethodKeys,
87-
hasMethodValues,
88-
hasMethodItems,
89-
]),
90-
);
67+
return (element: any) =>
68+
element instanceof ObjectElement ||
69+
(hasBasicElementProps(element) &&
70+
primitiveEq('object', element) &&
71+
hasMethod('keys', element) &&
72+
hasMethod('values', element) &&
73+
hasMethod('items', element));
9174
},
9275
);
9376

9477
export const isMemberElement = createPredicate(
9578
({ hasBasicElementProps, isElementType, primitiveEq }) => {
96-
const isElementTypeMember = isElementType('member');
97-
const primitiveEqUndefined = primitiveEq(undefined);
98-
99-
return either(
100-
is(MemberElement),
101-
allPass([hasBasicElementProps, isElementTypeMember, primitiveEqUndefined]),
102-
);
79+
return (element: any) =>
80+
element instanceof MemberElement ||
81+
(hasBasicElementProps(element) &&
82+
isElementType('member', element) &&
83+
primitiveEq(undefined, element));
10384
},
10485
);
10586

10687
export const isLinkElement = createPredicate(
10788
({ hasBasicElementProps, isElementType, primitiveEq }) => {
108-
const isElementTypeLink = isElementType('link');
109-
const primitiveEqUndefined = primitiveEq(undefined);
110-
111-
return either(
112-
is(LinkElement),
113-
allPass([hasBasicElementProps, isElementTypeLink, primitiveEqUndefined]),
114-
);
89+
return (element: any) =>
90+
element instanceof LinkElement ||
91+
(hasBasicElementProps(element) &&
92+
isElementType('link', element) &&
93+
primitiveEq(undefined, element));
11594
},
11695
);
11796

11897
export const isRefElement = createPredicate(
11998
({ hasBasicElementProps, isElementType, primitiveEq }) => {
120-
const isElementTypeRef = isElementType('ref');
121-
const primitiveEqUndefined = primitiveEq(undefined);
122-
123-
return either(
124-
is(RefElement),
125-
allPass([hasBasicElementProps, isElementTypeRef, primitiveEqUndefined]),
126-
);
99+
return (element: any) =>
100+
element instanceof RefElement ||
101+
(hasBasicElementProps(element) &&
102+
isElementType('ref', element) &&
103+
primitiveEq(undefined, element));
127104
},
128105
);
129106

130107
export const isAnnotationElement = createPredicate(
131108
({ hasBasicElementProps, isElementType, primitiveEq }) => {
132-
const isElementTypeAnnotation = isElementType('annotation');
133-
const primitiveEqString = primitiveEq('array');
134-
135-
return either(
136-
is(AnnotationElement),
137-
allPass([hasBasicElementProps, isElementTypeAnnotation, primitiveEqString]),
138-
);
109+
return (element: any) =>
110+
element instanceof AnnotationElement ||
111+
(hasBasicElementProps(element) &&
112+
isElementType('annotation', element) &&
113+
primitiveEq('array', element));
139114
},
140115
);
141116

142117
export const isCommentElement = createPredicate(
143118
({ hasBasicElementProps, isElementType, primitiveEq }) => {
144-
const isElementTypeComment = isElementType('comment');
145-
const primitiveEqString = primitiveEq('string');
146-
147-
return either(
148-
is(CommentElement),
149-
allPass([hasBasicElementProps, isElementTypeComment, primitiveEqString]),
150-
);
119+
return (element: any) =>
120+
element instanceof CommentElement ||
121+
(hasBasicElementProps(element) &&
122+
isElementType('comment', element) &&
123+
primitiveEq('string', element));
151124
},
152125
);
153126

154127
export const isParseResultElement = createPredicate(
155128
({ hasBasicElementProps, isElementType, primitiveEq }) => {
156-
const isElementTypeParseResult = isElementType('parseResult');
157-
const primitiveEqString = primitiveEq('array');
158-
159-
return either(
160-
is(ParserResultElement),
161-
allPass([hasBasicElementProps, isElementTypeParseResult, primitiveEqString]),
162-
);
129+
return (element: any) =>
130+
element instanceof ParserResultElement ||
131+
(hasBasicElementProps(element) &&
132+
isElementType('parseResult', element) &&
133+
primitiveEq('array', element));
163134
},
164135
);
165136

166137
export const isSourceMapElement = createPredicate(
167138
({ hasBasicElementProps, isElementType, primitiveEq }) => {
168-
const isElementTypeSourceMap = isElementType('sourceMap');
169-
const primitiveEqArray = primitiveEq('array');
170-
171-
return either(
172-
is(SourceMapElement),
173-
allPass([hasBasicElementProps, isElementTypeSourceMap, primitiveEqArray]),
174-
);
139+
return (element: any) =>
140+
element instanceof SourceMapElement ||
141+
(hasBasicElementProps(element) &&
142+
isElementType('sourceMap', element) &&
143+
primitiveEq('array', element));
175144
},
176145
);
177146

178-
export const isPrimitiveElement = anyPass([
179-
// @ts-ignore
180-
isElementTypeHelper('object'),
181-
// @ts-ignore
182-
isElementTypeHelper('array'),
183-
// @ts-ignore
184-
isElementTypeHelper('member'),
185-
// @ts-ignore
186-
isElementTypeHelper('boolean'),
187-
// @ts-ignore
188-
isElementTypeHelper('number'),
189-
// @ts-ignore
190-
isElementTypeHelper('string'),
191-
// @ts-ignore
192-
isElementTypeHelper('null'),
193-
]);
194-
195-
export const hasElementSourceMap = createPredicate(() => {
196-
return (element) => isSourceMapElement(element.meta.get('sourceMap'));
197-
});
198-
199-
export const includesSymbols = curry(
200-
<T extends Element>(symbols: string[], element: T): boolean => {
201-
if (isEmpty(symbols)) {
202-
return true;
203-
}
204-
205-
const elementSymbols = element.attributes.get('symbols');
206-
207-
if (!isArrayElement(elementSymbols)) {
208-
return false;
209-
}
210-
211-
return all(included(elementSymbols.toValue()), symbols);
212-
},
213-
);
214-
215-
export const includesClasses = curry(
216-
<T extends Element>(classes: string[], element: T): boolean => {
217-
if (isEmpty(classes)) {
218-
return true;
219-
}
220-
221-
return all(included(element.classes.toValue()), classes);
222-
},
223-
);
147+
export const isPrimitiveElement = (element: any): boolean => {
148+
return (
149+
isElementTypeHelper('object', element) ||
150+
isElementTypeHelper('array', element) ||
151+
isElementTypeHelper('boolean', element) ||
152+
isElementTypeHelper('number', element) ||
153+
isElementTypeHelper('string', element) ||
154+
isElementTypeHelper('null', element) ||
155+
isElementTypeHelper('member', element)
156+
);
157+
};
158+
159+
export const hasElementSourceMap = (element: any): boolean => {
160+
return isSourceMapElement(element?.meta?.get?.('sourceMap'));
161+
};
162+
163+
export const includesSymbols = <T extends Element>(symbols: string[], element: T): boolean => {
164+
if (symbols.length === 0) {
165+
return true;
166+
}
167+
168+
const elementSymbols = element.attributes.get('symbols');
169+
170+
if (!isArrayElement(elementSymbols)) {
171+
return false;
172+
}
173+
174+
return all(included(elementSymbols.toValue()), symbols);
175+
};
176+
177+
export const includesClasses = <T extends Element>(classes: string[], element: T): boolean => {
178+
if (classes.length === 0) {
179+
return true;
180+
}
181+
182+
return all(included(element.classes.toValue()), classes);
183+
};

0 commit comments

Comments
 (0)