Skip to content

Commit 161cbd2

Browse files
authoredMar 10, 2024
chore: handle declare statements in module rewriting (#9249)
* chore: handle declare statements in module rewriting * fix docs * simplify module structure * expose NativeProxy private type
1 parent 63eea02 commit 161cbd2

File tree

8 files changed

+226
-100
lines changed

8 files changed

+226
-100
lines changed
 

‎packages/graph/src/-private.ts

+39-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
export { graphFor, peekGraph } from './-private/index';
2-
export { isBelongsTo } from './-private/-utils';
3-
41
/**
52
* <p align="center">
63
<img
@@ -29,3 +26,42 @@ pnpm add @ember-data/graph
2926
@module @ember-data/graph
3027
@main @ember-data/graph
3128
*/
29+
import { DEBUG } from '@ember-data/env';
30+
import type Store from '@ember-data/store';
31+
import type { CacheCapabilitiesManager } from '@ember-data/store/-types/q/cache-store-wrapper';
32+
33+
import { getStore } from './-private/-utils';
34+
import { Graph, Graphs } from './-private/graph';
35+
36+
export { isBelongsTo } from './-private/-utils';
37+
38+
function isStore(maybeStore: unknown): maybeStore is Store {
39+
return (maybeStore as Store)._instanceCache !== undefined;
40+
}
41+
42+
function getWrapper(store: CacheCapabilitiesManager | Store): CacheCapabilitiesManager {
43+
return isStore(store) ? store._instanceCache._storeWrapper : store;
44+
}
45+
46+
export function peekGraph(store: CacheCapabilitiesManager | Store): Graph | undefined {
47+
return Graphs.get(getWrapper(store));
48+
}
49+
export type peekGraph = typeof peekGraph;
50+
51+
export function graphFor(store: CacheCapabilitiesManager | Store): Graph {
52+
const wrapper = getWrapper(store);
53+
let graph = Graphs.get(wrapper);
54+
55+
if (!graph) {
56+
graph = new Graph(wrapper);
57+
Graphs.set(wrapper, graph);
58+
getStore(wrapper)._graph = graph;
59+
60+
if (DEBUG) {
61+
if (getStore(wrapper).isDestroying) {
62+
throw new Error(`Memory Leak Detected During Teardown`);
63+
}
64+
}
65+
}
66+
return graph;
67+
}

‎packages/graph/src/-private/index.ts

-37
This file was deleted.

‎packages/model/src/-private/many-array.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { assert, deprecate } from '@ember/debug';
55

66
import { DEPRECATE_MANY_ARRAY_DUPLICATES } from '@ember-data/deprecations';
77
import type Store from '@ember-data/store';
8+
import type { NativeProxy } from '@ember-data/store/-private';
89
import {
910
ARRAY_SIGNAL,
1011
isStableIdentifier,
@@ -171,7 +172,7 @@ export default class RelatedCollection<T = unknown> extends RecordArray<T> {
171172

172173
[MUTATE](
173174
target: StableRecordIdentifier[],
174-
receiver: typeof Proxy<StableRecordIdentifier[], T[]>,
175+
receiver: typeof NativeProxy<StableRecordIdentifier[], T[]>,
175176
prop: string,
176177
args: unknown[],
177178
_SIGNAL: Signal

‎packages/store/src/-private.ts

+41-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
export * from './-private/index';
1+
/**
2+
@module @ember-data/store
3+
*/
4+
5+
export { default as Store, storeFor } from './-private/store-service';
6+
7+
export { recordIdentifierFor } from './-private/caches/instance-cache';
8+
9+
export { CacheHandler, type LifetimesService } from './-private/cache-handler';
10+
11+
export {
12+
setIdentifierGenerationMethod,
13+
setIdentifierUpdateMethod,
14+
setIdentifierForgetMethod,
15+
setIdentifierResetMethod,
16+
isStableIdentifier,
17+
} from './-private/caches/identifier-cache';
18+
19+
// TODO this should be a deprecated helper but we have so much usage of it
20+
// to also eliminate
21+
export { default as coerceId } from './-private/utils/coerce-id';
22+
export type { NativeProxy } from './-private/record-arrays/native-proxy-type-fix';
23+
export {
24+
default as RecordArray,
25+
default as IdentifierArray,
26+
Collection as AdapterPopulatedRecordArray,
27+
notifyArray,
28+
SOURCE,
29+
MUTATE,
30+
ARRAY_SIGNAL,
31+
} from './-private/record-arrays/identifier-array';
32+
export { default as RecordArrayManager, fastPush } from './-private/managers/record-array-manager';
33+
34+
// leaked for private use / test use, should investigate removing
35+
export { _clearCaches } from './-private/caches/instance-cache';
36+
export { default as peekCache, removeRecordDataFor } from './-private/caches/cache-utils';
37+
38+
// @ember-data/model needs these temporarily
39+
export { setRecordIdentifier, StoreMap } from './-private/caches/instance-cache';
40+
export { setCacheFor } from './-private/caches/cache-utils';
41+
export { default as _deprecatingNormalize } from './-private/utils/normalize-model-name';

‎packages/store/src/-private/index.ts

-41
This file was deleted.

‎packages/store/src/-private/record-arrays/identifier-array.ts

+7-11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { isStableIdentifier } from '../caches/identifier-cache';
2222
import { recordIdentifierFor } from '../caches/instance-cache';
2323
import type RecordArrayManager from '../managers/record-array-manager';
2424
import type Store from '../store-service';
25+
import { NativeProxy } from './native-proxy-type-fix';
2526

2627
type KeyType = string | symbol | number;
2728
const ARRAY_GETTER_METHODS = new Set<KeyType>([
@@ -81,11 +82,6 @@ function convertToInt(prop: KeyType): number | null {
8182
}
8283

8384
type ProxiedMethod = (...args: unknown[]) => unknown;
84-
declare global {
85-
interface ProxyConstructor {
86-
new <TSource extends object, TTarget extends object>(target: TSource, handler: ProxyHandler<TSource>): TTarget;
87-
}
88-
}
8985

9086
export type IdentifierArrayCreateOptions<T = unknown> = {
9187
identifiers: StableRecordIdentifier[];
@@ -101,9 +97,9 @@ interface PrivateState {
10197
links: Links | PaginationLinks | null;
10298
meta: Record<string, unknown> | null;
10399
}
104-
type ForEachCB<T> = (record: T, index: number, context: typeof Proxy<StableRecordIdentifier[], T[]>) => void;
100+
type ForEachCB<T> = (record: T, index: number, context: typeof NativeProxy<StableRecordIdentifier[], T[]>) => void;
105101
function safeForEach<T>(
106-
instance: typeof Proxy<StableRecordIdentifier[], T[]>,
102+
instance: typeof NativeProxy<StableRecordIdentifier[], T[]>,
107103
arr: StableRecordIdentifier[],
108104
store: Store,
109105
callback: ForEachCB<T>,
@@ -144,7 +140,7 @@ function safeForEach<T>(
144140
interface IdentifierArray<T = unknown> extends Omit<Array<T>, '[]'> {
145141
[MUTATE]?(
146142
target: StableRecordIdentifier[],
147-
receiver: typeof Proxy<StableRecordIdentifier[], T[]>,
143+
receiver: typeof NativeProxy<StableRecordIdentifier[], T[]>,
148144
prop: string,
149145
args: unknown[],
150146
_SIGNAL: Signal
@@ -231,8 +227,8 @@ class IdentifierArray<T = unknown> {
231227
// we track all mutations within the call
232228
// and forward them as one
233229

234-
const proxy = new Proxy<StableRecordIdentifier[], T[]>(this[SOURCE], {
235-
get<R extends typeof Proxy<StableRecordIdentifier[], T[]>>(
230+
const proxy = new NativeProxy<StableRecordIdentifier[], T[]>(this[SOURCE], {
231+
get<R extends typeof NativeProxy<StableRecordIdentifier[], T[]>>(
236232
target: StableRecordIdentifier[],
237233
prop: keyof R,
238234
receiver: R
@@ -344,7 +340,7 @@ class IdentifierArray<T = unknown> {
344340
target: StableRecordIdentifier[],
345341
prop: KeyType,
346342
value: unknown,
347-
receiver: typeof Proxy<StableRecordIdentifier[], T[]>
343+
receiver: typeof NativeProxy<StableRecordIdentifier[], T[]>
348344
): boolean {
349345
if (prop === 'length') {
350346
if (!transaction && value === 0) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
/*
3+
We redefine Proxy because the native Proxy type treats the `target` and
4+
`receiver` as the same type incorrectly.
5+
6+
We ported this from Typescript's own Proxy types on 3/10/2024.
7+
*/
8+
interface ProxyHandler<T extends object> {
9+
/**
10+
* A trap method for a function call.
11+
* @param target The original callable object which is being proxied.
12+
* @internal
13+
*/
14+
apply?(target: T, thisArg: any, argArray: any[]): any;
15+
16+
/**
17+
* A trap for the `new` operator.
18+
* @param target The original object which is being proxied.
19+
* @param newTarget The constructor that was originally called.
20+
* @internal
21+
*/
22+
// eslint-disable-next-line @typescript-eslint/ban-types
23+
construct?(target: T, argArray: any[], newTarget: Function): object;
24+
25+
/**
26+
* A trap for `Object.defineProperty()`.
27+
* @param target The original object which is being proxied.
28+
* @returns A `Boolean` indicating whether or not the property has been defined.
29+
* @internal
30+
*/
31+
defineProperty?(target: T, property: string | symbol, attributes: PropertyDescriptor): boolean;
32+
33+
/**
34+
* A trap for the `delete` operator.
35+
* @param target The original object which is being proxied.
36+
* @param p The name or `Symbol` of the property to delete.
37+
* @returns A `Boolean` indicating whether or not the property was deleted.
38+
* @internal
39+
*/
40+
deleteProperty?(target: T, p: string | symbol): boolean;
41+
42+
/**
43+
* A trap for getting a property value.
44+
* @param target The original object which is being proxied.
45+
* @param p The name or `Symbol` of the property to get.
46+
* @param receiver The proxy or an object that inherits from the proxy.
47+
* @internal
48+
*/
49+
get?(target: T, p: string | symbol, receiver: any): any;
50+
51+
/**
52+
* A trap for `Object.getOwnPropertyDescriptor()`.
53+
* @param target The original object which is being proxied.
54+
* @param p The name of the property whose description should be retrieved.
55+
* @internal
56+
*/
57+
getOwnPropertyDescriptor?(target: T, p: string | symbol): PropertyDescriptor | undefined;
58+
59+
/**
60+
* A trap for the `[[GetPrototypeOf]]` internal method.
61+
* @param target The original object which is being proxied.
62+
* @internal
63+
*/
64+
getPrototypeOf?(target: T): object | null;
65+
66+
/**
67+
* A trap for the `in` operator.
68+
* @param target The original object which is being proxied.
69+
* @param p The name or `Symbol` of the property to check for existence.
70+
* @internal
71+
*/
72+
has?(target: T, p: string | symbol): boolean;
73+
74+
/**
75+
* A trap for `Object.isExtensible()`.
76+
* @param target The original object which is being proxied.
77+
* @internal
78+
*/
79+
isExtensible?(target: T): boolean;
80+
81+
/**
82+
* A trap for `Reflect.ownKeys()`.
83+
* @param target The original object which is being proxied.
84+
* @internal
85+
*/
86+
ownKeys?(target: T): ArrayLike<string | symbol>;
87+
88+
/**
89+
* A trap for `Object.preventExtensions()`.
90+
* @param target The original object which is being proxied.
91+
* @internal
92+
*/
93+
preventExtensions?(target: T): boolean;
94+
95+
/**
96+
* A trap for setting a property value.
97+
* @param target The original object which is being proxied.
98+
* @param p The name or `Symbol` of the property to set.
99+
* @param receiver The object to which the assignment was originally directed.
100+
* @returns A `Boolean` indicating whether or not the property was set.
101+
* @internal
102+
*/
103+
set?(target: T, p: string | symbol, newValue: any, receiver: any): boolean;
104+
105+
/**
106+
* A trap for `Object.setPrototypeOf()`.
107+
* @param target The original object which is being proxied.
108+
* @param newPrototype The object's new prototype or `null`.
109+
* @internal
110+
*/
111+
setPrototypeOf?(target: T, v: object | null): boolean;
112+
}
113+
114+
interface ProxyConstructor {
115+
/**
116+
* Creates a revocable Proxy object.
117+
* @param target A target object to wrap with Proxy.
118+
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
119+
* @internal
120+
*/
121+
revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void };
122+
123+
/**
124+
* Creates a Proxy object. The Proxy object allows you to create an object that can be used in place of the
125+
* original object, but which may redefine fundamental Object operations like getting, setting, and defining
126+
* properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs.
127+
* @param target A target object to wrap with Proxy.
128+
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
129+
* @internal
130+
*/
131+
new <TSource extends object, TTarget extends object>(target: TSource, handler: ProxyHandler<TSource>): TTarget;
132+
}
133+
134+
export const NativeProxy: ProxyConstructor = Proxy as unknown as ProxyConstructor;

0 commit comments

Comments
 (0)