@@ -103,29 +103,54 @@ void NativeModuleLoader::CompileCodeCache( |
103 | 103 |
|
104 | 104 | // TODO(joyeecheung): allow compiling cache for bootstrapper by |
105 | 105 | // switching on id |
106 | | - Local<Value> result = CompileAsModule(env, *id, true); |
| 106 | + MaybeLocal<Value> result = |
| 107 | + CompileAsModule(env, *id, CompilationResultType::kCodeCache); |
107 | 108 | if (!result.IsEmpty()) { |
108 | | - args.GetReturnValue().Set(result); |
| 109 | + args.GetReturnValue().Set(result.ToLocalChecked()); |
109 | 110 | } |
110 | 111 | } |
111 | 112 |
|
112 | 113 | void NativeModuleLoader::CompileFunction( |
113 | 114 | const FunctionCallbackInfo<Value>& args) { |
114 | 115 | Environment* env = Environment::GetCurrent(args); |
115 | | - |
116 | 116 | CHECK(args[0]->IsString()); |
117 | 117 | node::Utf8Value id(env->isolate(), args[0].As<String>()); |
118 | | - Local<Value> result = CompileAsModule(env, *id, false); |
| 118 | + |
| 119 | + MaybeLocal<Value> result = |
| 120 | + CompileAsModule(env, *id, CompilationResultType::kFunction); |
119 | 121 | if (!result.IsEmpty()) { |
120 | | - args.GetReturnValue().Set(result); |
| 122 | + args.GetReturnValue().Set(result.ToLocalChecked()); |
121 | 123 | } |
122 | 124 | } |
123 | 125 |
|
124 | | -Local<Value> NativeModuleLoader::CompileAsModule(Environment* env, |
125 | | - const char* id, |
126 | | - bool produce_code_cache) { |
| 126 | +// TODO(joyeecheung): it should be possible to generate the argument names |
| 127 | +// from some special comments for the bootstrapper case. |
| 128 | +MaybeLocal<Value> NativeModuleLoader::CompileAndCall( |
| 129 | + Local<Context> context, |
| 130 | + const char* id, |
| 131 | + std::vector<Local<String>>* parameters, |
| 132 | + std::vector<Local<Value>>* arguments, |
| 133 | + Environment* optional_env) { |
| 134 | + Isolate* isolate = context->GetIsolate(); |
| 135 | + MaybeLocal<Value> compiled = per_process_loader.LookupAndCompile( |
| 136 | + context, id, parameters, CompilationResultType::kFunction, nullptr); |
| 137 | + if (compiled.IsEmpty()) { |
| 138 | + return compiled; |
| 139 | + } |
| 140 | + Local<Function> fn = compiled.ToLocalChecked().As<Function>(); |
| 141 | + return fn->Call( |
| 142 | + context, v8::Null(isolate), arguments->size(), arguments->data()); |
| 143 | +} |
| 144 | + |
| 145 | +MaybeLocal<Value> NativeModuleLoader::CompileAsModule( |
| 146 | + Environment* env, const char* id, CompilationResultType result) { |
| 147 | + std::vector<Local<String>> parameters = {env->exports_string(), |
| 148 | + env->require_string(), |
| 149 | + env->module_string(), |
| 150 | + env->process_string(), |
| 151 | + env->internal_binding_string()}; |
127 | 152 | return per_process_loader.LookupAndCompile( |
128 | | - env->context(), id, produce_code_cache, env); |
| 153 | + env->context(), id, ¶meters, result, env); |
129 | 154 | } |
130 | 155 |
|
131 | 156 | // Currently V8 only checks that the length of the source code is the |
@@ -183,15 +208,18 @@ ScriptCompiler::CachedData* NativeModuleLoader::GetCachedData( |
183 | 208 | return new ScriptCompiler::CachedData(code_cache_value, code_cache_length); |
184 | 209 | } |
185 | 210 |
|
186 | | -// Returns Local<Function> of the compiled module if produce_code_cache |
| 211 | +// Returns Local<Function> of the compiled module if return_code_cache |
187 | 212 | // is false (we are only compiling the function). |
188 | 213 | // Otherwise return a Local<Object> containing the cache. |
189 | | -Local<Value> NativeModuleLoader::LookupAndCompile(Local<Context> context, |
190 | | - const char* id, |
191 | | - bool produce_code_cache, |
192 | | - Environment* optional_env) { |
| 214 | +MaybeLocal<Value> NativeModuleLoader::LookupAndCompile( |
| 215 | + Local<Context> context, |
| 216 | + const char* id, |
| 217 | + std::vector<Local<String>>* parameters, |
| 218 | + CompilationResultType result_type, |
| 219 | + Environment* optional_env) { |
193 | 220 | Isolate* isolate = context->GetIsolate(); |
194 | 221 | EscapableHandleScope scope(isolate); |
| 222 | + Local<Value> ret; // Used to convert to MaybeLocal before return |
195 | 223 |
|
196 | 224 | Local<String> source = GetSource(isolate, id); |
197 | 225 |
|
@@ -209,7 +237,7 @@ Local<Value> NativeModuleLoader::LookupAndCompile(Local<Context> context, |
209 | 237 | // built with them. |
210 | 238 | // 2. If we are generating code cache for tools/general_code_cache.js, we |
211 | 239 | // are not going to use any cache ourselves. |
212 | | - if (has_code_cache_ && !produce_code_cache) { |
| 240 | + if (has_code_cache_ && result_type == CompilationResultType::kFunction) { |
213 | 241 | cached_data = GetCachedData(id); |
214 | 242 | if (cached_data != nullptr) { |
215 | 243 | use_cache = true; |
@@ -219,50 +247,33 @@ Local<Value> NativeModuleLoader::LookupAndCompile(Local<Context> context, |
219 | 247 | ScriptCompiler::Source script_source(source, origin, cached_data); |
220 | 248 |
|
221 | 249 | ScriptCompiler::CompileOptions options; |
222 | | - if (produce_code_cache) { |
| 250 | + if (result_type == CompilationResultType::kCodeCache) { |
223 | 251 | options = ScriptCompiler::kEagerCompile; |
224 | 252 | } else if (use_cache) { |
225 | 253 | options = ScriptCompiler::kConsumeCodeCache; |
226 | 254 | } else { |
227 | 255 | options = ScriptCompiler::kNoCompileOptions; |
228 | 256 | } |
229 | 257 |
|
230 | | - MaybeLocal<Function> maybe_fun; |
231 | | - // Currently we assume if Environment is ready, then we must be compiling |
232 | | - // native modules instead of bootstrappers. |
233 | | - if (optional_env != nullptr) { |
234 | | - Local<String> parameters[] = {optional_env->exports_string(), |
235 | | - optional_env->require_string(), |
236 | | - optional_env->module_string(), |
237 | | - optional_env->process_string(), |
238 | | - optional_env->internal_binding_string()}; |
239 | | - maybe_fun = ScriptCompiler::CompileFunctionInContext(context, |
240 | | - &script_source, |
241 | | - arraysize(parameters), |
242 | | - parameters, |
243 | | - 0, |
244 | | - nullptr, |
245 | | - options); |
246 | | - } else { |
247 | | - // Until we migrate bootstrappers compilations here this is unreachable |
248 | | - // TODO(joyeecheung): it should be possible to generate the argument names |
249 | | - // from some special comments for the bootstrapper case. |
250 | | - // Note that for bootstrappers we may not be able to get the argument |
251 | | - // names as env->some_string() because we might be compiling before |
252 | | - // those strings are initialized. |
253 | | - UNREACHABLE(); |
254 | | - } |
| 258 | + MaybeLocal<Function> maybe_fun = |
| 259 | + ScriptCompiler::CompileFunctionInContext(context, |
| 260 | + &script_source, |
| 261 | + parameters->size(), |
| 262 | + parameters->data(), |
| 263 | + 0, |
| 264 | + nullptr, |
| 265 | + options); |
255 | 266 |
|
256 | | - Local<Function> fun; |
257 | 267 | // This could fail when there are early errors in the native modules, |
258 | 268 | // e.g. the syntax errors |
259 | | - if (maybe_fun.IsEmpty() || !maybe_fun.ToLocal(&fun)) { |
| 269 | + if (maybe_fun.IsEmpty()) { |
260 | 270 | // In the case of early errors, v8 is already capable of |
261 | 271 | // decorating the stack for us - note that we use CompileFunctionInContext |
262 | 272 | // so there is no need to worry about wrappers. |
263 | | - return scope.Escape(Local<Value>()); |
| 273 | + return MaybeLocal<Value>(); |
264 | 274 | } |
265 | 275 |
|
| 276 | + Local<Function> fun = maybe_fun.ToLocalChecked(); |
266 | 277 | if (use_cache) { |
267 | 278 | if (optional_env != nullptr) { |
268 | 279 | // This could happen when Node is run with any v8 flag, but |
@@ -279,7 +290,7 @@ Local<Value> NativeModuleLoader::LookupAndCompile(Local<Context> context, |
279 | 290 | } |
280 | 291 | } |
281 | 292 |
|
282 | | - if (produce_code_cache) { |
| 293 | + if (result_type == CompilationResultType::kCodeCache) { |
283 | 294 | std::unique_ptr<ScriptCompiler::CachedData> cached_data( |
284 | 295 | ScriptCompiler::CreateCodeCacheForFunction(fun)); |
285 | 296 | CHECK_NE(cached_data, nullptr); |
@@ -296,10 +307,12 @@ Local<Value> NativeModuleLoader::LookupAndCompile(Local<Context> context, |
296 | 307 | copied.release(), |
297 | 308 | cached_data_length, |
298 | 309 | ArrayBufferCreationMode::kInternalized); |
299 | | - return scope.Escape(Uint8Array::New(buf, 0, cached_data_length)); |
| 310 | + ret = Uint8Array::New(buf, 0, cached_data_length); |
300 | 311 | } else { |
301 | | - return scope.Escape(fun); |
| 312 | + ret = fun; |
302 | 313 | } |
| 314 | + |
| 315 | + return scope.Escape(ret); |
303 | 316 | } |
304 | 317 |
|
305 | 318 | void NativeModuleLoader::Initialize(Local<Object> target, |
|