Skip to content

Commit ea12bee

Browse files
authored
fix(cli-repl): patch WASM wrapper for pac-proxy-agent on s390x MONGOSH-1858 (#2130)
Work around justjake/quickjs-emscripten#123.
1 parent 50de961 commit ea12bee

File tree

4 files changed

+77
-7
lines changed

4 files changed

+77
-7
lines changed

packages/cli-repl/.depcheckrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ ignores:
1818
- ipv6-normalize
1919
- bindings
2020
- system-ca
21+
# used for monkey-patching our s390x fix in
22+
- '@tootallnate/quickjs-emscripten'
2123
ignore-patterns:
2224
- .eslintrc.js
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import assert from 'assert';
2+
3+
const isBigEndian =
4+
new Int32Array(new Uint8Array([1, 0, 0, 0]).buffer)[0] !== 1;
5+
6+
// The pac-proxy-agent module uses a WebAssembly agent under the hood for
7+
// safely evaluating JS. The interface for this doesn't properly account for
8+
// little-endian vs. big-endian host platform distinctions.
9+
10+
// Official support for s390x may not be planned: https://github.com/justjake/quickjs-emscripten/issues/123
11+
12+
export let applyPacProxyS390XPatch: () => void;
13+
if (isBigEndian) {
14+
applyPacProxyS390XPatch = () => {
15+
// eslint-disable-next-line @typescript-eslint/no-var-requires
16+
const {
17+
ModuleMemory,
18+
} = require('@tootallnate/quickjs-emscripten/dist/memory');
19+
20+
const { toPointerArray } = ModuleMemory.prototype;
21+
{
22+
// Consistency check: The version we are currently using is actually broken
23+
const HEAPU8 = new Uint8Array(4);
24+
toPointerArray.call(
25+
new ModuleMemory({
26+
_malloc: () => 0,
27+
HEAPU8,
28+
}),
29+
[{ value: 0x01020304 }]
30+
);
31+
assert.deepStrictEqual([...HEAPU8], [1, 2, 3, 4]); // should be 4, 3, 2, 1
32+
}
33+
34+
ModuleMemory.prototype.toPointerArray = function (
35+
handleArray: { value: number }[]
36+
) {
37+
return toPointerArray.call(
38+
this,
39+
handleArray.map(({ value }) => ({
40+
value:
41+
((value & 0x000000ff) << 24) |
42+
((value & 0x0000ff00) << 8) |
43+
((value & 0x00ff0000) >> 8) |
44+
((value & 0xff000000) >> 24),
45+
}))
46+
);
47+
};
48+
};
49+
} else {
50+
applyPacProxyS390XPatch = () => {
51+
// no-op
52+
};
53+
}

packages/cli-repl/src/run.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { baseBuildInfo, buildInfo } from './build-info';
2222
import { getStoragePaths, getGlobalConfigPaths } from './config-directory';
2323
import { getCryptLibraryPaths } from './crypt-library-paths';
2424
import { getTlsCertificateSelector } from './tls-certificate-selector';
25+
import { applyPacProxyS390XPatch } from './pac-proxy-s390x-patch';
2526
import { redactURICredentials } from '@mongosh/history';
2627
import { generateConnectionInfoFromCliArgs } from '@mongosh/arg-parser';
2728
import askcharacter from 'askcharacter';
@@ -170,6 +171,8 @@ async function main() {
170171
process.removeAllListeners('SIGINT');
171172
}
172173

174+
applyPacProxyS390XPatch();
175+
173176
// If we are spawned via Windows doubleclick, ask the user for an URI to
174177
// connect to. Allow an environment variable to override this for testing.
175178
isSingleConsoleProcess =

packages/e2e-tests/test/e2e-snapshot.spec.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const commonPrefix = (a: string, b: string): string =>
1515
? a
1616
: b && commonPrefix(a, b.slice(0, -1));
1717

18-
describe('e2e startup banners', function () {
18+
describe('e2e snapshot support', function () {
1919
skipIfApiStrict();
2020
afterEach(TestShell.cleanup);
2121

@@ -103,14 +103,22 @@ describe('e2e startup banners', function () {
103103
// console.table(categorized.map(([m, c]) => [m.replace(prefix, ''), c]));
104104
const verifyAllInCategoryMatch = (
105105
category: (typeof categorized)[number][1],
106-
re: RegExp
106+
re: RegExp,
107+
negative = false
107108
) => {
108109
for (const [module, cat] of categorized) {
109110
if (cat === category) {
110-
expect(module).to.match(
111-
re,
112-
`Found unexpected '${module}' in category '${cat}'`
113-
);
111+
if (negative) {
112+
expect(module).not.to.match(
113+
re,
114+
`Found unexpected '${module}' in category '${cat}'`
115+
);
116+
} else {
117+
expect(module).to.match(
118+
re,
119+
`Found unexpected '${module}' in category '${cat}'`
120+
);
121+
}
114122
}
115123
}
116124
};
@@ -138,8 +146,12 @@ describe('e2e startup banners', function () {
138146
);
139147
verifyAllInCategoryMatch(
140148
'nodb-eval',
141-
/^node_modules\/(kerberos|mongodb-client-encryption|glibc-version|@mongodb-js\/devtools-proxy-support|@mongodb-js\/socksv5|agent-base|(win|macos)-export-certificate-and-key)\//
149+
/^node_modules\/(kerberos|mongodb-client-encryption|glibc-version|@mongodb-js\/devtools-proxy-support|@mongodb-js\/socksv5|agent-base|(win|macos)-export-certificate-and-key|@tootallnate\/quickjs-emscripten)\//
142150
);
151+
if (process.arch !== 's390x') {
152+
// quickjs is in the list above but should be exlucded anywhere but on s390x
153+
verifyAllInCategoryMatch('nodb-eval', /quickjs-emscripten/, true);
154+
}
143155
verifyAllThatMatchAreInCategory(
144156
'not-loaded',
145157
/^node_modules\/(express|openid-client|qs|send|jose|execa|body-parser|@babel\/highlight|@babel\/code-frame)\//

0 commit comments

Comments
 (0)