Skip to content

Commit b4193fe

Browse files
committed
chore: handle declare statements in module rewriting
1 parent 63eea02 commit b4193fe

File tree

3 files changed

+128
-13
lines changed

3 files changed

+128
-13
lines changed

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,119 @@
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+
*/
13+
apply?(target: T, thisArg: any, argArray: any[]): any;
14+
15+
/**
16+
* A trap for the `new` operator.
17+
* @param target The original object which is being proxied.
18+
* @param newTarget The constructor that was originally called.
19+
*/
20+
// eslint-disable-next-line @typescript-eslint/ban-types
21+
construct?(target: T, argArray: any[], newTarget: Function): object;
22+
23+
/**
24+
* A trap for `Object.defineProperty()`.
25+
* @param target The original object which is being proxied.
26+
* @returns A `Boolean` indicating whether or not the property has been defined.
27+
*/
28+
defineProperty?(target: T, property: string | symbol, attributes: PropertyDescriptor): boolean;
29+
30+
/**
31+
* A trap for the `delete` operator.
32+
* @param target The original object which is being proxied.
33+
* @param p The name or `Symbol` of the property to delete.
34+
* @returns A `Boolean` indicating whether or not the property was deleted.
35+
*/
36+
deleteProperty?(target: T, p: string | symbol): boolean;
37+
38+
/**
39+
* A trap for getting a property value.
40+
* @param target The original object which is being proxied.
41+
* @param p The name or `Symbol` of the property to get.
42+
* @param receiver The proxy or an object that inherits from the proxy.
43+
*/
44+
get?(target: T, p: string | symbol, receiver: any): any;
45+
46+
/**
47+
* A trap for `Object.getOwnPropertyDescriptor()`.
48+
* @param target The original object which is being proxied.
49+
* @param p The name of the property whose description should be retrieved.
50+
*/
51+
getOwnPropertyDescriptor?(target: T, p: string | symbol): PropertyDescriptor | undefined;
52+
53+
/**
54+
* A trap for the `[[GetPrototypeOf]]` internal method.
55+
* @param target The original object which is being proxied.
56+
*/
57+
getPrototypeOf?(target: T): object | null;
58+
59+
/**
60+
* A trap for the `in` operator.
61+
* @param target The original object which is being proxied.
62+
* @param p The name or `Symbol` of the property to check for existence.
63+
*/
64+
has?(target: T, p: string | symbol): boolean;
65+
66+
/**
67+
* A trap for `Object.isExtensible()`.
68+
* @param target The original object which is being proxied.
69+
*/
70+
isExtensible?(target: T): boolean;
71+
72+
/**
73+
* A trap for `Reflect.ownKeys()`.
74+
* @param target The original object which is being proxied.
75+
*/
76+
ownKeys?(target: T): ArrayLike<string | symbol>;
77+
78+
/**
79+
* A trap for `Object.preventExtensions()`.
80+
* @param target The original object which is being proxied.
81+
*/
82+
preventExtensions?(target: T): boolean;
83+
84+
/**
85+
* A trap for setting a property value.
86+
* @param target The original object which is being proxied.
87+
* @param p The name or `Symbol` of the property to set.
88+
* @param receiver The object to which the assignment was originally directed.
89+
* @returns A `Boolean` indicating whether or not the property was set.
90+
*/
91+
set?(target: T, p: string | symbol, newValue: any, receiver: any): boolean;
92+
93+
/**
94+
* A trap for `Object.setPrototypeOf()`.
95+
* @param target The original object which is being proxied.
96+
* @param newPrototype The object's new prototype or `null`.
97+
*/
98+
setPrototypeOf?(target: T, v: object | null): boolean;
99+
}
100+
101+
interface ProxyConstructor {
102+
/**
103+
* Creates a revocable Proxy object.
104+
* @param target A target object to wrap with Proxy.
105+
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
106+
*/
107+
revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void };
108+
109+
/**
110+
* Creates a Proxy object. The Proxy object allows you to create an object that can be used in place of the
111+
* original object, but which may redefine fundamental Object operations like getting, setting, and defining
112+
* properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs.
113+
* @param target A target object to wrap with Proxy.
114+
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
115+
*/
116+
new <TSource extends object, TTarget extends object>(target: TSource, handler: ProxyHandler<TSource>): TTarget;
117+
}
118+
119+
export const NativeProxy: ProxyConstructor = Proxy as unknown as ProxyConstructor;

release/core/publish/steps/generate-tarballs.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ async function convertFileToModule(fileData: string, relativePath: string, pkgNa
176176
: maybeModuleName;
177177

178178
for (let i = 0; i < lines.length; i++) {
179-
const line = lines[i];
179+
const line = lines[i].replace(/^declare /, '').replaceAll(' declare ', '');
180180
if (line.startsWith('import ')) {
181181
if (!line.includes(`'`)) {
182182
throw new Error(`Unhandled import in ${relativePath}`);
@@ -214,7 +214,7 @@ async function convertFileToModule(fileData: string, relativePath: string, pkgNa
214214

215215
// insert 2 spaces at the beginning of each line
216216
// to account for module wrapper
217-
lines[i] = ' ' + lines[i];
217+
if (!lines[i].startsWith('//# sourceMappingURL=')) lines[i] = ' ' + lines[i];
218218
}
219219

220220
lines.unshift(`declare module '${moduleName}' {`);

0 commit comments

Comments
 (0)