Skip to content

Commit e7fadc4

Browse files
committed
fix: backward compatability for did-update
1 parent f7d5e07 commit e7fadc4

4 files changed

Lines changed: 116 additions & 7 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"eslint-plugin-ember": "^12.7.5",
8686
"eslint-plugin-import": "^2.32.0",
8787
"eslint-plugin-n": "^17.24.0",
88-
"globals": "^17.4.0",
88+
"globals": "^17.5.0",
8989
"prettier": "^3.8.2",
9090
"prettier-plugin-ember-template-tag": "^2.1.4",
9191
"publint": "^0.3.18",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/-private/untrack.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as glimmerValidator from '@glimmer/validator';
2+
3+
// Ember apps can provide @glimmer/validator through different module shapes
4+
// depending on ember-source version and bundling mode. We centralize the
5+
// resolution logic here so modifiers can always call a single `untrack` API.
6+
7+
type UntrackCallback = () => void;
8+
type ValidatorRequire = (moduleName: string) => ValidatorModule;
9+
10+
interface ValidatorModule {
11+
untrack?: unknown;
12+
beginUntrackFrame?: unknown;
13+
endUntrackFrame?: unknown;
14+
}
15+
16+
function getCallable<T extends (...args: never[]) => unknown>(
17+
target: unknown,
18+
property: string,
19+
): T | undefined {
20+
const value = (target as Record<string, unknown>)[property];
21+
22+
return typeof value === 'function' ? (value as T) : undefined;
23+
}
24+
25+
function tryRequire(maybeRequire: ValidatorRequire | undefined) {
26+
if (typeof maybeRequire !== 'function') {
27+
return undefined;
28+
}
29+
30+
try {
31+
return maybeRequire('@glimmer/validator');
32+
} catch {
33+
return undefined;
34+
}
35+
}
36+
37+
function resolveValidatorModule(): ValidatorModule {
38+
const importedModule = glimmerValidator as ValidatorModule;
39+
const importedUntrack = getCallable<Untrack>(importedModule, 'untrack');
40+
const importedBeginUntrackFrame = getCallable<() => void>(
41+
importedModule,
42+
'beginUntrackFrame',
43+
);
44+
45+
if (importedUntrack || importedBeginUntrackFrame) {
46+
// Modern ESM shape: use the imported namespace directly.
47+
return importedModule;
48+
}
49+
50+
const globalWithEmber = globalThis as {
51+
Ember?: {
52+
__loader?: {
53+
require?: (moduleName: string) => ValidatorModule;
54+
};
55+
};
56+
require?: ValidatorRequire;
57+
requirejs?: ValidatorRequire;
58+
};
59+
60+
const requireCandidates: Array<ValidatorRequire | undefined> = [
61+
globalWithEmber.Ember?.__loader?.require,
62+
globalWithEmber.require,
63+
globalWithEmber.requirejs,
64+
];
65+
66+
for (const maybeRequire of requireCandidates) {
67+
const module = tryRequire(maybeRequire);
68+
69+
if (module) {
70+
// Older or compat builds: resolve from runtime module loader.
71+
return module;
72+
}
73+
}
74+
75+
return {};
76+
}
77+
78+
type Untrack = (callback: UntrackCallback) => void;
79+
80+
export const untrack: Untrack = (() => {
81+
const validator = resolveValidatorModule();
82+
const moduleUntrack = getCallable<Untrack>(validator, 'untrack');
83+
84+
if (moduleUntrack) {
85+
return moduleUntrack;
86+
}
87+
88+
const beginUntrackFrame = getCallable<() => void>(
89+
validator,
90+
'beginUntrackFrame',
91+
);
92+
const endUntrackFrame = getCallable<() => void>(validator, 'endUntrackFrame');
93+
94+
if (beginUntrackFrame && endUntrackFrame) {
95+
// Some validator versions expose frame primitives instead of `untrack`.
96+
return (callback: UntrackCallback) => {
97+
beginUntrackFrame();
98+
99+
try {
100+
callback();
101+
} finally {
102+
endUntrackFrame();
103+
}
104+
};
105+
}
106+
107+
// Last resort for very old/unexpected runtime shapes.
108+
return (callback: UntrackCallback) => callback();
109+
})();

src/modifiers/did-update.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { setModifierManager, capabilities } from '@ember/modifier';
2-
import { untrack } from '@glimmer/validator';
2+
import { untrack } from '../-private/untrack.ts';
33

44
import type {
55
ModifierArgs,

0 commit comments

Comments
 (0)