assign-gingerly 0.0.72 → 0.0.74
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/README.md +29 -92
- package/assignFeatures.js +145 -254
- package/assignFeatures.ts +713 -837
- package/assignFrom.ts +1 -1
- package/assignFromAsync.ts +1 -1
- package/assignGingerly.js +1 -1
- package/assignGingerly.ts +3 -2
- package/assignPermissions/isAllowedImportPath.js +41 -0
- package/assignPermissions/isAllowedImportPath.ts +38 -0
- package/assignPermissions/restrictedProps.js +43 -0
- package/assignPermissions/restrictedProps.ts +53 -0
- package/assignTentatively.js +1 -1
- package/assignTentatively.ts +2 -2
- package/defineWithFeatures.js +12 -72
- package/defineWithFeatures.ts +92 -167
- package/eachTime.js +1 -1
- package/eachTime.ts +3 -2
- package/enhanceAll.js +10 -6
- package/enhanceAll.ts +11 -10
- package/handlers/addEventListener.ts +1 -1
- package/handlers/lazyLoad.ts +1 -1
- package/handlers/lazyLoadSwitch.ts +1 -1
- package/handlers/manageTemplateList.ts +1 -1
- package/handlers/rangeSelector.ts +1 -1
- package/inferencer/types/assign-gingerly/types.d.ts +5 -2
- package/inferencer/types/font-face-feature/types.d.ts +9 -0
- package/inferencer/types/nested-regex-groups/types.d.ts +12 -0
- package/package.json +13 -4
- package/processHandlerCommands.js +12 -34
- package/processHandlerCommands.ts +15 -41
- package/resolveAndAssignFeatures.js +9 -40
- package/resolveAndAssignFeatures.ts +43 -79
- package/types/assign-gingerly/types.d.ts +13 -25
- package/isAllowedImportPath.js +0 -104
- package/isAllowedImportPath.ts +0 -118
package/enhanceAll.js
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* { emc: 'be-observant/emc.json', matching: '[itemprop]' },
|
|
16
16
|
* ]);
|
|
17
17
|
*/
|
|
18
|
-
import { isAllowedImportPath } from './isAllowedImportPath.js';
|
|
18
|
+
import { isAllowedImportPath } from './assignPermissions/isAllowedImportPath.js';
|
|
19
|
+
import { findClassPrototypeInPath } from './utils/findClassPrototypeInPath.js';
|
|
19
20
|
/**
|
|
20
21
|
* Apply enhancements in bulk to matching elements within a target.
|
|
21
22
|
*
|
|
@@ -37,7 +38,7 @@ export async function enhanceAll(target, configs, permissions) {
|
|
|
37
38
|
// Validate EMC path unless cross-domain imports are explicitly permitted
|
|
38
39
|
if (!permissions?.crossDomainImports && !isAllowedImportPath(config.emc)) {
|
|
39
40
|
throw new Error(`enhanceAll: EMC path "${config.emc}" is a cross-domain URL. ` +
|
|
40
|
-
`Only
|
|
41
|
+
`Only same-origin paths or import-map-covered specifiers are allowed by default. ` +
|
|
41
42
|
`Pass { crossDomainImports: true } in permissions to override.`);
|
|
42
43
|
}
|
|
43
44
|
// 1. Import the EMC JSON
|
|
@@ -85,13 +86,16 @@ async function resolveAndRegister(enhConfig, target) {
|
|
|
85
86
|
if (existing)
|
|
86
87
|
return existing;
|
|
87
88
|
}
|
|
88
|
-
// Not registered — dynamically import the spawn module
|
|
89
|
+
// Not registered — dynamically import the spawn module and extract the spawn class
|
|
89
90
|
if (!spawnPath)
|
|
90
91
|
return null;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
let SpawnClass;
|
|
93
|
+
try {
|
|
94
|
+
SpawnClass = await findClassPrototypeInPath(spawnPath);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
94
97
|
return null;
|
|
98
|
+
}
|
|
95
99
|
// Build and register the registry item
|
|
96
100
|
const registryItem = {
|
|
97
101
|
spawn: SpawnClass,
|
package/enhanceAll.ts
CHANGED
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
* ]);
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { isAllowedImportPath } from './isAllowedImportPath.js';
|
|
20
|
-
import
|
|
19
|
+
import { isAllowedImportPath } from './assignPermissions/isAllowedImportPath.js';
|
|
20
|
+
import { findClassPrototypeInPath } from './utils/findClassPrototypeInPath.js';
|
|
21
|
+
import type { AssignPermissions } from './types/assign-gingerly/types.js';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Configuration for a single enhancement to apply in bulk.
|
|
@@ -57,7 +58,7 @@ export async function enhanceAll(
|
|
|
57
58
|
if (!permissions?.crossDomainImports && !isAllowedImportPath(config.emc)) {
|
|
58
59
|
throw new Error(
|
|
59
60
|
`enhanceAll: EMC path "${config.emc}" is a cross-domain URL. ` +
|
|
60
|
-
`Only
|
|
61
|
+
`Only same-origin paths or import-map-covered specifiers are allowed by default. ` +
|
|
61
62
|
`Pass { crossDomainImports: true } in permissions to override.`
|
|
62
63
|
);
|
|
63
64
|
}
|
|
@@ -112,15 +113,15 @@ async function resolveAndRegister(enhConfig: any, target: Element): Promise<any>
|
|
|
112
113
|
if (existing) return existing;
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
// Not registered — dynamically import the spawn module
|
|
116
|
+
// Not registered — dynamically import the spawn module and extract the spawn class
|
|
116
117
|
if (!spawnPath) return null;
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
let SpawnClass;
|
|
120
|
+
try {
|
|
121
|
+
SpawnClass = await findClassPrototypeInPath(spawnPath);
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
124
125
|
|
|
125
126
|
// Build and register the registry item
|
|
126
127
|
const registryItem: any = {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import assignGingerly from '../assignGingerly.js';
|
|
11
11
|
import type { AddEventListenerConfig, AssignDispatchVector } from '../types/assign-gingerly/types.js';
|
|
12
|
-
import type { AssignPermissions } from '../
|
|
12
|
+
import type { AssignPermissions } from '../types/assign-gingerly/types.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* WeakMap for dedup: Element → Map<key, AbortController>
|
package/handlers/lazyLoad.ts
CHANGED
|
@@ -24,7 +24,7 @@ import type { LazyLoadResolvedParams, LazyLoadInstantiatedContext } from '../typ
|
|
|
24
24
|
import { withTransition, ensureHideStyle, DEFAULT_HIDE_CLASS } from '../transitionHelper.js';
|
|
25
25
|
import { findMarkers, createMarkers, getNodesBetweenMarkers, findMarkersSibling, createMarkersSibling, MARKER_START_PREFIX, MARKER_END } from '../markerUtils.js';
|
|
26
26
|
import { assignFrom } from '../assignFrom.js';
|
|
27
|
-
import type { AssignPermissions } from '../
|
|
27
|
+
import type { AssignPermissions } from '../types/assign-gingerly/types.js';
|
|
28
28
|
|
|
29
29
|
export type { LazyLoadResolvedParams, LazyLoadInstantiatedContext };
|
|
30
30
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { LazyLoadHandler } from './lazyLoad.js';
|
|
24
|
-
import type { AssignPermissions } from '../
|
|
24
|
+
import type { AssignPermissions } from '../types/assign-gingerly/types.js';
|
|
25
25
|
import type { AssignFromHandler } from '../assignFromAsync.js';
|
|
26
26
|
import type { LazyLoadSwitchResolvedParams } from '../types/assign-gingerly/types.js';
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@ import { findMarkers, createMarkers, getNodesBetweenMarkers, MARKER_START_PREFIX
|
|
|
31
31
|
import { resolveValue } from '../resolveValues.js';
|
|
32
32
|
import { assignFrom } from '../assignFrom.js';
|
|
33
33
|
import { processInferredAssignments } from '../inferredAssignments.js';
|
|
34
|
-
import type { AssignPermissions } from '../
|
|
34
|
+
import type { AssignPermissions } from '../types/assign-gingerly/types.js';
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Reserved keys in fromEachItem config — not treated as shorthand patterns.
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import type { AssignFromHandler } from '../assignFromAsync.js';
|
|
25
25
|
import assignGingerly from '../assignGingerly.js';
|
|
26
|
-
import type { AssignPermissions } from '../
|
|
26
|
+
import type { AssignPermissions } from '../types/assign-gingerly/types.js';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Operator keys recognized in case objects.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {ParserOptions} from '../nested-regex-groups/types.js';
|
|
2
|
+
|
|
1
3
|
export type EnhKey = string | symbol;
|
|
2
4
|
|
|
3
5
|
// type NoUnderscore<T extends string> = T extends `_${string}` ? never : T;
|
|
@@ -196,7 +198,7 @@ export interface AttrConfig<T = unknown, TParserConfig = unknown> {
|
|
|
196
198
|
* For named parsers like 'parse-pattern-statements', this is forwarded
|
|
197
199
|
* as the options argument to the underlying parse function.
|
|
198
200
|
*/
|
|
199
|
-
parserOptions?:
|
|
201
|
+
parserOptions?: ParserOptions;
|
|
200
202
|
}
|
|
201
203
|
|
|
202
204
|
export type AttrPatterns<T = any> = {
|
|
@@ -613,7 +615,8 @@ export interface FeatureConfig {
|
|
|
613
615
|
*/
|
|
614
616
|
spawn?:
|
|
615
617
|
| { new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }
|
|
616
|
-
| (() => Promise<{ new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }>)
|
|
618
|
+
| (() => Promise<{ new(hostElement: any, ctx: FeatureSpawnContext, initVals?: any): any }>)
|
|
619
|
+
| string // import path or builtIns.* alias
|
|
617
620
|
|
|
618
621
|
/** Attribute patterns for parsing element attributes into initVals. */
|
|
619
622
|
withAttrs?: AttrPatterns<any>;
|
|
@@ -91,6 +91,18 @@ export interface ParserOptions {
|
|
|
91
91
|
* as statement delimiters during splitting.
|
|
92
92
|
*/
|
|
93
93
|
ignorePeriodInsideBraces?: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* When true, normalizes whitespace in the input string before parsing.
|
|
97
|
+
* This replaces multiple whitespace characters with a single space and trims the string.
|
|
98
|
+
* Default is false.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // Input: " First. Second. "
|
|
102
|
+
* // With normalizeWhitespace: true -> "First. Second."
|
|
103
|
+
* // With normalizeWhitespace: false -> " First. Second. "
|
|
104
|
+
*/
|
|
105
|
+
normalizeWhitespace?: boolean;
|
|
94
106
|
}
|
|
95
107
|
|
|
96
108
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assign-gingerly",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.74",
|
|
4
4
|
"description": "This package provides a utility function for carefully merging one object into another.",
|
|
5
5
|
"homepage": "https://github.com/bahrus/assign-gingerly#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"*.js",
|
|
19
19
|
"*.ts",
|
|
20
20
|
"DX/**",
|
|
21
|
+
"assignPermissions/**",
|
|
21
22
|
"handlers/**",
|
|
22
23
|
"inferencer/**",
|
|
23
24
|
"README.md",
|
|
@@ -143,9 +144,17 @@
|
|
|
143
144
|
"default": "./enhanceAll.js",
|
|
144
145
|
"types": "./enhanceAll.ts"
|
|
145
146
|
},
|
|
146
|
-
"./isAllowedImportPath.js": {
|
|
147
|
-
"default": "./isAllowedImportPath.js",
|
|
148
|
-
"types": "./isAllowedImportPath.ts"
|
|
147
|
+
"./assignPermissions/isAllowedImportPath.js": {
|
|
148
|
+
"default": "./assignPermissions/isAllowedImportPath.js",
|
|
149
|
+
"types": "./assignPermissions/isAllowedImportPath.ts"
|
|
150
|
+
},
|
|
151
|
+
"./utils/findClassPrototypeInPath.js": {
|
|
152
|
+
"default": "./utils/findClassPrototypeInPath.js",
|
|
153
|
+
"types": "./utils/findClassPrototypeInPath.ts"
|
|
154
|
+
},
|
|
155
|
+
"./utils/isAsyncSpawn.js": {
|
|
156
|
+
"default": "./utils/isAsyncSpawn.js",
|
|
157
|
+
"types": "./utils/isAsyncSpawn.ts"
|
|
149
158
|
},
|
|
150
159
|
"./markerUtils.js": {
|
|
151
160
|
"default": "./markerUtils.js",
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
import { resolveValues } from './resolveValues.js';
|
|
7
7
|
import { getValues } from './getValues.js';
|
|
8
8
|
import { evaluatePathWithMethods } from './assignGingerly.js';
|
|
9
|
-
import {
|
|
9
|
+
import { findClassPrototypeInPath } from './utils/findClassPrototypeInPath.js';
|
|
10
|
+
import { buildRestrictedPropSet, redirectRestrictedProp } from './assignPermissions/restrictedProps.js';
|
|
10
11
|
/**
|
|
11
12
|
* Map of built-in handler names to their module paths.
|
|
12
13
|
* These are auto-loaded on demand — no explicit import required.
|
|
@@ -20,23 +21,11 @@ const BUILT_IN_MAP = {
|
|
|
20
21
|
'builtIns.rangeSelector': './handlers/rangeSelector.js',
|
|
21
22
|
};
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
24
|
+
* Criteria for locating an assignFrom handler class: must expose an `assign` method
|
|
25
|
+
* on its prototype.
|
|
25
26
|
*/
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
if (module.default && typeof module.default === 'function'
|
|
29
|
-
&& module.default.prototype && 'assign' in module.default.prototype) {
|
|
30
|
-
return module.default;
|
|
31
|
-
}
|
|
32
|
-
// Search other exports
|
|
33
|
-
for (const key of Object.keys(module)) {
|
|
34
|
-
const exported = module[key];
|
|
35
|
-
if (typeof exported === 'function' && exported.prototype && 'assign' in exported.prototype) {
|
|
36
|
-
return exported;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
27
|
+
function handlerCriteria(proto) {
|
|
28
|
+
return 'assign' in proto.prototype;
|
|
40
29
|
}
|
|
41
30
|
/**
|
|
42
31
|
* Cache for loaded built-in handler classes — avoids await on subsequent calls.
|
|
@@ -54,16 +43,14 @@ async function loadBuiltIn(name) {
|
|
|
54
43
|
const path = BUILT_IN_MAP[name];
|
|
55
44
|
if (!path)
|
|
56
45
|
return undefined;
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
if (cls)
|
|
60
|
-
handlerCache.set(name, cls);
|
|
46
|
+
const cls = await findClassPrototypeInPath(path, handlerCriteria);
|
|
47
|
+
handlerCache.set(name, cls);
|
|
61
48
|
return cls;
|
|
62
49
|
}
|
|
63
50
|
/**
|
|
64
51
|
* Resolve a handler from options.handlers (class constructor or import path).
|
|
65
52
|
*/
|
|
66
|
-
async function resolveFromHandlers(name, handlers
|
|
53
|
+
async function resolveFromHandlers(name, handlers) {
|
|
67
54
|
if (!handlers || !(name in handlers))
|
|
68
55
|
return undefined;
|
|
69
56
|
const entry = handlers[name];
|
|
@@ -77,17 +64,8 @@ async function resolveFromHandlers(name, handlers, permissions) {
|
|
|
77
64
|
if (entry.startsWith('builtIns.')) {
|
|
78
65
|
return loadBuiltIn(entry);
|
|
79
66
|
}
|
|
80
|
-
// Import path string — validate and
|
|
81
|
-
|
|
82
|
-
throw new Error(`assignFrom: handler "${name}" has an invalid import path "${entry}". ` +
|
|
83
|
-
`Only relative, absolute, or bare specifier paths are allowed (no cross-domain URLs). ` +
|
|
84
|
-
`Pass { crossDomainImports: true } in permissions to override.`);
|
|
85
|
-
}
|
|
86
|
-
const module = await import(entry);
|
|
87
|
-
const HandlerClass = findHandlerInModule(module);
|
|
88
|
-
if (!HandlerClass) {
|
|
89
|
-
throw new Error(`assignFrom: handler "${name}" — module "${entry}" does not export a valid handler class.`);
|
|
90
|
-
}
|
|
67
|
+
// Import path string — validate and extract handler class via shared utility
|
|
68
|
+
const HandlerClass = await findClassPrototypeInPath(entry, handlerCriteria);
|
|
91
69
|
return HandlerClass;
|
|
92
70
|
}
|
|
93
71
|
return undefined;
|
|
@@ -179,7 +157,7 @@ export async function processHandlerCommands(target, handlerKeys, pattern, optio
|
|
|
179
157
|
for (const config of configs) {
|
|
180
158
|
//return; //1.3ms
|
|
181
159
|
// 1. Check options.handlers (local, per-call)
|
|
182
|
-
let HandlerClass = await resolveFromHandlers(config.do, options.handlers
|
|
160
|
+
let HandlerClass = await resolveFromHandlers(config.do, options.handlers);
|
|
183
161
|
//return; // 1.4
|
|
184
162
|
// 2. Fallback to built-in auto-load
|
|
185
163
|
if (!HandlerClass && config.do.startsWith('builtIns.')) {
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { resolveValues } from './resolveValues.js';
|
|
8
8
|
import { getValues } from './getValues.js';
|
|
9
9
|
import { evaluatePathWithMethods } from './assignGingerly.js';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
10
|
+
import { findClassPrototypeInPath } from './utils/findClassPrototypeInPath.js';
|
|
11
|
+
import { buildRestrictedPropSet, redirectRestrictedProp } from './assignPermissions/restrictedProps.js';
|
|
12
|
+
import type { AssignPermissions } from './types/assign-gingerly/types.js';
|
|
12
13
|
import type { AssignFromOptions, AssignFromHandlerConstructor } from './assignFromAsync.js';
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -25,23 +26,11 @@ const BUILT_IN_MAP: Record<string, string> = {
|
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
29
|
+
* Criteria for locating an assignFrom handler class: must expose an `assign` method
|
|
30
|
+
* on its prototype.
|
|
30
31
|
*/
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
if (module.default && typeof module.default === 'function'
|
|
34
|
-
&& module.default.prototype && 'assign' in module.default.prototype) {
|
|
35
|
-
return module.default;
|
|
36
|
-
}
|
|
37
|
-
// Search other exports
|
|
38
|
-
for (const key of Object.keys(module)) {
|
|
39
|
-
const exported = module[key];
|
|
40
|
-
if (typeof exported === 'function' && exported.prototype && 'assign' in exported.prototype) {
|
|
41
|
-
return exported as AssignFromHandlerConstructor;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return undefined;
|
|
32
|
+
function handlerCriteria(proto: any): boolean {
|
|
33
|
+
return 'assign' in proto.prototype;
|
|
45
34
|
}
|
|
46
35
|
|
|
47
36
|
/**
|
|
@@ -59,10 +48,9 @@ async function loadBuiltIn(name: string): Promise<AssignFromHandlerConstructor |
|
|
|
59
48
|
if (cached) return cached;
|
|
60
49
|
const path = BUILT_IN_MAP[name];
|
|
61
50
|
if (!path) return undefined;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return cls;
|
|
51
|
+
const cls = await findClassPrototypeInPath(path, handlerCriteria);
|
|
52
|
+
handlerCache.set(name, cls);
|
|
53
|
+
return cls as AssignFromHandlerConstructor;
|
|
66
54
|
}
|
|
67
55
|
|
|
68
56
|
/**
|
|
@@ -70,8 +58,7 @@ async function loadBuiltIn(name: string): Promise<AssignFromHandlerConstructor |
|
|
|
70
58
|
*/
|
|
71
59
|
async function resolveFromHandlers(
|
|
72
60
|
name: string,
|
|
73
|
-
handlers: Record<string, AssignFromHandlerConstructor | string> | undefined
|
|
74
|
-
permissions?: AssignPermissions
|
|
61
|
+
handlers: Record<string, AssignFromHandlerConstructor | string> | undefined
|
|
75
62
|
): Promise<AssignFromHandlerConstructor | undefined> {
|
|
76
63
|
if (!handlers || !(name in handlers)) return undefined;
|
|
77
64
|
|
|
@@ -89,22 +76,9 @@ async function resolveFromHandlers(
|
|
|
89
76
|
return loadBuiltIn(entry);
|
|
90
77
|
}
|
|
91
78
|
|
|
92
|
-
// Import path string — validate and
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
`assignFrom: handler "${name}" has an invalid import path "${entry}". ` +
|
|
96
|
-
`Only relative, absolute, or bare specifier paths are allowed (no cross-domain URLs). ` +
|
|
97
|
-
`Pass { crossDomainImports: true } in permissions to override.`
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
const module = await import(entry);
|
|
101
|
-
const HandlerClass = findHandlerInModule(module);
|
|
102
|
-
if (!HandlerClass) {
|
|
103
|
-
throw new Error(
|
|
104
|
-
`assignFrom: handler "${name}" — module "${entry}" does not export a valid handler class.`
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
return HandlerClass;
|
|
79
|
+
// Import path string — validate and extract handler class via shared utility
|
|
80
|
+
const HandlerClass = await findClassPrototypeInPath(entry, handlerCriteria);
|
|
81
|
+
return HandlerClass as AssignFromHandlerConstructor;
|
|
108
82
|
}
|
|
109
83
|
|
|
110
84
|
return undefined;
|
|
@@ -203,7 +177,7 @@ export async function processHandlerCommands(
|
|
|
203
177
|
for (const config of configs) {
|
|
204
178
|
//return; //1.3ms
|
|
205
179
|
// 1. Check options.handlers (local, per-call)
|
|
206
|
-
let HandlerClass = await resolveFromHandlers(config.do, options.handlers
|
|
180
|
+
let HandlerClass = await resolveFromHandlers(config.do, options.handlers);
|
|
207
181
|
//return; // 1.4
|
|
208
182
|
// 2. Fallback to built-in auto-load
|
|
209
183
|
if (!HandlerClass && config.do.startsWith('builtIns.')) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* resolveAndAssignFeatures -
|
|
2
|
+
* resolveAndAssignFeatures - Thin wrapper around assignFeatures for backward compatibility.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Resolves all configured spawns (including async fallback spawns and string import paths)
|
|
5
|
+
* and installs feature getters on the class prototype, then delegates to the registry's
|
|
6
|
+
* assignFeatures implementation.
|
|
7
7
|
*
|
|
8
|
-
* This
|
|
9
|
-
*
|
|
8
|
+
* This is kept as a convenience entry point for callers that already await this function.
|
|
9
|
+
* The actual resolution logic lives in assignFeatures.
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
12
|
* import { resolveAndAssignFeatures } from 'assign-gingerly/resolveAndAssignFeatures.js';
|
|
@@ -22,46 +22,15 @@
|
|
|
22
22
|
* }
|
|
23
23
|
* });
|
|
24
24
|
*/
|
|
25
|
+
import { assignFeatures } from './assignFeatures.js';
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
-
*/
|
|
28
|
-
function isAsyncSpawn(fn) {
|
|
29
|
-
if (typeof fn !== 'function')
|
|
30
|
-
return false;
|
|
31
|
-
if (fn.constructor.name === 'AsyncFunction')
|
|
32
|
-
return true;
|
|
33
|
-
if (fn.prototype === undefined)
|
|
34
|
-
return true;
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Resolves async fallback spawns for features that don't have an explicit spawn,
|
|
39
|
-
* then calls assignFeatures on the registry.
|
|
27
|
+
* Resolves all configured spawns and calls assignFeatures on the registry.
|
|
40
28
|
*
|
|
41
29
|
* @param ElementClass - The custom element class (must have static supportedFeatures)
|
|
42
30
|
* @param featuresConfig - Feature configurations (spawn will be resolved from fallbackSpawn if missing)
|
|
43
31
|
* @param registry - Optional CustomElementRegistry (defaults to global customElements)
|
|
44
32
|
*/
|
|
45
33
|
export async function resolveAndAssignFeatures(ElementClass, featuresConfig, registry) {
|
|
46
|
-
const supportedFeatures = ElementClass.supportedFeatures;
|
|
47
|
-
if (!supportedFeatures) {
|
|
48
|
-
throw new Error(`resolveAndAssignFeatures: ${ElementClass.name || 'constructor'} does not define static supportedFeatures`);
|
|
49
|
-
}
|
|
50
|
-
// Resolve async fallback spawns in parallel for features without explicit spawn
|
|
51
|
-
await Promise.all(Object.entries(featuresConfig).map(async ([key, featureConfig]) => {
|
|
52
|
-
// Skip if spawn is already provided
|
|
53
|
-
if (featureConfig.spawn)
|
|
54
|
-
return;
|
|
55
|
-
const optIn = supportedFeatures[key];
|
|
56
|
-
if (!optIn?.fallbackSpawn)
|
|
57
|
-
return;
|
|
58
|
-
let spawn = optIn.fallbackSpawn;
|
|
59
|
-
if (isAsyncSpawn(spawn)) {
|
|
60
|
-
spawn = await spawn();
|
|
61
|
-
}
|
|
62
|
-
featureConfig.spawn = spawn;
|
|
63
|
-
}));
|
|
64
|
-
// Call assignFeatures on the registry
|
|
65
34
|
const reg = registry || customElements;
|
|
66
|
-
await
|
|
35
|
+
await assignFeatures(ElementClass, featuresConfig, reg.featuresRegistry);
|
|
67
36
|
}
|
|
@@ -1,79 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* resolveAndAssignFeatures -
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* This
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* import { resolveAndAssignFeatures } from 'assign-gingerly/resolveAndAssignFeatures.js';
|
|
13
|
-
*
|
|
14
|
-
* await resolveAndAssignFeatures(MyElement, {
|
|
15
|
-
* roundabout: {
|
|
16
|
-
* customData: {...},
|
|
17
|
-
* withAttrs: {...},
|
|
18
|
-
* callbackForwarding: ['connectedCallback']
|
|
19
|
-
* },
|
|
20
|
-
* faceUp: {
|
|
21
|
-
* callbackForwarding: ['connectedCallback', 'disconnectedCallback']
|
|
22
|
-
* }
|
|
23
|
-
* });
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { FeatureConfigsMap
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
* @param registry - Optional CustomElementRegistry (defaults to global customElements)
|
|
45
|
-
*/
|
|
46
|
-
export async function resolveAndAssignFeatures(
|
|
47
|
-
ElementClass: Function,
|
|
48
|
-
featuresConfig: FeatureConfigsMap,
|
|
49
|
-
registry?: any
|
|
50
|
-
): Promise<void> {
|
|
51
|
-
const supportedFeatures: SupportedFeaturesMap | undefined = (ElementClass as any).supportedFeatures;
|
|
52
|
-
|
|
53
|
-
if (!supportedFeatures) {
|
|
54
|
-
throw new Error(
|
|
55
|
-
`resolveAndAssignFeatures: ${(ElementClass as any).name || 'constructor'} does not define static supportedFeatures`
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Resolve async fallback spawns in parallel for features without explicit spawn
|
|
60
|
-
await Promise.all(
|
|
61
|
-
Object.entries(featuresConfig).map(async ([key, featureConfig]) => {
|
|
62
|
-
// Skip if spawn is already provided
|
|
63
|
-
if (featureConfig.spawn) return;
|
|
64
|
-
|
|
65
|
-
const optIn = supportedFeatures[key];
|
|
66
|
-
if (!optIn?.fallbackSpawn) return;
|
|
67
|
-
|
|
68
|
-
let spawn = optIn.fallbackSpawn;
|
|
69
|
-
if (isAsyncSpawn(spawn)) {
|
|
70
|
-
spawn = await (spawn as () => Promise<any>)();
|
|
71
|
-
}
|
|
72
|
-
(featureConfig as any).spawn = spawn;
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
// Call assignFeatures on the registry
|
|
77
|
-
const reg = registry || customElements;
|
|
78
|
-
await reg.assignFeatures(ElementClass, featuresConfig);
|
|
79
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* resolveAndAssignFeatures - Thin wrapper around assignFeatures for backward compatibility.
|
|
3
|
+
*
|
|
4
|
+
* Resolves all configured spawns (including async fallback spawns and string import paths)
|
|
5
|
+
* and installs feature getters on the class prototype, then delegates to the registry's
|
|
6
|
+
* assignFeatures implementation.
|
|
7
|
+
*
|
|
8
|
+
* This is kept as a convenience entry point for callers that already await this function.
|
|
9
|
+
* The actual resolution logic lives in assignFeatures.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { resolveAndAssignFeatures } from 'assign-gingerly/resolveAndAssignFeatures.js';
|
|
13
|
+
*
|
|
14
|
+
* await resolveAndAssignFeatures(MyElement, {
|
|
15
|
+
* roundabout: {
|
|
16
|
+
* customData: {...},
|
|
17
|
+
* withAttrs: {...},
|
|
18
|
+
* callbackForwarding: ['connectedCallback']
|
|
19
|
+
* },
|
|
20
|
+
* faceUp: {
|
|
21
|
+
* callbackForwarding: ['connectedCallback', 'disconnectedCallback']
|
|
22
|
+
* }
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { FeatureConfigsMap } from './types/assign-gingerly/types.js';
|
|
27
|
+
import { assignFeatures } from './assignFeatures.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolves all configured spawns and calls assignFeatures on the registry.
|
|
31
|
+
*
|
|
32
|
+
* @param ElementClass - The custom element class (must have static supportedFeatures)
|
|
33
|
+
* @param featuresConfig - Feature configurations (spawn will be resolved from fallbackSpawn if missing)
|
|
34
|
+
* @param registry - Optional CustomElementRegistry (defaults to global customElements)
|
|
35
|
+
*/
|
|
36
|
+
export async function resolveAndAssignFeatures(
|
|
37
|
+
ElementClass: Function,
|
|
38
|
+
featuresConfig: FeatureConfigsMap,
|
|
39
|
+
registry?: any
|
|
40
|
+
): Promise<void> {
|
|
41
|
+
const reg = registry || customElements;
|
|
42
|
+
await assignFeatures(ElementClass, featuresConfig, reg.featuresRegistry);
|
|
43
|
+
}
|