Skip to content

Commit c22bfb3

Browse files
authored
fix: Avoid ESBuild destroying Proxy in __toESM (#164)
1 parent acf34b9 commit c22bfb3

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

src/discoverer/evaluate.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,32 @@ export class EvaluationTestDiscoverer implements ITestDiscoverer {
6262
function placeholder(): unknown {
6363
return new Proxy(placeholder, {
6464
get: (obj, target) => {
65-
const desc = Object.getOwnPropertyDescriptor(obj, target);
66-
if (desc && !desc.writable && !desc.configurable) {
67-
return desc.value; // avoid invariant volation https://stackoverflow.com/q/75148897
65+
try {
66+
const desc = Object.getOwnPropertyDescriptor(obj, target);
67+
if (desc && !desc.writable && !desc.configurable) {
68+
return desc.value; // avoid invariant volation https://stackoverflow.com/q/75148897
69+
}
70+
return placeholder();
71+
} catch (e) {
72+
return placeholder();
6873
}
74+
},
75+
set: () => true,
76+
apply: () => {
6977
return placeholder();
7078
},
79+
});
80+
}
81+
82+
function objectPlaceholder(originalObject: any): unknown {
83+
return new Proxy(objectPlaceholder, {
84+
get: (_, target) => {
85+
if (target === 'create') {
86+
return placeholder();
87+
} else {
88+
return originalObject[target];
89+
}
90+
},
7191
set: () => true,
7292
});
7393
}
@@ -186,6 +206,15 @@ export class EvaluationTestDiscoverer implements ITestDiscoverer {
186206
} else if (prop in target) {
187207
return target[prop]; // top-level `var` defined get set on the contextObj
188208
} else if (prop in globalThis && !replacedGlobals.has(prop as string)) {
209+
// Bug #153: ESBuild will wrap require() calls into __toESM which breaks quite some things
210+
// we want to keep our Proxy placeholder object in all scenarios
211+
// Due to that we provide a special proxy object which will create again placeholder proxies
212+
// on Object.create
213+
// https://github.com/evanw/esbuild/blob/d34e79e2a998c21bb71d57b92b0017ca11756912/internal/runtime/runtime.go#L231-L242
214+
if (prop === 'Object') {
215+
return objectPlaceholder((globalThis as any)[prop]);
216+
}
217+
189218
return (globalThis as any)[prop];
190219
} else {
191220
return placeholder();

src/test/integration/typescript.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('typescript', () => {
8484
expect(failed.message?.location).to.not.be.undefined;
8585
expect(failed.message?.location?.uri.toString()).to.include('hello.test.ts');
8686
expect(path.isAbsolute(failed.message!.location!.uri.fsPath)).to.be.true;
87-
expect(failed.message?.location?.range.start.line).to.equal(25);
87+
expect(failed.message?.location?.range.start.line).to.equal(29);
8888
expect(failed.message?.location?.range.start.character).to.equal(5);
8989
});
9090
});

test-workspaces/typescript/hello.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { strictEqual } from 'node:assert';
2+
import path, { join } from 'node:path';
3+
4+
path.join('', '');
5+
join('', '');
26

37
// just some typescript code which would be valid directly in Node
48

0 commit comments

Comments
 (0)