diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/env.h | 490 | ||||
-rw-r--r-- | src/node.cc | 27 | ||||
-rw-r--r-- | src/node_code_cache.h | 2 | ||||
-rw-r--r-- | src/node_code_cache_stub.cc | 3 | ||||
-rw-r--r-- | src/node_internals.h | 1 | ||||
-rw-r--r-- | src/node_native_module.cc | 326 | ||||
-rw-r--r-- | src/node_native_module.h | 41 |
7 files changed, 634 insertions, 256 deletions
@@ -120,248 +120,258 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2; // Strings are per-isolate primitives but Environment proxies them // for the sake of convenience. Strings should be ASCII-only. -#define PER_ISOLATE_STRING_PROPERTIES(V) \ - V(address_string, "address") \ - V(aliases_string, "aliases") \ - V(args_string, "args") \ - V(async_ids_stack_string, "async_ids_stack") \ - V(buffer_string, "buffer") \ - V(bytes_parsed_string, "bytesParsed") \ - V(bytes_read_string, "bytesRead") \ - V(bytes_written_string, "bytesWritten") \ - V(cached_data_string, "cachedData") \ - V(cached_data_produced_string, "cachedDataProduced") \ - V(cached_data_rejected_string, "cachedDataRejected") \ - V(change_string, "change") \ - V(channel_string, "channel") \ - V(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite") \ - V(constants_string, "constants") \ - V(oncertcb_string, "oncertcb") \ - V(code_string, "code") \ - V(cwd_string, "cwd") \ - V(dest_string, "dest") \ - V(destroyed_string, "destroyed") \ - V(detached_string, "detached") \ - V(dns_a_string, "A") \ - V(dns_aaaa_string, "AAAA") \ - V(dns_cname_string, "CNAME") \ - V(dns_mx_string, "MX") \ - V(dns_naptr_string, "NAPTR") \ - V(dns_ns_string, "NS") \ - V(dns_ptr_string, "PTR") \ - V(dns_soa_string, "SOA") \ - V(dns_srv_string, "SRV") \ - V(dns_txt_string, "TXT") \ - V(duration_string, "duration") \ - V(emit_warning_string, "emitWarning") \ - V(exchange_string, "exchange") \ - V(encoding_string, "encoding") \ - V(entries_string, "entries") \ - V(entry_type_string, "entryType") \ - V(env_pairs_string, "envPairs") \ - V(env_var_settings_string, "envVarSettings") \ - V(errno_string, "errno") \ - V(error_string, "error") \ - V(exit_code_string, "exitCode") \ - V(expire_string, "expire") \ - V(exponent_string, "exponent") \ - V(exports_string, "exports") \ - V(ext_key_usage_string, "ext_key_usage") \ - V(external_stream_string, "_externalStream") \ - V(family_string, "family") \ - V(fatal_exception_string, "_fatalException") \ - V(fd_string, "fd") \ - V(file_string, "file") \ - V(fingerprint_string, "fingerprint") \ - V(fingerprint256_string, "fingerprint256") \ - V(flags_string, "flags") \ - V(fragment_string, "fragment") \ - V(get_data_clone_error_string, "_getDataCloneError") \ - V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ - V(gid_string, "gid") \ - V(handle_string, "handle") \ - V(help_text_string, "helpText") \ - V(homedir_string, "homedir") \ - V(host_string, "host") \ - V(hostmaster_string, "hostmaster") \ - V(ignore_string, "ignore") \ - V(infoaccess_string, "infoAccess") \ - V(inherit_string, "inherit") \ - V(input_string, "input") \ - V(internal_string, "internal") \ - V(ipv4_string, "IPv4") \ - V(ipv6_string, "IPv6") \ - V(isclosing_string, "isClosing") \ - V(issuer_string, "issuer") \ - V(issuercert_string, "issuerCertificate") \ - V(kill_signal_string, "killSignal") \ - V(kind_string, "kind") \ - V(mac_string, "mac") \ - V(main_string, "main") \ - V(max_buffer_string, "maxBuffer") \ - V(message_string, "message") \ - V(message_port_string, "messagePort") \ - V(message_port_constructor_string, "MessagePort") \ - V(minttl_string, "minttl") \ - V(modulus_string, "modulus") \ - V(name_string, "name") \ - V(netmask_string, "netmask") \ - V(nsname_string, "nsname") \ - V(ocsp_request_string, "OCSPRequest") \ - V(onaltsvc_string, "onaltsvc") \ - V(onchange_string, "onchange") \ - V(onclienthello_string, "onclienthello") \ - V(oncomplete_string, "oncomplete") \ - V(onconnection_string, "onconnection") \ - V(ondone_string, "ondone") \ - V(onerror_string, "onerror") \ - V(onexit_string, "onexit") \ - V(onframeerror_string, "onframeerror") \ - V(ongetpadding_string, "ongetpadding") \ - V(onhandshakedone_string, "onhandshakedone") \ - V(onhandshakestart_string, "onhandshakestart") \ - V(onheaders_string, "onheaders") \ - V(onmessage_string, "onmessage") \ - V(onnewsession_string, "onnewsession") \ - V(onocspresponse_string, "onocspresponse") \ - V(ongoawaydata_string, "ongoawaydata") \ - V(onorigin_string, "onorigin") \ - V(onpriority_string, "onpriority") \ - V(onread_string, "onread") \ - V(onreadstart_string, "onreadstart") \ - V(onreadstop_string, "onreadstop") \ - V(onping_string, "onping") \ - V(onsettings_string, "onsettings") \ - V(onshutdown_string, "onshutdown") \ - V(onsignal_string, "onsignal") \ - V(onstreamclose_string, "onstreamclose") \ - V(ontrailers_string, "ontrailers") \ - V(onunpipe_string, "onunpipe") \ - V(onwrite_string, "onwrite") \ - V(openssl_error_stack, "opensslErrorStack") \ - V(options_string, "options") \ - V(output_string, "output") \ - V(order_string, "order") \ - V(parse_error_string, "Parse Error") \ - V(password_string, "password") \ - V(path_string, "path") \ - V(pending_handle_string, "pendingHandle") \ - V(pid_string, "pid") \ - V(pipe_string, "pipe") \ - V(pipe_target_string, "pipeTarget") \ - V(pipe_source_string, "pipeSource") \ - V(port_string, "port") \ - V(port1_string, "port1") \ - V(port2_string, "port2") \ - V(preference_string, "preference") \ - V(priority_string, "priority") \ - V(promise_string, "promise") \ - V(pubkey_string, "pubkey") \ - V(query_string, "query") \ - V(raw_string, "raw") \ - V(read_host_object_string, "_readHostObject") \ - V(readable_string, "readable") \ - V(reason_string, "reason") \ - V(refresh_string, "refresh") \ - V(regexp_string, "regexp") \ - V(rename_string, "rename") \ - V(replacement_string, "replacement") \ - V(retry_string, "retry") \ - V(scheme_string, "scheme") \ - V(serial_string, "serial") \ - V(scopeid_string, "scopeid") \ - V(serial_number_string, "serialNumber") \ - V(service_string, "service") \ - V(servername_string, "servername") \ - V(session_id_string, "sessionId") \ - V(shell_string, "shell") \ - V(signal_string, "signal") \ - V(sink_string, "sink") \ - V(size_string, "size") \ - V(sni_context_err_string, "Invalid SNI context") \ - V(sni_context_string, "sni_context") \ - V(source_string, "source") \ - V(stack_string, "stack") \ - V(start_time_string, "startTime") \ - V(status_string, "status") \ - V(stdio_string, "stdio") \ - V(subject_string, "subject") \ - V(subjectaltname_string, "subjectaltname") \ - V(syscall_string, "syscall") \ - V(thread_id_string, "threadId") \ - V(ticketkeycallback_string, "onticketkeycallback") \ - V(timeout_string, "timeout") \ - V(tls_ticket_string, "tlsTicket") \ - V(ttl_string, "ttl") \ - V(type_string, "type") \ - V(uid_string, "uid") \ - V(unknown_string, "<unknown>") \ - V(url_string, "url") \ - V(username_string, "username") \ - V(valid_from_string, "valid_from") \ - V(valid_to_string, "valid_to") \ - V(value_string, "value") \ - V(verify_error_string, "verifyError") \ - V(version_string, "version") \ - V(weight_string, "weight") \ - V(windows_hide_string, "windowsHide") \ - V(windows_verbatim_arguments_string, "windowsVerbatimArguments") \ - V(wrap_string, "wrap") \ - V(writable_string, "writable") \ - V(write_host_object_string, "_writeHostObject") \ - V(write_queue_size_string, "writeQueueSize") \ - V(x_forwarded_string, "x-forwarded-for") \ +#define PER_ISOLATE_STRING_PROPERTIES(V) \ + V(address_string, "address") \ + V(aliases_string, "aliases") \ + V(args_string, "args") \ + V(async_ids_stack_string, "async_ids_stack") \ + V(buffer_string, "buffer") \ + V(bytes_parsed_string, "bytesParsed") \ + V(bytes_read_string, "bytesRead") \ + V(bytes_written_string, "bytesWritten") \ + V(cached_data_string, "cachedData") \ + V(cached_data_produced_string, "cachedDataProduced") \ + V(cached_data_rejected_string, "cachedDataRejected") \ + V(change_string, "change") \ + V(channel_string, "channel") \ + V(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite") \ + V(constants_string, "constants") \ + V(oncertcb_string, "oncertcb") \ + V(code_string, "code") \ + V(cwd_string, "cwd") \ + V(dest_string, "dest") \ + V(destroyed_string, "destroyed") \ + V(detached_string, "detached") \ + V(dns_a_string, "A") \ + V(dns_aaaa_string, "AAAA") \ + V(dns_cname_string, "CNAME") \ + V(dns_mx_string, "MX") \ + V(dns_naptr_string, "NAPTR") \ + V(dns_ns_string, "NS") \ + V(dns_ptr_string, "PTR") \ + V(dns_soa_string, "SOA") \ + V(dns_srv_string, "SRV") \ + V(dns_txt_string, "TXT") \ + V(duration_string, "duration") \ + V(emit_warning_string, "emitWarning") \ + V(exchange_string, "exchange") \ + V(encoding_string, "encoding") \ + V(entries_string, "entries") \ + V(entry_type_string, "entryType") \ + V(env_pairs_string, "envPairs") \ + V(env_var_settings_string, "envVarSettings") \ + V(errno_string, "errno") \ + V(error_string, "error") \ + V(exit_code_string, "exitCode") \ + V(expire_string, "expire") \ + V(exponent_string, "exponent") \ + V(exports_string, "exports") \ + V(ext_key_usage_string, "ext_key_usage") \ + V(external_stream_string, "_externalStream") \ + V(family_string, "family") \ + V(fatal_exception_string, "_fatalException") \ + V(fd_string, "fd") \ + V(file_string, "file") \ + V(fingerprint_string, "fingerprint") \ + V(fingerprint256_string, "fingerprint256") \ + V(flags_string, "flags") \ + V(fragment_string, "fragment") \ + V(get_data_clone_error_string, "_getDataCloneError") \ + V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ + V(gid_string, "gid") \ + V(handle_string, "handle") \ + V(help_text_string, "helpText") \ + V(homedir_string, "homedir") \ + V(host_string, "host") \ + V(hostmaster_string, "hostmaster") \ + V(ignore_string, "ignore") \ + V(infoaccess_string, "infoAccess") \ + V(inherit_string, "inherit") \ + V(input_string, "input") \ + V(internal_string, "internal") \ + V(internal_binding_string, "internalBinding") \ + V(ipv4_string, "IPv4") \ + V(ipv6_string, "IPv6") \ + V(isclosing_string, "isClosing") \ + V(issuer_string, "issuer") \ + V(issuercert_string, "issuerCertificate") \ + V(kill_signal_string, "killSignal") \ + V(kind_string, "kind") \ + V(mac_string, "mac") \ + V(main_string, "main") \ + V(max_buffer_string, "maxBuffer") \ + V(message_string, "message") \ + V(message_port_string, "messagePort") \ + V(message_port_constructor_string, "MessagePort") \ + V(minttl_string, "minttl") \ + V(module_string, "module") \ + V(modulus_string, "modulus") \ + V(name_string, "name") \ + V(netmask_string, "netmask") \ + V(nsname_string, "nsname") \ + V(ocsp_request_string, "OCSPRequest") \ + V(onaltsvc_string, "onaltsvc") \ + V(onchange_string, "onchange") \ + V(onclienthello_string, "onclienthello") \ + V(oncomplete_string, "oncomplete") \ + V(onconnection_string, "onconnection") \ + V(ondone_string, "ondone") \ + V(onerror_string, "onerror") \ + V(onexit_string, "onexit") \ + V(onframeerror_string, "onframeerror") \ + V(ongetpadding_string, "ongetpadding") \ + V(onhandshakedone_string, "onhandshakedone") \ + V(onhandshakestart_string, "onhandshakestart") \ + V(onheaders_string, "onheaders") \ + V(onmessage_string, "onmessage") \ + V(onnewsession_string, "onnewsession") \ + V(onocspresponse_string, "onocspresponse") \ + V(ongoawaydata_string, "ongoawaydata") \ + V(onorigin_string, "onorigin") \ + V(onpriority_string, "onpriority") \ + V(onread_string, "onread") \ + V(onreadstart_string, "onreadstart") \ + V(onreadstop_string, "onreadstop") \ + V(onping_string, "onping") \ + V(onsettings_string, "onsettings") \ + V(onshutdown_string, "onshutdown") \ + V(onsignal_string, "onsignal") \ + V(onstreamclose_string, "onstreamclose") \ + V(ontrailers_string, "ontrailers") \ + V(onunpipe_string, "onunpipe") \ + V(onwrite_string, "onwrite") \ + V(openssl_error_stack, "opensslErrorStack") \ + V(options_string, "options") \ + V(output_string, "output") \ + V(order_string, "order") \ + V(parse_error_string, "Parse Error") \ + V(password_string, "password") \ + V(path_string, "path") \ + V(pending_handle_string, "pendingHandle") \ + V(pid_string, "pid") \ + V(pipe_string, "pipe") \ + V(pipe_target_string, "pipeTarget") \ + V(pipe_source_string, "pipeSource") \ + V(port_string, "port") \ + V(port1_string, "port1") \ + V(port2_string, "port2") \ + V(preference_string, "preference") \ + V(priority_string, "priority") \ + V(process_string, "process") \ + V(promise_string, "promise") \ + V(pubkey_string, "pubkey") \ + V(query_string, "query") \ + V(raw_string, "raw") \ + V(read_host_object_string, "_readHostObject") \ + V(readable_string, "readable") \ + V(reason_string, "reason") \ + V(refresh_string, "refresh") \ + V(regexp_string, "regexp") \ + V(rename_string, "rename") \ + V(replacement_string, "replacement") \ + V(require_string, "require") \ + V(retry_string, "retry") \ + V(scheme_string, "scheme") \ + V(serial_string, "serial") \ + V(scopeid_string, "scopeid") \ + V(serial_number_string, "serialNumber") \ + V(service_string, "service") \ + V(servername_string, "servername") \ + V(session_id_string, "sessionId") \ + V(shell_string, "shell") \ + V(signal_string, "signal") \ + V(sink_string, "sink") \ + V(size_string, "size") \ + V(sni_context_err_string, "Invalid SNI context") \ + V(sni_context_string, "sni_context") \ + V(source_string, "source") \ + V(stack_string, "stack") \ + V(start_time_string, "startTime") \ + V(status_string, "status") \ + V(stdio_string, "stdio") \ + V(subject_string, "subject") \ + V(subjectaltname_string, "subjectaltname") \ + V(syscall_string, "syscall") \ + V(thread_id_string, "threadId") \ + V(ticketkeycallback_string, "onticketkeycallback") \ + V(timeout_string, "timeout") \ + V(tls_ticket_string, "tlsTicket") \ + V(ttl_string, "ttl") \ + V(type_string, "type") \ + V(uid_string, "uid") \ + V(unknown_string, "<unknown>") \ + V(url_string, "url") \ + V(username_string, "username") \ + V(valid_from_string, "valid_from") \ + V(valid_to_string, "valid_to") \ + V(value_string, "value") \ + V(verify_error_string, "verifyError") \ + V(version_string, "version") \ + V(weight_string, "weight") \ + V(windows_hide_string, "windowsHide") \ + V(windows_verbatim_arguments_string, "windowsVerbatimArguments") \ + V(wrap_string, "wrap") \ + V(writable_string, "writable") \ + V(write_host_object_string, "_writeHostObject") \ + V(write_queue_size_string, "writeQueueSize") \ + V(x_forwarded_string, "x-forwarded-for") \ V(zero_return_string, "ZERO_RETURN") -#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \ - V(as_external, v8::External) \ - V(async_hooks_after_function, v8::Function) \ - V(async_hooks_before_function, v8::Function) \ - V(async_hooks_binding, v8::Object) \ - V(async_hooks_destroy_function, v8::Function) \ - V(async_hooks_init_function, v8::Function) \ - V(async_hooks_promise_resolve_function, v8::Function) \ - V(async_wrap_object_ctor_template, v8::FunctionTemplate) \ - V(async_wrap_ctor_template, v8::FunctionTemplate) \ - V(buffer_prototype_object, v8::Object) \ - V(context, v8::Context) \ - V(domain_callback, v8::Function) \ - V(domexception_function, v8::Function) \ - V(fdclose_constructor_template, v8::ObjectTemplate) \ - V(fd_constructor_template, v8::ObjectTemplate) \ - V(filehandlereadwrap_template, v8::ObjectTemplate) \ - V(fsreqpromise_constructor_template, v8::ObjectTemplate) \ - V(fs_use_promises_symbol, v8::Symbol) \ - V(handle_wrap_ctor_template, v8::FunctionTemplate) \ - V(host_import_module_dynamically_callback, v8::Function) \ - V(host_initialize_import_meta_object_callback, v8::Function) \ - V(http2ping_constructor_template, v8::ObjectTemplate) \ - V(http2settings_constructor_template, v8::ObjectTemplate) \ - V(http2stream_constructor_template, v8::ObjectTemplate) \ - V(immediate_callback_function, v8::Function) \ - V(inspector_console_api_object, v8::Object) \ - V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \ - V(message_port, v8::Object) \ - V(message_port_constructor_template, v8::FunctionTemplate) \ - V(pipe_constructor_template, v8::FunctionTemplate) \ - V(performance_entry_callback, v8::Function) \ - V(performance_entry_template, v8::Function) \ - V(process_object, v8::Object) \ - V(promise_handler_function, v8::Function) \ - V(promise_wrap_template, v8::ObjectTemplate) \ - V(sab_lifetimepartner_constructor_template, v8::FunctionTemplate) \ - V(script_context_constructor_template, v8::FunctionTemplate) \ - V(script_data_constructor_function, v8::Function) \ - V(secure_context_constructor_template, v8::FunctionTemplate) \ - V(shutdown_wrap_template, v8::ObjectTemplate) \ - V(tcp_constructor_template, v8::FunctionTemplate) \ - V(tick_callback_function, v8::Function) \ - V(timers_callback_function, v8::Function) \ - V(tls_wrap_constructor_function, v8::Function) \ - V(trace_category_state_function, v8::Function) \ - V(tty_constructor_template, v8::FunctionTemplate) \ - V(udp_constructor_function, v8::Function) \ - V(url_constructor_function, v8::Function) \ +#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \ + V(as_external, v8::External) \ + V(async_hooks_after_function, v8::Function) \ + V(async_hooks_before_function, v8::Function) \ + V(async_hooks_binding, v8::Object) \ + V(async_hooks_destroy_function, v8::Function) \ + V(async_hooks_init_function, v8::Function) \ + V(async_hooks_promise_resolve_function, v8::Function) \ + V(async_wrap_object_ctor_template, v8::FunctionTemplate) \ + V(async_wrap_ctor_template, v8::FunctionTemplate) \ + V(buffer_prototype_object, v8::Object) \ + V(context, v8::Context) \ + V(domain_callback, v8::Function) \ + V(domexception_function, v8::Function) \ + V(fdclose_constructor_template, v8::ObjectTemplate) \ + V(fd_constructor_template, v8::ObjectTemplate) \ + V(filehandlereadwrap_template, v8::ObjectTemplate) \ + V(fsreqpromise_constructor_template, v8::ObjectTemplate) \ + V(fs_use_promises_symbol, v8::Symbol) \ + V(handle_wrap_ctor_template, v8::FunctionTemplate) \ + V(host_import_module_dynamically_callback, v8::Function) \ + V(host_initialize_import_meta_object_callback, v8::Function) \ + V(http2ping_constructor_template, v8::ObjectTemplate) \ + V(http2settings_constructor_template, v8::ObjectTemplate) \ + V(http2stream_constructor_template, v8::ObjectTemplate) \ + V(immediate_callback_function, v8::Function) \ + V(inspector_console_api_object, v8::Object) \ + V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \ + V(message_port, v8::Object) \ + V(message_port_constructor_template, v8::FunctionTemplate) \ + V(native_modules_code_cache, v8::Object) \ + V(native_modules_code_cache_hash, v8::Object) \ + V(native_modules_source, v8::Object) \ + V(native_modules_source_hash, v8::Object) \ + V(native_modules_with_cache, v8::Set) \ + V(native_modules_without_cache, v8::Set) \ + V(pipe_constructor_template, v8::FunctionTemplate) \ + V(performance_entry_callback, v8::Function) \ + V(performance_entry_template, v8::Function) \ + V(process_object, v8::Object) \ + V(promise_handler_function, v8::Function) \ + V(promise_wrap_template, v8::ObjectTemplate) \ + V(sab_lifetimepartner_constructor_template, v8::FunctionTemplate) \ + V(script_context_constructor_template, v8::FunctionTemplate) \ + V(script_data_constructor_function, v8::Function) \ + V(secure_context_constructor_template, v8::FunctionTemplate) \ + V(shutdown_wrap_template, v8::ObjectTemplate) \ + V(tcp_constructor_template, v8::FunctionTemplate) \ + V(tick_callback_function, v8::Function) \ + V(timers_callback_function, v8::Function) \ + V(tls_wrap_constructor_function, v8::Function) \ + V(trace_category_state_function, v8::Function) \ + V(tty_constructor_template, v8::FunctionTemplate) \ + V(udp_constructor_function, v8::Function) \ + V(url_constructor_function, v8::Function) \ V(write_wrap_template, v8::ObjectTemplate) class Environment; diff --git a/src/node.cc b/src/node.cc index d4272bea20..48e8f0a249 100644 --- a/src/node.cc +++ b/src/node.cc @@ -25,10 +25,9 @@ #include "node_errors.h" #include "node_internals.h" #include "node_javascript.h" -#include "node_code_cache.h" +#include "node_native_module.h" +#include "node_perf.h" #include "node_platform.h" -#include "node_version.h" -#include "node_internals.h" #include "node_revert.h" #include "node_version.h" #include "tracing/traced_value.h" @@ -131,6 +130,7 @@ typedef int mode_t; namespace node { +using native_module::NativeModule; using options_parser::kAllowedInEnvironment; using options_parser::kDisallowedInEnvironment; using v8::Array; @@ -775,6 +775,7 @@ static MaybeLocal<Value> ExecuteString(Environment* env, try_catch.SetVerbose(false); ScriptOrigin origin(filename); + MaybeLocal<Script> script = Script::Compile(env->context(), source, &origin); if (script.IsEmpty()) { @@ -1222,19 +1223,7 @@ static void GetInternalBinding(const FunctionCallbackInfo<Value>& args) { DefineConstants(env->isolate(), exports); } else if (!strcmp(*module_v, "natives")) { exports = Object::New(env->isolate()); - DefineJavaScript(env, exports); - } else if (!strcmp(*module_v, "code_cache")) { - // internalBinding('code_cache') - exports = Object::New(env->isolate()); - DefineCodeCache(env, exports); - } else if (!strcmp(*module_v, "code_cache_hash")) { - // internalBinding('code_cache_hash') - exports = Object::New(env->isolate()); - DefineCodeCacheHash(env, exports); - } else if (!strcmp(*module_v, "natives_hash")) { - // internalBinding('natives_hash') - exports = Object::New(env->isolate()); - DefineJavaScriptHash(env, exports); + NativeModule::GetNatives(env, exports); } else { return ThrowIfNoSuchModule(env, *module_v); } @@ -1772,6 +1761,8 @@ void LoadEnvironment(Environment* env) { // lib/internal/bootstrap/node.js, each included as a static C string // defined in node_javascript.h, generated in node_javascript.cc by // node_js2c. + + // TODO(joyeecheung): use NativeModule::Compile Local<String> loaders_name = FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/loaders.js"); MaybeLocal<Function> loaders_bootstrapper = @@ -1831,6 +1822,8 @@ void LoadEnvironment(Environment* env) { env->options()->debug_options->break_node_first_line) }; + NativeModule::LoadBindings(env); + // Bootstrap internal loaders Local<Value> bootstrapped_loaders; if (!ExecuteBootstrapper(env, loaders_bootstrapper.ToLocalChecked(), @@ -2484,6 +2477,8 @@ Local<Context> NewContext(Isolate* isolate, { // Run lib/internal/per_context.js Context::Scope context_scope(context); + + // TODO(joyeecheung): use NativeModule::Compile Local<String> per_context = NodePerContextSource(isolate); ScriptCompiler::Source per_context_src(per_context, nullptr); Local<Script> s = ScriptCompiler::Compile( diff --git a/src/node_code_cache.h b/src/node_code_cache.h index db80122861..8054279d55 100644 --- a/src/node_code_cache.h +++ b/src/node_code_cache.h @@ -7,6 +7,8 @@ namespace node { +extern const bool native_module_has_code_cache; + void DefineCodeCache(Environment* env, v8::Local<v8::Object> target); void DefineCodeCacheHash(Environment* env, v8::Local<v8::Object> target); diff --git a/src/node_code_cache_stub.cc b/src/node_code_cache_stub.cc index 35780e13f0..2fb86c5bf7 100644 --- a/src/node_code_cache_stub.cc +++ b/src/node_code_cache_stub.cc @@ -5,6 +5,9 @@ // The stub here is used when configure is run without `--code-cache-path` namespace node { + +const bool native_module_has_code_cache = false; + void DefineCodeCache(Environment* env, v8::Local<v8::Object> target) { // When we do not produce code cache for builtin modules, // `internalBinding('code_cache')` returns an empty object diff --git a/src/node_internals.h b/src/node_internals.h index b026a96843..b6cd628086 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -118,6 +118,7 @@ struct sockaddr; V(js_stream) \ V(messaging) \ V(module_wrap) \ + V(native_module) \ V(options) \ V(os) \ V(performance) \ diff --git a/src/node_native_module.cc b/src/node_native_module.cc new file mode 100644 index 0000000000..ea7fe9189a --- /dev/null +++ b/src/node_native_module.cc @@ -0,0 +1,326 @@ +#include "node_native_module.h" +#include "node_code_cache.h" +#include "node_errors.h" +#include "node_javascript.h" + +namespace node { +namespace native_module { + +using v8::Array; +using v8::ArrayBuffer; +using v8::Context; +using v8::EscapableHandleScope; +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::HandleScope; +using v8::Integer; +using v8::IntegrityLevel; +using v8::Isolate; +using v8::Local; +using v8::Maybe; +using v8::MaybeLocal; +using v8::Object; +using v8::Script; +using v8::ScriptCompiler; +using v8::ScriptOrigin; +using v8::Set; +using v8::String; +using v8::TryCatch; +using v8::Uint8Array; +using v8::Value; + +void NativeModule::GetNatives(Environment* env, Local<Object> exports) { + DefineJavaScript(env, exports); +} + +void NativeModule::LoadBindings(Environment* env) { + // TODO(joyeecheung): put the static values into a + // std::map<std::string, const uint8_t*> instead of a v8::Object, + // because here they are only looked up from the C++ side + // (except in process.binding('natives') which we don't use) + // so there is little value to put them in a v8::Object upfront. + // Moreover, a std::map lookup should be faster than a lookup on + // an V8 Object in dictionary mode. + Isolate* isolate = env->isolate(); + Local<Context> context = env->context(); + Local<Value> null = Null(isolate); + + Local<Object> native_modules_source = Object::New(isolate); + CHECK(native_modules_source->SetPrototype(context, null).FromJust()); + DefineJavaScript(env, native_modules_source); + native_modules_source->SetIntegrityLevel(context, IntegrityLevel::kFrozen) + .FromJust(); + env->set_native_modules_source(native_modules_source); + + Local<Object> native_modules_source_hash = Object::New(isolate); + CHECK(native_modules_source_hash->SetPrototype(context, null).FromJust()); + DefineJavaScriptHash(env, native_modules_source_hash); + native_modules_source_hash + ->SetIntegrityLevel(context, IntegrityLevel::kFrozen) + .FromJust(); + env->set_native_modules_source_hash(native_modules_source_hash); + + Local<Object> native_modules_code_cache = Object::New(isolate); + CHECK(native_modules_code_cache->SetPrototype(context, null).FromJust()); + DefineCodeCache(env, native_modules_code_cache); + native_modules_code_cache->SetIntegrityLevel(context, IntegrityLevel::kFrozen) + .FromJust(); + env->set_native_modules_code_cache(native_modules_code_cache); + + Local<Object> native_modules_code_cache_hash = Object::New(isolate); + CHECK(native_modules_code_cache_hash->SetPrototype(context, null).FromJust()); + DefineCodeCacheHash(env, native_modules_code_cache_hash); + native_modules_code_cache_hash + ->SetIntegrityLevel(context, IntegrityLevel::kFrozen) + .FromJust(); + env->set_native_modules_code_cache_hash(native_modules_code_cache_hash); + + env->set_native_modules_with_cache(Set::New(isolate)); + env->set_native_modules_without_cache(Set::New(isolate)); +} + +void NativeModule::CompileCodeCache(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + CHECK(args[0]->IsString()); + Local<String> id = args[0].As<String>(); + + Local<Value> result = CompileAsModule(env, id, true); + if (!result.IsEmpty()) { + args.GetReturnValue().Set(result); + } +} + +void NativeModule::CompileFunction(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK(args[0]->IsString()); + Local<String> id = args[0].As<String>(); + + Local<Value> result = CompileAsModule(env, id, false); + if (!result.IsEmpty()) { + args.GetReturnValue().Set(result); + } +} + +Local<Value> NativeModule::CompileAsModule(Environment* env, + Local<String> id, + bool produce_code_cache) { + Local<String> parameters[] = {env->exports_string(), + env->require_string(), + env->module_string(), + env->process_string(), + env->internal_binding_string()}; + + return Compile( + env, id, parameters, arraysize(parameters), produce_code_cache); +} + +// Currently V8 only checks that the length of the source code is the +// same as the code used to generate the hash, so we add an additional +// check here: +// 1. During compile time, when generating node_javascript.cc and +// node_code_cache.cc, we compute and include the hash of the +// JavaScript source in both. +// 2. At runtime, we check that the hash of the code being compiled +// and the hash of the code used to generate the cache +// (without the parameters) is the same. +// This is based on the assumptions: +// 1. `code_cache_hash` must be in sync with `code_cache` +// (both defined in node_code_cache.cc) +// 2. `source_hash` must be in sync with `source` +// (both defined in node_javascript.cc) +// 3. If `source_hash` is in sync with `code_cache_hash`, +// then the source code used to generate `code_cache` +// should be in sync with the source code in `source` +// The only variable left, then, are the parameters passed to the +// CompileFunctionInContext. If the parameters used generate the cache +// is different from the one used to compile modules at run time, then +// there could be false postivies, but that should be rare and should fail +// early in the bootstrap process so it should be easy to detect and fix. + +// Returns nullptr if there is no code cache corresponding to the id +ScriptCompiler::CachedData* GetCachedData(Environment* env, Local<String> id) { + HandleScope scope(env->isolate()); + Local<Context> context = env->context(); + + Local<Value> result = + env->native_modules_code_cache()->Get(context, id).ToLocalChecked(); + // This could be false if the module cannot be cached somehow. + // See lib/internal/bootstrap/cache.js on the modules that cannot be cached + if (result->IsUndefined()) { + return nullptr; + } + + CHECK(result->IsUint8Array()); + Local<Uint8Array> code_cache = result.As<Uint8Array>(); + + result = + env->native_modules_code_cache_hash()->Get(context, id).ToLocalChecked(); + CHECK(result->IsString()); + Local<String> code_cache_hash = result.As<String>(); + + result = + env->native_modules_source_hash()->Get(context, id).ToLocalChecked(); + CHECK(result->IsString()); + Local<String> source_hash = result.As<String>(); + + // It may fail when any of the inputs of the `node_js2c` target in + // node.gyp is modified but the tools/generate_code_cache.js + // is not re run. + // FIXME(joyeecheung): Figure out how to resolve the dependency issue. + // When the code cache was introduced we were at a point where refactoring + // node.gyp may not be worth the effort. + CHECK(code_cache_hash->StrictEquals(source_hash)); + + ArrayBuffer::Contents contents = code_cache->Buffer()->GetContents(); + uint8_t* data = static_cast<uint8_t*>(contents.Data()); + return new ScriptCompiler::CachedData(data + code_cache->ByteOffset(), + code_cache->ByteLength()); +} + +// Returns Local<Function> of the compiled module if produce_code_cache +// is false (we are only compiling the function). +// Otherwise return a Local<Object> containing the cache. +Local<Value> NativeModule::Compile(Environment* env, + Local<String> id, + Local<String> parameters[], + size_t parameters_count, + bool produce_code_cache) { + EscapableHandleScope scope(env->isolate()); + Local<Context> context = env->context(); + Isolate* isolate = env->isolate(); + + Local<Value> result = + env->native_modules_source()->Get(context, id).ToLocalChecked(); + CHECK(result->IsString()); + Local<String> source = result.As<String>(); + + Local<String> filename = + String::Concat(isolate, id, FIXED_ONE_BYTE_STRING(isolate, ".js")); + Local<Integer> line_offset = Integer::New(isolate, 0); + Local<Integer> column_offset = Integer::New(isolate, 0); + ScriptOrigin origin(filename, line_offset, column_offset); + + bool use_cache = false; + ScriptCompiler::CachedData* cached_data = nullptr; + + // 1. We won't even check the existence of the cache if the binary is not + // built with them. + // 2. If we are generating code cache for tools/general_code_cache.js, we + // are not going to use any cache ourselves. + if (native_module_has_code_cache && !produce_code_cache) { + cached_data = GetCachedData(env, id); + if (cached_data != nullptr) { + use_cache = true; + } + } + + ScriptCompiler::Source script_source(source, origin, cached_data); + + ScriptCompiler::CompileOptions options; + if (produce_code_cache) { + options = ScriptCompiler::kEagerCompile; + } else if (use_cache) { + options = ScriptCompiler::kConsumeCodeCache; + } else { + options = ScriptCompiler::kNoCompileOptions; + } + + MaybeLocal<Function> maybe_fun = + ScriptCompiler::CompileFunctionInContext(context, + &script_source, + parameters_count, + parameters, + 0, + nullptr, + options); + + TryCatch try_catch(isolate); + Local<Function> fun; + // This could fail when there are early errors in the native modules, + // e.g. the syntax errors + if (maybe_fun.IsEmpty() || !maybe_fun.ToLocal(&fun)) { + DecorateErrorStack(env, try_catch); + try_catch.ReThrow(); + return scope.Escape(Local<Value>()); + } + + if (use_cache) { + // If the cache is rejected, something must be wrong with the build + // and we should just crash. + CHECK(!script_source.GetCachedData()->rejected); + if (env->native_modules_with_cache()->Add(context, id).IsEmpty()) { + return scope.Escape(Local<Value>()); + } + } else { + if (env->native_modules_without_cache()->Add(context, id).IsEmpty()) { + return scope.Escape(Local<Value>()); + } + } + + if (produce_code_cache) { + std::unique_ptr<ScriptCompiler::CachedData> cached_data( + ScriptCompiler::CreateCodeCacheForFunction(fun)); + CHECK_NE(cached_data, nullptr); + char* data = + reinterpret_cast<char*>(const_cast<uint8_t*>(cached_data->data)); + + // Since we have no API to create a buffer from a new'ed pointer, + // we will need to copy it - but this code path is only run by the + // tooling that generates the code cache to be bundled in the binary + // so it should be fine. + Local<Object> buf = + Buffer::Copy(env, data, cached_data->length).ToLocalChecked(); + return scope.Escape(buf); + } else { + return scope.Escape(fun); + } +} + +void Initialize(Local<Object> target, + Local<Value> unused, + Local<Context> context) { + Environment* env = Environment::GetCurrent(context); + + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "source"), + env->native_modules_source()) + .FromJust(); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "sourceHash"), + env->native_modules_source_hash()) + .FromJust(); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "codeCache"), + env->native_modules_code_cache()) + .FromJust(); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "codeCacheHash"), + env->native_modules_code_cache_hash()) + .FromJust(); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "compiledWithCache"), + env->native_modules_with_cache()) + .FromJust(); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(env->isolate(), "compiledWithoutCache"), + env->native_modules_without_cache()) + .FromJust(); + + env->SetMethod(target, "compileFunction", NativeModule::CompileFunction); + env->SetMethod(target, "compileCodeCache", NativeModule::CompileCodeCache); + // internalBinding('native_module') should be frozen + target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust(); +} + +} // namespace native_module +} // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(native_module, + node::native_module::Initialize) diff --git a/src/node_native_module.h b/src/node_native_module.h new file mode 100644 index 0000000000..c4ffbfb0cd --- /dev/null +++ b/src/node_native_module.h @@ -0,0 +1,41 @@ +#ifndef SRC_NODE_NATIVE_MODULE_H_ +#define SRC_NODE_NATIVE_MODULE_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "node_internals.h" + +namespace node { +namespace native_module { + +// The native (C++) side of the native module compilation. + +class NativeModule { + public: + // For legacy process.binding('natives') which is mutable + static void GetNatives(Environment* env, v8::Local<v8::Object> exports); + // Loads the static JavaScript source code and the cache into Environment + static void LoadBindings(Environment* env); + // Compile code cache for a specific native module + static void CompileCodeCache(const v8::FunctionCallbackInfo<v8::Value>& args); + // Compile a specific native module as a function + static void CompileFunction(const v8::FunctionCallbackInfo<v8::Value>& args); + + private: + static v8::Local<v8::Value> CompileAsModule(Environment* env, + v8::Local<v8::String> id, + bool produce_code_cache); + // TODO(joyeecheung): make this public and reuse it to compile bootstrappers + static v8::Local<v8::Value> Compile(Environment* env, + v8::Local<v8::String> id, + v8::Local<v8::String> parameters[], + size_t parameters_count, + bool produce_code_cache); +}; + +} // namespace native_module +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_NATIVE_MODULE_H_ |