diff --git a/README.md b/README.md
index b0f8c46d7..292f1ce92 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Independent daily [test262](https://github.com/tc39/test262) (standard test suit
- [x] Nova [site](https://trynova.dev) [source](https://github.com/trynova/nova)
- [X] NJS [site](https://nginx.org/en/docs/njs/) [source](https://github.com/nginx/njs)
- [ ] Bali [source](https://github.com/ferus-web/bali)
+- [X] Escargot [source](https://github.com/Samsung/escargot)
- Request more in GitHub issues!
### Transpilers
diff --git a/controller/index.js b/controller/index.js
index c657dbff7..9125dab54 100644
--- a/controller/index.js
+++ b/controller/index.js
@@ -28,7 +28,8 @@ const engines = [
'xs',
'njs',
'kiesel',
- 'nova'
+ 'nova',
+ 'escargot'
];
let queue = process.argv[2]?.split(',').map(x => x.trim()).filter(x => x);
diff --git a/controller/oom-killer.js b/controller/oom-killer.js
index 5ca2075a3..142ec1968 100644
--- a/controller/oom-killer.js
+++ b/controller/oom-killer.js
@@ -1,6 +1,6 @@
import { execFile } from 'node:child_process';
-const limit = 1 * 1024 * 1024 * 1024, // 2G
+const limit = 1 * 1024 * 1024 * 1024, // 1G
filter = 'test262/test';
let interval, running = false;
diff --git a/engines/escargot/run.js b/engines/escargot/run.js
new file mode 100644
index 000000000..fc72783de
--- /dev/null
+++ b/engines/escargot/run.js
@@ -0,0 +1,8 @@
+import { $$ } from '../../util.js';
+
+export default (file, module = false) => {
+ const args = [ file ];
+ if (module) args.unshift('--module');
+
+ return $$('./escargot', args);
+};
diff --git a/engines/escargot/runtime.js b/engines/escargot/runtime.js
new file mode 100644
index 000000000..d5780ccd5
--- /dev/null
+++ b/engines/escargot/runtime.js
@@ -0,0 +1 @@
+// Escargot provides the test262 host API natively when built with ESCARGOT_TEST=ON.
\ No newline at end of file
diff --git a/engines/escargot/setup.js b/engines/escargot/setup.js
new file mode 100644
index 000000000..a60e8b525
--- /dev/null
+++ b/engines/escargot/setup.js
@@ -0,0 +1,34 @@
+import { $, $$ } from '../../util.js';
+
+const buildDir = 'escargot-src';
+
+// escargot needs icu, which is keg-only in homebrew so pkg-config can't find it by default
+const icuEnv = () => {
+ if (process.platform !== 'darwin') return {};
+
+ const { stdout, error } = $$('brew', ['--prefix', 'icu4c']);
+ if (error) {
+ console.error('escargot: could not locate icu4c via homebrew, build will likely fail (install with `brew install icu4c`, or set PKG_CONFIG_PATH yourself)');
+ return {};
+ }
+
+ return {
+ PKG_CONFIG_PATH: [`${stdout.trim()}/lib/pkgconfig`, process.env.PKG_CONFIG_PATH].filter(Boolean).join(':')
+ };
+};
+
+export default async () => {
+ const env = icuEnv();
+
+ $(`rm -rf ${buildDir}`);
+ $(`git clone https://github.com/Samsung/escargot.git ${buildDir} --depth=1 --recurse-submodules --shallow-submodules`);
+ const version = $(`git -C ${buildDir} rev-parse HEAD`).trim().slice(0, 7);
+
+ // escargot and its submodules still declare cmake_minimum_required 2.8.12, which cmake 4 rejects outright
+ $(`cmake -S ${buildDir} -B ${buildDir}/build -GNinja -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DESCARGOT_MODE=release -DESCARGOT_OUTPUT=shell -DESCARGOT_TEST=ON -DESCARGOT_TEMPORAL=ON -DESCARGOT_SHADOWREALM=ON`, env);
+ $(`cmake --build ${buildDir}/build`, env);
+ $(`cp -rf ${buildDir}/build/escargot ./escargot`);
+ $(`rm -rf ${buildDir}`);
+
+ return { version };
+};