Skip to content

Commit e3be342

Browse files
deepak1556nornagon
authored andcommitted
fix: Use per process native module loader for compiled JS source
nodejs/node#24384
1 parent 8223e4e commit e3be342

File tree

9 files changed

+92
-150
lines changed

9 files changed

+92
-150
lines changed

BUILD.gn

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,7 @@ config("branding") {
5454
}
5555

5656
npm_action("atom_browserify_sandbox") {
57-
deps = [
58-
":atom_js2c_copy",
59-
]
60-
61-
sandbox_args = [
62-
"lib/sandboxed_renderer/init.js",
63-
"-r",
64-
"./lib/sandboxed_renderer/api/exports/electron.js:electron",
65-
"-t",
66-
"aliasify",
67-
]
57+
script = "browserify"
6858

6959
inputs = [
7060
# FIXME(zcbenz): The dependencies of these files are not listed here, so
@@ -73,36 +63,40 @@ npm_action("atom_browserify_sandbox") {
7363
"lib/sandboxed_renderer/init.js",
7464
"lib/sandboxed_renderer/api/exports/electron.js",
7565
]
66+
7667
outputs = [
7768
"$target_gen_dir/js2c/preload_bundle.js",
7869
]
7970

80-
script = "browserify"
81-
args = sandbox_args + [
82-
"-o",
83-
rebase_path(outputs[0]),
84-
]
71+
args = [
72+
"lib/sandboxed_renderer/init.js",
73+
"-r",
74+
"./lib/sandboxed_renderer/api/exports/electron.js:electron",
75+
"-t",
76+
"aliasify",
77+
"-o",
78+
rebase_path(outputs[0]),
79+
]
8580
}
8681

8782
npm_action("atom_browserify_isolated") {
88-
deps = [
89-
":atom_js2c_copy",
90-
]
83+
script = "browserify"
9184

9285
inputs = [
9386
"lib/isolated_renderer/init.js",
9487
]
88+
9589
outputs = [
9690
"$target_gen_dir/js2c/isolated_bundle.js",
9791
]
9892

99-
script = "browserify"
100-
args = inputs + [
101-
"-t",
102-
"aliasify",
103-
"-o",
104-
rebase_path(outputs[0]),
105-
]
93+
args = [
94+
"lib/isolated_renderer/init.js",
95+
"-t",
96+
"aliasify",
97+
"-o",
98+
rebase_path(outputs[0]),
99+
]
106100
}
107101

108102
copy("atom_js2c_copy") {
@@ -122,23 +116,25 @@ action("atom_js2c") {
122116
":atom_js2c_copy",
123117
]
124118

125-
js2c_sources = filenames.js2c_sources
126-
127119
browserify_sources = [
128120
"$target_gen_dir/js2c/isolated_bundle.js",
129121
"$target_gen_dir/js2c/preload_bundle.js",
130122
]
131123

132-
inputs = js2c_sources + browserify_sources
124+
sources = browserify_sources + [
125+
"$target_gen_dir/js2c/asar.js",
126+
"$target_gen_dir/js2c/asar_init.js",
127+
]
133128

129+
inputs = sources
134130
outputs = [
135-
"$target_gen_dir/atom_natives.h",
131+
"$root_gen_dir/atom_natives.cc",
136132
]
137133

138134
script = "tools/js2c.py"
139135
args = [ rebase_path("//third_party/electron_node") ] +
140136
rebase_path(outputs, root_build_dir) +
141-
[ rebase_path("$target_gen_dir/js2c", root_build_dir) ]
137+
rebase_path(sources, root_build_dir)
142138
}
143139

144140
asar("js2asar") {
@@ -337,8 +333,6 @@ static_library("electron_lib") {
337333
sources = filenames.lib_sources
338334
set_sources_assignment_filter(sources_assignment_filter)
339335

340-
sources += [ "$target_gen_dir/atom_natives.h" ]
341-
342336
if (is_component_build) {
343337
defines += [ "NODE_SHARED_MODE" ]
344338
}

atom/common/api/atom_api_asar.cc

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "native_mate/wrappable.h"
1616

1717
#include "atom/common/node_includes.h"
18-
#include "atom_natives.h" // NOLINT: This file is generated with js2c.
18+
#include "third_party/electron_node/src/node_native_module.h"
1919

2020
namespace {
2121

@@ -122,23 +122,15 @@ void InitAsarSupport(v8::Isolate* isolate,
122122
v8::Local<v8::Value> source,
123123
v8::Local<v8::Value> require) {
124124
// Evaluate asar_init.js.
125-
v8::Local<v8::Context> context(isolate->GetCurrentContext());
126-
auto maybe_asar_init = v8::Script::Compile(
127-
context, node::asar_init_value.ToStringChecked(isolate));
128-
v8::Local<v8::Script> asar_init;
129-
v8::Local<v8::Value> result;
130-
if (maybe_asar_init.ToLocal(&asar_init))
131-
result = asar_init->Run(context).ToLocalChecked();
132-
133-
// Initialize asar support.
134-
DCHECK(result->IsFunction());
135-
136-
v8::Local<v8::Value> args[] = {
137-
source,
138-
require,
139-
node::asar_value.ToStringChecked(isolate),
140-
};
141-
result.As<v8::Function>()->Call(result, 3, args);
125+
std::vector<v8::Local<v8::String>> asar_init_params = {
126+
node::FIXED_ONE_BYTE_STRING(isolate, "source"),
127+
node::FIXED_ONE_BYTE_STRING(isolate, "require")};
128+
129+
std::vector<v8::Local<v8::Value>> asar_init_args = {source, require};
130+
131+
node::per_process::native_module_loader.CompileAndCall(
132+
isolate->GetCurrentContext(), "electron/js2c/asar_init",
133+
&asar_init_params, &asar_init_args, nullptr);
142134
}
143135

144136
void Initialize(v8::Local<v8::Object> exports,

atom/common/node_includes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030
#undef NO_RETURN
3131
#undef LIKELY
3232
#undef arraysize
33-
#undef debug_string // This is defined in macOS SDK in AssertMacros.h.
33+
#undef debug_string // This is defined in macOS SDK in AssertMacros.h.
34+
#undef require_string // This is defined in macOS SDK in AssertMacros.h.
3435
#include "env-inl.h"
3536
#include "env.h"
3637
#include "node.h"
37-
#include "node_binding.h"
3838
#include "node_buffer.h"
3939
#include "node_internals.h"
4040
#include "node_options.h"

atom/renderer/atom_renderer_client.cc

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
#include "third_party/blink/public/web/web_local_frame.h"
2222

2323
#include "atom/common/node_includes.h"
24-
#include "atom_natives.h" // NOLINT: This file is generated with js2c
25-
#include "tracing/trace_event.h"
24+
#include "third_party/electron_node/src/node_native_module.h"
2625

2726
namespace atom {
2827

@@ -189,28 +188,20 @@ void AtomRendererClient::SetupMainWorldOverrides(
189188
v8::Handle<v8::Context> context,
190189
content::RenderFrame* render_frame) {
191190
// Setup window overrides in the main world context
192-
v8::Isolate* isolate = context->GetIsolate();
193-
v8::HandleScope handle_scope(isolate);
194-
v8::Context::Scope context_scope(context);
195-
196191
// Wrap the bundle into a function that receives the isolatedWorld as
197192
// an argument.
198-
std::string left = "(function (nodeProcess, isolatedWorld) {\n";
199-
std::string right = "\n})";
200-
auto source = v8::String::Concat(
201-
isolate, mate::ConvertToV8(isolate, left)->ToString(isolate),
202-
v8::String::Concat(isolate,
203-
node::isolated_bundle_value.ToStringChecked(isolate),
204-
mate::ConvertToV8(isolate, right)->ToString(isolate)));
205-
auto result = RunScript(context, source);
206-
DCHECK(result->IsFunction());
207-
208-
v8::Local<v8::Value> args[] = {
193+
auto* isolate = context->GetIsolate();
194+
std::vector<v8::Local<v8::String>> isolated_bundle_params = {
195+
node::FIXED_ONE_BYTE_STRING(isolate, "nodeProcess"),
196+
node::FIXED_ONE_BYTE_STRING(isolate, "isolatedWorld")};
197+
198+
std::vector<v8::Local<v8::Value>> isolated_bundle_args = {
209199
GetEnvironment(render_frame)->process_object(),
210-
GetContext(render_frame->GetWebFrame(), isolate)->Global(),
211-
};
212-
ignore_result(result.As<v8::Function>()->Call(context, v8::Null(isolate),
213-
node::arraysize(args), args));
200+
GetContext(render_frame->GetWebFrame(), isolate)->Global()};
201+
202+
node::per_process::native_module_loader.CompileAndCall(
203+
context, "electron/js2c/isolated_bundle", &isolated_bundle_params,
204+
&isolated_bundle_args, nullptr);
214205
}
215206

216207
node::Environment* AtomRendererClient::GetEnvironment(

atom/renderer/atom_renderer_client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
namespace node {
1616
class Environment;
17-
}
17+
} // namespace node
1818

1919
namespace atom {
2020

atom/renderer/atom_sandboxed_renderer_client.cc

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
#include "third_party/blink/public/web/web_document.h"
2626

2727
#include "atom/common/node_includes.h"
28-
#include "atom_natives.h" // NOLINT: This file is generated with js2c
28+
#include "third_party/electron_node/src/node_binding.h"
29+
#include "third_party/electron_node/src/node_native_module.h"
2930

3031
namespace atom {
3132

@@ -182,30 +183,21 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
182183
!IsDevToolsExtension(render_frame))
183184
return;
184185

186+
// Wrap the bundle into a function that receives the binding object as
187+
// argument.
185188
auto* isolate = context->GetIsolate();
186-
v8::HandleScope handle_scope(isolate);
187-
v8::Context::Scope context_scope(context);
188-
// Wrap the bundle into a function that receives the binding object and the
189-
// preload script path as arguments.
190-
std::string left = "(function(binding, require) {\n";
191-
std::string right = "\n})";
192-
// Compile the wrapper and run it to get the function object
193-
auto source = v8::String::Concat(
194-
isolate, mate::ConvertToV8(isolate, left)->ToString(isolate),
195-
v8::String::Concat(isolate,
196-
node::preload_bundle_value.ToStringChecked(isolate),
197-
mate::ConvertToV8(isolate, right)->ToString(isolate)));
198-
auto result = RunScript(context, source);
199-
200-
DCHECK(result->IsFunction());
201-
// Create and initialize the binding object
202189
auto binding = v8::Object::New(isolate);
203190
InitializeBindings(binding, context);
204191
AddRenderBindings(isolate, binding);
205-
v8::Local<v8::Value> args[] = {binding};
206-
// Execute the function with proper arguments
207-
ignore_result(result.As<v8::Function>()->Call(context, v8::Null(isolate),
208-
node::arraysize(args), args));
192+
193+
std::vector<v8::Local<v8::String>> preload_bundle_params = {
194+
node::FIXED_ONE_BYTE_STRING(isolate, "binding")};
195+
196+
std::vector<v8::Local<v8::Value>> preload_bundle_args = {binding};
197+
198+
node::per_process::native_module_loader.CompileAndCall(
199+
isolate->GetCurrentContext(), "electron/js2c/preload_bundle",
200+
&preload_bundle_params, &preload_bundle_args, nullptr);
209201
}
210202

211203
void AtomSandboxedRendererClient::WillReleaseScriptContext(

filenames.gni

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
filenames = {
2-
js2c_sources = [
3-
"lib/common/asar.js",
4-
"lib/common/asar_init.js",
5-
]
6-
72
js_sources = [
83
"lib/browser/api/app.js",
94
"lib/browser/api/auto-updater.js",

lib/common/asar_init.js

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
'use strict'
22

3-
;(function () { // eslint-disable-line
4-
return function (source, require, asarSource) {
5-
// Expose fs module without asar support.
6-
7-
// NB: Node's 'fs' and 'internal/fs/streams' have a lazy-loaded circular
8-
// dependency. So to expose the unmodified Node 'fs' functionality here,
9-
// we have to copy both 'fs' *and* 'internal/fs/streams' and modify the
10-
// copies to depend on each other instead of on our asarified 'fs' code.
11-
source['original-fs'] = source.fs.replace("require('internal/fs/streams')", "require('original-fs/streams')")
12-
source['original-fs/streams'] = source['internal/fs/streams'].replace("require('fs')", "require('original-fs')")
13-
14-
// Make asar.js accessible via "require".
15-
source.ELECTRON_ASAR = asarSource
16-
17-
// Monkey-patch the fs module.
18-
require('ELECTRON_ASAR').wrapFsWithAsar(require('fs'))
19-
}
20-
})()
3+
/* global source, require */
4+
5+
// Expose fs module without asar support.
6+
// NB: Node's 'fs' and 'internal/fs/streams' have a lazy-loaded circular
7+
// dependency. So to expose the unmodified Node 'fs' functionality here,
8+
// we have to copy both 'fs' *and* 'internal/fs/streams' and modify the
9+
// copies to depend on each other instead of on our asarified 'fs' code.
10+
source['original-fs'].replace("require('internal/fs/streams')", "require('original-fs/streams')")
11+
source['original-fs/streams'].replace("require('fs')", "require('original-fs')")
12+
13+
// Monkey-patch the fs module.
14+
require('electron/js2c/asar').wrapFsWithAsar(require('fs'))

tools/js2c.py

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,38 @@
11
#!/usr/bin/env python
22

3-
import contextlib
4-
import glob
53
import os
64
import subprocess
75
import sys
86

9-
10-
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
11-
127
TEMPLATE = """
13-
#ifndef ATOM_NATIVES_H_
14-
#define ATOM_NATIVES_H_
8+
#include "node_native_module.h"
9+
#include "node_internals.h"
1510
1611
namespace node {{
1712
13+
namespace native_module {{
14+
1815
{definitions}
1916
20-
}} // namespace node
17+
void NativeModuleLoader::LoadEmbedderJavaScriptSource() {{
18+
{initializers}
19+
}}
2120
22-
#endif // ATOM_NATIVES_H_
23-
"""
21+
}} // namespace native_module
2422
23+
}} // namespace node
24+
"""
2525

2626
def main():
2727
node_path = os.path.abspath(sys.argv[1])
2828
natives = os.path.abspath(sys.argv[2])
29-
js_source_files = glob.glob('{0}/*.js'.format(sys.argv[3]))
30-
31-
call_js2c(node_path, natives, js_source_files)
32-
29+
js_source_files = sys.argv[3:]
3330

34-
def call_js2c(node_path, natives, js_source_files):
3531
js2c = os.path.join(node_path, 'tools', 'js2c.py')
36-
src_dir = os.path.dirname(js_source_files[0])
37-
with scoped_cwd(src_dir):
38-
subprocess.check_call(
39-
[sys.executable, js2c, natives] +
40-
[os.path.basename(source) for source in js_source_files] +
41-
['-t', TEMPLATE])
42-
43-
44-
@contextlib.contextmanager
45-
def scoped_cwd(path):
46-
cwd = os.getcwd()
47-
os.chdir(path)
48-
try:
49-
yield
50-
finally:
51-
os.chdir(cwd)
32+
subprocess.check_call(
33+
[sys.executable, js2c, natives] +
34+
js_source_files +
35+
['-t', TEMPLATE])
5236

5337

5438
if __name__ == '__main__':

0 commit comments

Comments
 (0)