Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 8 additions & 171 deletions bin/proxyquire-bun-shim.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -355,180 +355,17 @@ if (
try {
const assert = require('assert');
const origDeepEqual = assert.deepEqual;
function looseDeepEqual(a, b) {
if (a === b) return true;
// In Node.js, assert.deepEqual performs abstract equality (==) on primitives
// (e.g. assert.deepEqual('1', 1) passes). In Bun, native assert.deepEqual('1', 1)
// throws. Allow loose primitive equality only when both operands are non-null
// primitives to avoid false positives like null == undefined or [] == false.
if (
typeof a !== 'object' &&
typeof b !== 'object' &&
a !== null &&
b !== null
) {
return a == b;
}
if (
a === null ||
b === null ||
typeof a !== 'object' ||
typeof b !== 'object'
) {
return false;
}
if (a instanceof Date || b instanceof Date) {
return (
a instanceof Date &&
b instanceof Date &&
a.getTime() === b.getTime()
);
}
if (a instanceof RegExp || b instanceof RegExp) {
return (
a instanceof RegExp &&
b instanceof RegExp &&
a.toString() === b.toString()
);
}
if (
typeof Buffer !== 'undefined' &&
(Buffer.isBuffer(a) || Buffer.isBuffer(b))
) {
return Buffer.isBuffer(a) && Buffer.isBuffer(b) && a.equals(b);
}
if (a instanceof Map || b instanceof Map) {
return (
a instanceof Map &&
b instanceof Map &&
a.size === b.size &&
looseDeepEqual(Array.from(a.entries()), Array.from(b.entries()))
);
}
if (a instanceof Set || b instanceof Set) {
return (
a instanceof Set &&
b instanceof Set &&
a.size === b.size &&
looseDeepEqual(Array.from(a.values()), Array.from(b.values()))
);
}
if (Array.isArray(a) !== Array.isArray(b)) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const k of keysA) {
if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
if (!looseDeepEqual(a[k], b[k])) return false;
}
return true;
}
if (typeof origDeepEqual === 'function') {
if (typeof origDeepEqual === 'function' && typeof Headers !== 'undefined') {
assert.deepEqual = function (actual, expected, message) {
if (
typeof Headers !== 'undefined' &&
actual instanceof Headers &&
expected instanceof Headers
) {
actual = Object.fromEntries(actual.entries());
expected = Object.fromEntries(expected.entries());
}
try {
return origDeepEqual.call(this, actual, expected, message);
} catch (err) {
if (looseDeepEqual(actual, expected)) return;
throw err;
}
};
}
const origDeepStrictEqual = assert.deepStrictEqual;
if (typeof origDeepStrictEqual === 'function') {
// Bun <= 1.4 strictly requires prototype reference equality in
// assert.deepStrictEqual. In Node 20+, Array subclasses whose constructor
// is Array (such as RowImpl) are compared by contents and properties against
// plain arrays. In affected Bun versions, retry only for arrays where both
// constructors are Array, transferring own properties so custom prototypes
// or property mismatches continue to fail strictly.
const [bunMajor, bunMinor] = (
(typeof process !== 'undefined' && process.versions?.bun) ||
'0.0'
)
.split('.')
.map(Number);
const hasBunArrayProtoIssue =
bunMajor === 1 &&
bunMinor <= 4 &&
(() => {
try {
class TestArr extends Array {}
Object.defineProperty(TestArr.prototype, 'constructor', {
value: Array,
writable: true,
configurable: true,
enumerable: false,
});
origDeepStrictEqual(new TestArr(), []);
return false;
} catch {
return true;
}
})();

assert.deepStrictEqual = function (actual, expected, message) {
try {
return origDeepStrictEqual.call(this, actual, expected, message);
} catch (err) {
if (
hasBunArrayProtoIssue &&
Array.isArray(actual) &&
Array.isArray(expected) &&
actual.constructor === Array &&
expected.constructor === Array
) {
try {
const copyA = Array.from(actual);
for (const k of Reflect.ownKeys(actual)) {
if (k !== 'length') {
Object.defineProperty(
copyA,
k,
Object.getOwnPropertyDescriptor(actual, k),
);
}
}
const copyB = Array.from(expected);
for (const k of Reflect.ownKeys(expected)) {
if (k !== 'length') {
Object.defineProperty(
copyB,
k,
Object.getOwnPropertyDescriptor(expected, k),
);
}
}
return origDeepStrictEqual.call(this, copyA, copyB, message);
} catch {
throw err;
}
}
throw err;
}
};
}
const origThrows = assert.throws;
if (typeof origThrows === 'function') {
assert.throws = function (block, error, message) {
if (
error instanceof RegExp &&
/Cannot assign to read only property/.test(error.source)
) {
const adapted = new RegExp(
'(?:' + error.source + '|Attempted to assign to readonly property)',
error.flags,
if (actual instanceof Headers && expected instanceof Headers) {
return origDeepEqual.call(
this,
Object.fromEntries(actual.entries()),
Object.fromEntries(expected.entries()),
message,
);
return origThrows.call(this, block, adapted, message);
}
return origThrows.call(this, block, error, message);
return origDeepEqual.call(this, actual, expected, message);
};
}
} catch {
Expand Down
110 changes: 0 additions & 110 deletions design.md

This file was deleted.

2 changes: 1 addition & 1 deletion handwritten/spanner/test/codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@
value: music.Genre.JAZZ,
fullName: 'examples.spanner.music.Genre',
}).toJSON(),
1,
'1',
);
});
});
Expand Down Expand Up @@ -1268,7 +1268,7 @@
protoTypeFqn: 'examples.spanner.music.Genre',
};

const decoded = codec.decode(1, type as any, music.Genre);

Check warning on line 1271 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
assert(decoded instanceof codec.ProtoEnum);
assert.strictEqual(decoded.value, '1');
});
Expand All @@ -1279,7 +1279,7 @@
protoTypeFqn: 'examples.spanner.music.Genre',
};

const decoder = codec.getDecoder(type as any, music.Genre, {

Check warning on line 1282 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
wrapStructs: false,
});

Expand All @@ -1296,7 +1296,7 @@
protoTypeFqn: 'examples.spanner.music.Genre',
};

const decoder = codec.getDecoder(type as any, music.Genre, {

Check warning on line 1299 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
wrapStructs: false,
});

Expand Down Expand Up @@ -1775,7 +1775,7 @@
};

// 1. In standard mode (options = undefined)
const decoder = codec.getDecoder(type as any, mockMetadata, undefined);

Check warning on line 1778 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

const testData = {
singer: music.SingerInfo.encode({
Expand All @@ -1788,7 +1788,7 @@
.toString('base64'),
};

const result = decoder(testData) as any;

Check warning on line 1791 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
assert(result instanceof codec.Struct);
const singerField = result[0].value;
assert(singerField instanceof codec.ProtoMessage);
Expand All @@ -1798,10 +1798,10 @@
);

// 2. In JSON mode (options = {wrapStructs: false})
const jsonDecoder = codec.getDecoder(type as any, mockMetadata, {

Check warning on line 1801 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
wrapStructs: false,
});
const jsonResult = jsonDecoder(testData) as any;

Check warning on line 1804 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
assert.strictEqual(jsonResult.singer.birthDate, 'January');
assert.strictEqual(jsonResult.singer.nationality, 'Country1');
assert.strictEqual(jsonResult.singer.genre, 0);
Expand All @@ -1828,7 +1828,7 @@
'': music.SingerInfo,
};

const decoder = codec.getDecoder(type as any, mockMetadata, undefined);

Check warning on line 1831 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

const testData = {
'': music.SingerInfo.encode({
Expand All @@ -1841,7 +1841,7 @@
.toString('base64'),
};

const result = decoder(testData) as any;

Check warning on line 1844 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
assert(result instanceof codec.Struct);
const singerField = result[0].value;
assert(singerField instanceof codec.ProtoMessage);
Expand Down Expand Up @@ -1873,7 +1873,7 @@
});

// It should NOT resolve the prototype's toString property, but instead pass undefined to the nested decoder
const decoder = codec.getDecoder(type as any, mockMetadata, undefined);

Check warning on line 1876 in handwritten/spanner/test/codec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

const testData = {
toString: music.SingerInfo.encode({
Expand Down
2 changes: 1 addition & 1 deletion handwritten/spanner/test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe('helper', () => {

assert.throws(() => {
replaceProjectIdToken(frozenObj, projectId);
}, /Cannot assign to read only property/);
}, /Cannot assign to read only property|Attempted to assign to readonly property/);
});

it('should replace more than one {{projectId}}', () => {
Expand Down
10 changes: 8 additions & 2 deletions handwritten/spanner/test/partial-result-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ describe('PartialResultStream', () => {
// Node 18's assert.deepStrictEqual strictly requires prototype equality,
// which fails when comparing RowImpl (an Array subclass) with a plain Array literal.
// Node 20+ relaxed this for Array subclasses with constructor = Array.
if (parseInt(process.versions.node.split('.')[0], 10) < 20) {
if (
parseInt(process.versions.node.split('.')[0], 10) < 20 ||
process.versions.bun
) {
assert.deepStrictEqual([...row], EXPECTED_ROW);
} else {
assert.deepStrictEqual(row, EXPECTED_ROW);
Expand Down Expand Up @@ -260,7 +263,10 @@ describe('PartialResultStream', () => {
// Node 18's assert.deepStrictEqual strictly requires prototype equality,
// which fails when comparing RowImpl (an Array subclass) with a plain Array literal.
// Node 20+ relaxed this for Array subclasses with constructor = Array.
if (parseInt(process.versions.node.split('.')[0], 10) < 20) {
if (
parseInt(process.versions.node.split('.')[0], 10) < 20 ||
process.versions.bun
) {
assert.deepStrictEqual([...row], EXPECTED_ROW);
} else {
assert.deepStrictEqual(row, EXPECTED_ROW);
Expand Down
Loading