diff --git a/packages/cloudflare/src/instrumentations/instrumentDurableObjectStorage.ts b/packages/cloudflare/src/instrumentations/instrumentDurableObjectStorage.ts index 29d47eb481f3..984bcb22707e 100644 --- a/packages/cloudflare/src/instrumentations/instrumentDurableObjectStorage.ts +++ b/packages/cloudflare/src/instrumentations/instrumentDurableObjectStorage.ts @@ -16,8 +16,13 @@ type StorageMethod = (typeof STORAGE_METHODS_TO_INSTRUMENT)[number]; */ export function instrumentDurableObjectStorage(storage: DurableObjectStorage): DurableObjectStorage { return new Proxy(storage, { - get(target, prop, receiver) { - const original = Reflect.get(target, prop, receiver); + get(target, prop, _receiver) { + // Use `target` as the receiver instead of the proxy (`_receiver`). + // Native workerd getters (e.g., `storage.sql`) validate `this` via + // internal slots. Passing the proxy as receiver breaks that check, + // causing "Illegal invocation: function called with incorrect `this` + // reference" errors. + const original = Reflect.get(target, prop, target); if (typeof original !== 'function') { return original; diff --git a/packages/cloudflare/test/instrumentDurableObjectStorage.test.ts b/packages/cloudflare/test/instrumentDurableObjectStorage.test.ts index 11c3228f905b..188b007a0b59 100644 --- a/packages/cloudflare/test/instrumentDurableObjectStorage.test.ts +++ b/packages/cloudflare/test/instrumentDurableObjectStorage.test.ts @@ -182,6 +182,25 @@ describe('instrumentDurableObjectStorage', () => { }); }); + describe('native getter preservation', () => { + it('preserves native getter `this` binding through the proxy', () => { + // Private fields simulate workerd's native brand check — + // accessing #sqlInstance on wrong `this` throws TypeError, + // like workerd's "Illegal invocation". + class BrandCheckedStorage { + #sqlInstance = { exec: () => {} }; + get sql() { + return this.#sqlInstance; + } + } + + const storage = new BrandCheckedStorage(); + const instrumented = instrumentDurableObjectStorage(storage as any); + + expect(() => (instrumented as any).sql).not.toThrow(); + }); + }); + describe('error handling', () => { it('propagates errors from storage operations', async () => { const mockStorage = createMockStorage();