1'use strict';
2const common = require('../common');
3const assert = require('assert');
4const { once } = require('events');
5const v8 = require('v8');
6const { Worker } = require('worker_threads');
7
8// Verify that Workers don't care about --stack-size, as they have their own
9// fixed and known stack sizes.
10
11async function runWorker(options = {}) {
12  const empiricalStackDepth = new Uint32Array(new SharedArrayBuffer(4));
13  const worker = new Worker(`
14  const { workerData: { empiricalStackDepth } } = require('worker_threads');
15  function f() {
16    empiricalStackDepth[0]++;
17    f();
18  }
19  f();`, {
20    eval: true,
21    workerData: { empiricalStackDepth },
22    ...options
23  });
24
25  const [ error ] = await once(worker, 'error');
26  if (!options.skipErrorCheck) {
27    common.expectsError({
28      constructor: RangeError,
29      message: 'Maximum call stack size exceeded'
30    })(error);
31  }
32
33  return empiricalStackDepth[0];
34}
35
36(async function() {
37  {
38    v8.setFlagsFromString('--stack-size=500');
39    const w1stack = await runWorker();
40    v8.setFlagsFromString('--stack-size=1000');
41    const w2stack = await runWorker();
42    // Make sure the two stack sizes are within 10 % of each other, i.e. not
43    // affected by the different `--stack-size` settings.
44    assert(Math.max(w1stack, w2stack) / Math.min(w1stack, w2stack) < 1.1,
45           `w1stack = ${w1stack}, w2stack = ${w2stack} are too far apart`);
46  }
47
48  {
49    const w1stack = await runWorker({ resourceLimits: { stackSizeMb: 0.5 } });
50    const w2stack = await runWorker({ resourceLimits: { stackSizeMb: 1.0 } });
51    // Make sure the two stack sizes are at least 40 % apart from each other,
52    // i.e. affected by the different `stackSizeMb` settings.
53    assert(w2stack > w1stack * 1.4,
54           `w1stack = ${w1stack}, w2stack = ${w2stack} are too close`);
55  }
56
57  // Test that various low stack sizes result in an 'error' event.
58  // Currently the stack size needs to be at least 0.3MB for the worker to be
59  // bootstrapped properly.
60  for (const stackSizeMb of [ 0.3, 0.5, 1 ]) {
61    await runWorker({ resourceLimits: { stackSizeMb }, skipErrorCheck: true });
62  }
63})().then(common.mustCall());
64