Skip to content

Commit acb591a

Browse files
authored
feat: allow using default libuv event loop (#37)
This may be required by some legacy addons which refer to the default libuv event loop. Fixes: #36
1 parent 9c98887 commit acb591a

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

bin/boxednode.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const argv = require('yargs')
2727
.option('namespace', {
2828
alias: 'N', type: 'string', desc: 'Module identifier for the generated binary'
2929
})
30+
.options('use-legacy-default-uv-loop', {
31+
type: 'boolean', desc: 'Use the global singleton libuv event loop rather than a separate local one'
32+
})
3033
.example('$0 -s myProject.js -t myProject.exe -n ^14.0.0',
3134
'Create myProject.exe from myProject.js using Node.js v14')
3235
.help()
@@ -42,7 +45,8 @@ const argv = require('yargs')
4245
clean: argv.c,
4346
configureArgs: (argv.C || '').split(',').filter(Boolean),
4447
makeArgs: (argv.M || '').split(',').filter(Boolean),
45-
namespace: argv.N
48+
namespace: argv.N,
49+
useLegacyDefaultUvLoop: argv.useLegacyDefaultUvLoop
4650
});
4751
} catch (err) {
4852
console.error(err);

resources/main-template.cc

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,29 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
6060
const std::vector<std::string>& args,
6161
const std::vector<std::string>& exec_args) {
6262
int exit_code = 0;
63+
uv_loop_t* loop;
64+
#ifndef BOXEDNODE_USE_DEFAULT_UV_LOOP
6365
// Set up a libuv event loop.
64-
uv_loop_t loop;
65-
int ret = uv_loop_init(&loop);
66+
uv_loop_t loop_;
67+
loop = &loop_;
68+
int ret = uv_loop_init(loop);
6669
if (ret != 0) {
6770
fprintf(stderr, "%s: Failed to initialize loop: %s\n",
6871
args[0].c_str(),
6972
uv_err_name(ret));
7073
return 1;
7174
}
75+
#else
76+
loop = uv_default_loop();
77+
#endif
7278

7379
std::shared_ptr<ArrayBufferAllocator> allocator =
7480
ArrayBufferAllocator::Create();
7581

7682
#if NODE_VERSION_AT_LEAST(14, 0, 0)
77-
Isolate* isolate = NewIsolate(allocator, &loop, platform);
83+
Isolate* isolate = NewIsolate(allocator, loop, platform);
7884
#else
79-
Isolate* isolate = NewIsolate(allocator.get(), &loop, platform);
85+
Isolate* isolate = NewIsolate(allocator.get(), loop, platform);
8086
#endif
8187
if (isolate == nullptr) {
8288
fprintf(stderr, "%s: Failed to initialize V8 Isolate\n", args[0].c_str());
@@ -90,7 +96,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
9096
// Create a node::IsolateData instance that will later be released using
9197
// node::FreeIsolateData().
9298
std::unique_ptr<IsolateData, decltype(&node::FreeIsolateData)> isolate_data(
93-
node::CreateIsolateData(isolate, &loop, platform, allocator.get()),
99+
node::CreateIsolateData(isolate, loop, platform, allocator.get()),
94100
node::FreeIsolateData);
95101

96102
// Set up a new v8::Context.
@@ -154,15 +160,15 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
154160
SealHandleScope seal(isolate);
155161
bool more;
156162
do {
157-
uv_run(&loop, UV_RUN_DEFAULT);
163+
uv_run(loop, UV_RUN_DEFAULT);
158164

159165
// V8 tasks on background threads may end up scheduling new tasks in the
160166
// foreground, which in turn can keep the event loop going. For example,
161167
// WebAssembly.compile() may do so.
162168
platform->DrainTasks(isolate);
163169

164170
// If there are new tasks, continue.
165-
more = uv_loop_alive(&loop);
171+
more = uv_loop_alive(loop);
166172
if (more) continue;
167173

168174
// node::EmitBeforeExit() is used to emit the 'beforeExit' event on
@@ -171,7 +177,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
171177

172178
// 'beforeExit' can also schedule new work that keeps the event loop
173179
// running.
174-
more = uv_loop_alive(&loop);
180+
more = uv_loop_alive(loop);
175181
} while (more == true);
176182
}
177183

@@ -196,9 +202,11 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
196202

197203
// Wait until the platform has cleaned up all relevant resources.
198204
while (!platform_finished)
199-
uv_run(&loop, UV_RUN_ONCE);
200-
int err = uv_loop_close(&loop);
205+
uv_run(loop, UV_RUN_ONCE);
206+
#ifndef BOXEDNODE_USE_DEFAULT_UV_LOOP
207+
int err = uv_loop_close(loop);
201208
assert(err == 0);
209+
#endif
202210

203211
return exit_code;
204212
}

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ type CompilationOptions = {
229229
namespace?: string,
230230
addons?: AddonConfig[],
231231
enableBindingsPatch?: boolean,
232+
useLegacyDefaultUvLoop?: boolean;
232233
executableMetadata?: ExecutableMetadata,
233234
preCompileHook?: (nodeSourceTree: string, options: CompilationOptions) => void | Promise<void>
234235
}
@@ -301,6 +302,9 @@ async function compileJSFileAsBinaryImpl (options: CompilationOptions, logger: L
301302
registerFunctions.map((fn) => `${fn},`).join(''));
302303
mainSource = mainSource.replace(/\bREPLACE_WITH_MAIN_SCRIPT_SOURCE_GETTER\b/g,
303304
createCppJsStringDefinition('GetBoxednodeMainScriptSource', jsMainSource));
305+
if (options.useLegacyDefaultUvLoop) {
306+
mainSource = `#define BOXEDNODE_USE_DEFAULT_UV_LOOP 1\n${mainSource}`;
307+
}
304308
await fs.writeFile(path.join(nodeSourcePath, 'src', 'node_main.cc'), mainSource);
305309
logger.stepCompleted();
306310
}

0 commit comments

Comments
 (0)