Skip to content

Commit bb73339

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

4 files changed

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

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)