@fireemu/darwin-arm64 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/fireemu +0 -0
- package/bin/runner-node/index.mjs +54 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @fireemu/darwin-arm64
|
|
2
2
|
|
|
3
3
|
The [fireemu](https://www.npmjs.com/package/fireemu) daemon built for `darwin-arm64`
|
|
4
|
-
(Rust target `aarch64-apple-darwin`), version 0.
|
|
4
|
+
(Rust target `aarch64-apple-darwin`), version 0.22.0.
|
|
5
5
|
|
|
6
6
|
macOS 13 or newer on Apple silicon.
|
|
7
7
|
|
package/bin/fireemu
CHANGED
|
Binary file
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { pathToFileURL } from "node:url";
|
|
13
|
-
import { existsSync, readFileSync, readlinkSync } from "node:fs";
|
|
13
|
+
import { appendFileSync, existsSync, readFileSync, readlinkSync, writeSync } from "node:fs";
|
|
14
14
|
import { resolve, join, dirname } from "node:path";
|
|
15
15
|
import { createServer } from "node:http";
|
|
16
16
|
import timers from "node:timers";
|
|
17
17
|
const {setTimeout, clearTimeout} = timers;
|
|
18
|
-
import { createRuntimeClock } from "./clock.mjs";
|
|
19
18
|
import { execFileSync, spawn } from "node:child_process";
|
|
20
19
|
import { url as inspectorUrl } from "node:inspector";
|
|
20
|
+
|
|
21
|
+
import { createRuntimeClock } from "./clock.mjs";
|
|
21
22
|
import { instrumentCallables } from "./callable-app-check.mjs";
|
|
22
23
|
import { removeAppCheckToken, withholdsAppCheckToken } from "./app-check-token.mjs";
|
|
23
24
|
import { blockingFailure } from "./blocking-error.mjs";
|
|
@@ -34,10 +35,28 @@ import { installDiagnosticOutput } from "./diagnostic-output.mjs";
|
|
|
34
35
|
import { trackHttpResponse } from "./http-lifecycle.mjs";
|
|
35
36
|
import { createHttpAdmission } from "./http-admission.mjs";
|
|
36
37
|
|
|
38
|
+
const startupTraceEnabled = process.env.FIREEMU_RUNNER_TRACE === '1';
|
|
39
|
+
const startupTracePath = startupTraceEnabled ? join(process.cwd(), 'fireemu-runner-trace.log') : undefined;
|
|
40
|
+
let startupTraceSequence = 0;
|
|
41
|
+
function startupTrace(step) {
|
|
42
|
+
if (!startupTraceEnabled) return;
|
|
43
|
+
const line = `[runner trace ${++startupTraceSequence}] ${step}\n`;
|
|
44
|
+
// Record first so a stalled stderr pipe cannot hide the last startup step.
|
|
45
|
+
try { appendFileSync(startupTracePath, line); }
|
|
46
|
+
catch { /* stderr still reports startup when the working directory is read-only. */ }
|
|
47
|
+
try { writeSync(2, line); }
|
|
48
|
+
catch { /* The file remains available when stderr is broken. */ }
|
|
49
|
+
}
|
|
50
|
+
startupTrace('process start');
|
|
51
|
+
|
|
52
|
+
startupTrace('runner imports complete');
|
|
53
|
+
|
|
37
54
|
// Keep one best-effort terminal diagnostic available after ordinary output
|
|
38
55
|
// admission closes. It is only used when stderr has no pending data, never to
|
|
39
56
|
// bypass a failed/stalled diagnostic channel or grow its queue.
|
|
57
|
+
startupTrace('stderr initialization start');
|
|
40
58
|
const terminalDiagnosticWrite = process.stderr.write.bind(process.stderr);
|
|
59
|
+
startupTrace('stderr initialization complete');
|
|
41
60
|
let outputFailed = false;
|
|
42
61
|
const diagnosticOutput = installDiagnosticOutput(process.stderr, {
|
|
43
62
|
onError() {
|
|
@@ -47,6 +66,8 @@ const diagnosticOutput = installDiagnosticOutput(process.stderr, {
|
|
|
47
66
|
process.exit(2);
|
|
48
67
|
},
|
|
49
68
|
});
|
|
69
|
+
startupTrace('diagnostic output installed');
|
|
70
|
+
startupTrace('stdout initialization start');
|
|
50
71
|
const frameOutput = new FrameWriter(process.stdout, {
|
|
51
72
|
onError(error) {
|
|
52
73
|
outputFailed = true;
|
|
@@ -61,6 +82,7 @@ const frameOutput = new FrameWriter(process.stdout, {
|
|
|
61
82
|
} finally { process.exit(2); }
|
|
62
83
|
},
|
|
63
84
|
});
|
|
85
|
+
startupTrace('stdout frame writer installed');
|
|
64
86
|
let finishingOutput = false;
|
|
65
87
|
let groupCleanupPromise = Promise.resolve(true);
|
|
66
88
|
function finishOutput() {
|
|
@@ -106,7 +128,9 @@ function runnerProcessGroup() {
|
|
|
106
128
|
|
|
107
129
|
// Capture the group before user code can spawn children or replace process information.
|
|
108
130
|
const daemonManagedRunner = process.env.FIREEMU_RUNNER === '1';
|
|
131
|
+
startupTrace('process group initialization start');
|
|
109
132
|
const ownedProcessGroup = daemonManagedRunner ? runnerProcessGroup() : null;
|
|
133
|
+
startupTrace('process group initialization complete');
|
|
110
134
|
let inputCleanupStarted = false;
|
|
111
135
|
let explicitShutdown = false;
|
|
112
136
|
let deferredExitCleanup = false;
|
|
@@ -198,12 +222,16 @@ function killOwnedGroupOnExit() {
|
|
|
198
222
|
catch { /* The group has already ended or signaling was denied. */ }
|
|
199
223
|
}
|
|
200
224
|
process.on('exit', killOwnedGroupOnExit);
|
|
225
|
+
startupTrace('stdin initialization start');
|
|
201
226
|
process.stdin.on('close', () => {
|
|
202
227
|
if (!explicitShutdown) cleanupProcessGroupOnInputClose();
|
|
203
228
|
finishOutput();
|
|
204
229
|
});
|
|
230
|
+
startupTrace('stdin initialization complete');
|
|
205
231
|
process.stdout.write = (chunk, encoding, cb) => process.stderr.write(chunk, encoding, cb);
|
|
232
|
+
startupTrace('stdout redirected');
|
|
206
233
|
|
|
234
|
+
startupTrace('local environment initialization start');
|
|
207
235
|
const localSecrets = (() => {
|
|
208
236
|
const encoded = process.env.FIREEMU_LOCAL_SECRETS_JSON;
|
|
209
237
|
delete process.env.FIREEMU_LOCAL_SECRETS_JSON;
|
|
@@ -211,6 +239,7 @@ const localSecrets = (() => {
|
|
|
211
239
|
const parsed = JSON.parse(encoded);
|
|
212
240
|
return new Map(Object.entries(parsed).filter(([, value]) => typeof value === "string"));
|
|
213
241
|
})();
|
|
242
|
+
startupTrace('local environment initialization complete');
|
|
214
243
|
let functionEnvironmentQueue = Promise.resolve();
|
|
215
244
|
const sharedFunctionInvocations = new Set();
|
|
216
245
|
let activeSharedEnvironments = 0;
|
|
@@ -321,7 +350,9 @@ function parseArgs(argv) {
|
|
|
321
350
|
}
|
|
322
351
|
|
|
323
352
|
const args = parseArgs(process.argv.slice(2));
|
|
353
|
+
startupTrace('argv parsed');
|
|
324
354
|
const sourceDir = resolve(args.source);
|
|
355
|
+
startupTrace('source resolved');
|
|
325
356
|
process.env.FUNCTIONS_EMULATOR = process.env.FUNCTIONS_EMULATOR || "true";
|
|
326
357
|
process.env.FUNCTION_TARGET = process.env.FUNCTION_TARGET || "";
|
|
327
358
|
process.env.FUNCTION_SIGNATURE_TYPE = process.env.FUNCTION_SIGNATURE_TYPE || "";
|
|
@@ -420,6 +451,7 @@ function restoreLocalSecrets(saved) {
|
|
|
420
451
|
}
|
|
421
452
|
|
|
422
453
|
async function loadCodebase() {
|
|
454
|
+
startupTrace('user entry resolution start');
|
|
423
455
|
const pkgPath = join(sourceDir, "package.json");
|
|
424
456
|
let main = "index.js";
|
|
425
457
|
if (existsSync(pkgPath)) {
|
|
@@ -432,7 +464,9 @@ async function loadCodebase() {
|
|
|
432
464
|
}
|
|
433
465
|
const entry = resolve(sourceDir, main);
|
|
434
466
|
if (!existsSync(entry)) throw new Error(`functions entry point ${entry} does not exist`);
|
|
467
|
+
startupTrace('user module import start');
|
|
435
468
|
const mod = await import(pathToFileURL(entry).href);
|
|
469
|
+
startupTrace('user module import end');
|
|
436
470
|
return exportNamespace(mod);
|
|
437
471
|
}
|
|
438
472
|
|
|
@@ -1560,15 +1594,18 @@ function resolveCodebaseParams() {
|
|
|
1560
1594
|
}
|
|
1561
1595
|
|
|
1562
1596
|
async function main() {
|
|
1597
|
+
startupTrace('clock preamble start');
|
|
1563
1598
|
const clockOptions = JSON.parse(process.env.FIREEMU_CLOCK_JSON ?? '{}');
|
|
1564
1599
|
const runtimeClock = createRuntimeClock(clockOptions);
|
|
1565
1600
|
let clockRevision = BigInt(clockOptions.revision ?? '0');
|
|
1566
1601
|
runtimeClock.install();
|
|
1602
|
+
startupTrace('clock preamble installed');
|
|
1567
1603
|
let functions;
|
|
1568
1604
|
let manifest;
|
|
1569
1605
|
let runnerReady = false;
|
|
1570
1606
|
const activeInvocations = new InvocationBudget();
|
|
1571
1607
|
// Read before loading user code, which may await indefinitely after spawning children.
|
|
1608
|
+
startupTrace('stdin frame reader start');
|
|
1572
1609
|
readFrames(
|
|
1573
1610
|
process.stdin,
|
|
1574
1611
|
(msg, payloadBytes) => {
|
|
@@ -1636,10 +1673,15 @@ async function main() {
|
|
|
1636
1673
|
try { process.stderr.write(`${error.message}\n`); } finally { process.exit(2); }
|
|
1637
1674
|
},
|
|
1638
1675
|
);
|
|
1676
|
+
startupTrace('stdin frame reader installed');
|
|
1639
1677
|
// Before any user code loads: the callable options are only observable as a callable is
|
|
1640
1678
|
// declared (spec 13.4).
|
|
1679
|
+
startupTrace('callable instrumentation start');
|
|
1641
1680
|
const instrumentation = instrumentCallables(sourceDir);
|
|
1681
|
+
startupTrace('callable instrumentation complete');
|
|
1682
|
+
startupTrace('parameter initialization start');
|
|
1642
1683
|
resolveWhenDeclared(declaredParamsOfCodebase(), process.env);
|
|
1684
|
+
startupTrace('parameter initialization complete');
|
|
1643
1685
|
let ns;
|
|
1644
1686
|
try {
|
|
1645
1687
|
ns = await loadCodebase();
|
|
@@ -1648,7 +1690,10 @@ async function main() {
|
|
|
1648
1690
|
process.exit(1);
|
|
1649
1691
|
}
|
|
1650
1692
|
// Parameters are resolved before any endpoint option that references one is evaluated.
|
|
1693
|
+
startupTrace('parameter resolution start');
|
|
1651
1694
|
const paramReport = resolveCodebaseParams();
|
|
1695
|
+
startupTrace('parameter resolution complete');
|
|
1696
|
+
startupTrace('global options inspection start');
|
|
1652
1697
|
try {
|
|
1653
1698
|
const require = createRequire(join(sourceDir, "package.json"));
|
|
1654
1699
|
const cjsOptions = require("firebase-functions/v2/options").getGlobalOptions();
|
|
@@ -1666,6 +1711,8 @@ async function main() {
|
|
|
1666
1711
|
} catch (e) {
|
|
1667
1712
|
log("warn", `cannot inspect firebase-functions global options: ${invocationFailure(e).message}`);
|
|
1668
1713
|
}
|
|
1714
|
+
startupTrace('global options inspection complete');
|
|
1715
|
+
startupTrace('function discovery start');
|
|
1669
1716
|
const discovered = collectFunctions(ns);
|
|
1670
1717
|
functions = discovered.functions;
|
|
1671
1718
|
const { broken } = discovered;
|
|
@@ -1709,6 +1756,7 @@ async function main() {
|
|
|
1709
1756
|
reason: d.ignored.reason,
|
|
1710
1757
|
})),
|
|
1711
1758
|
};
|
|
1759
|
+
startupTrace('function discovery complete');
|
|
1712
1760
|
let httpPort;
|
|
1713
1761
|
if (
|
|
1714
1762
|
manifest.functions.some(
|
|
@@ -1719,7 +1767,9 @@ async function main() {
|
|
|
1719
1767
|
)
|
|
1720
1768
|
) {
|
|
1721
1769
|
try {
|
|
1770
|
+
startupTrace('HTTP server start');
|
|
1722
1771
|
const server = await makeHttpServer(functions, manifest);
|
|
1772
|
+
startupTrace('HTTP server ready');
|
|
1723
1773
|
if (server) httpPort = server.address().port;
|
|
1724
1774
|
else
|
|
1725
1775
|
log(
|
|
@@ -1731,6 +1781,7 @@ async function main() {
|
|
|
1731
1781
|
}
|
|
1732
1782
|
}
|
|
1733
1783
|
activeInspectorPort = inspectorPort();
|
|
1784
|
+
startupTrace('hello about to be written');
|
|
1734
1785
|
send({
|
|
1735
1786
|
type: "hello",
|
|
1736
1787
|
runner: "node",
|
|
@@ -1750,6 +1801,7 @@ async function main() {
|
|
|
1750
1801
|
graphs: instrumentation.graphs,
|
|
1751
1802
|
},
|
|
1752
1803
|
});
|
|
1804
|
+
startupTrace('hello written');
|
|
1753
1805
|
runnerReady = true;
|
|
1754
1806
|
}
|
|
1755
1807
|
|