From bac422f9971f722140735c02d6e1ba3a2e3f00b2 Mon Sep 17 00:00:00 2001 From: h7lin Date: Sun, 16 Feb 2020 23:30:23 +0800 Subject: [PATCH] v12.16.0 --- addons/c_addons.md | 5 +- addons/context_aware_addons.md | 14 +- addons/factory_of_wrapped_objects.md | 12 +- addons/passing_wrapped_objects_around.md | 12 +- addons/worker_support.md | 65 ++++++++- addons/wrapping_c_objects.md | 23 +-- ...sert_doesnotmatch_string_regexp_message.md | 35 +++++ .../assert_doesnotthrow_fn_error_message.md | 7 +- .../assert_equal_actual_expected_message.md | 2 +- assert/assert_fail_message.md | 4 +- assert/assert_iferror_value.md | 3 +- assert/assert_match_string_regexp_message.md | 35 +++++ ...rt_notdeepequal_actual_expected_message.md | 10 +- ...deepstrictequal_actual_expected_message.md | 4 +- ...assert_notequal_actual_expected_message.md | 8 +- ..._notstrictequal_actual_expected_message.md | 2 +- assert/assert_ok_value_message.md | 2 +- .../assert_rejects_asyncfn_error_message.md | 2 +- ...ert_strictequal_actual_expected_message.md | 4 +- assert/assert_throws_fn_error_message.md | 24 ++-- assert/comparison_details.md | 6 +- assert/comparison_details_1.md | 2 +- assert/strict_mode.md | 2 +- async_hooks/asyncresource_emitafter.md | 18 --- async_hooks/asyncresource_emitbefore.md | 15 -- async_hooks/asyncresource_type_options.md | 35 ----- .../asyncresource_type_triggerasyncid.md | 29 ---- async_hooks/triggerid.md | 38 ----- buffer/buf_tostring_encoding_start_end.md | 1 + child_process/advanced_serialization.md | 56 ++++++++ ...ld_process_fork_modulepath_args_options.md | 4 + ...hild_process_spawn_command_args_options.md | 4 + child_process/event_message.md | 4 + cli/disallow_code_generation_from_strings.md | 8 ++ cli/es_module_specifier_resolution_mode.md | 13 -- cli/experimental_exports.md | 6 - cli/experimental_loader_module.md | 2 +- cli/experimental_specifier_resolution_mode.md | 13 ++ cli/experimental_wasi_unstable_preview1.md | 6 + cli/is_equivalent_to.md | 80 ----------- cli/node_options_options.md | 9 +- cli/node_repl_external_module_file.md | 7 + ...nspector_will_be_available_on_port_5555.md | 9 -- cli/tls_keylog_file.md | 8 ++ cli/trace_exit.md | 7 + cli/trace_uncaught.md | 11 ++ cli/use_largepages_mode.md | 15 ++ cluster/cluster_settings.md | 4 + console/new_console_options.md | 4 +- crypto/cipher_setaad_buffer_options.md | 2 +- crypto/crypto_createcredentials_details.md | 18 --- ...eatediffiehellman_primelength_generator.md | 3 +- crypto/crypto_sign_algorithm_data_key.md | 4 + ...pto_verify_algorithm_data_key_signature.md | 4 + crypto/hash_copy_options.md | 34 +++++ crypto/openssl_engine_constants.md | 2 +- crypto/sign_sign_privatekey_outputencoding.md | 5 + ...rify_object_signature_signatureencoding.md | 5 + ...age_headers_outgoingmessage_headernames.md | 20 --- deprecations/dep0134_process_tickcallback.md | 105 +------------- deprecations/dep0136_http_finished.md | 131 ++++++++++++++++++ ...address_groupaddress_multicastinterface.md | 14 ++ ...address_groupaddress_multicastinterface.md | 17 +++ dns/dns.md | 82 ++++++----- dns/dnspromises_lookup_hostname_options.md | 4 +- dns/dnspromises_lookupservice_address_port.md | 2 +- dns/dnspromises_resolve4_hostname_options.md | 2 +- dns/dnspromises_resolve6_hostname_options.md | 2 +- dns/dnspromises_resolve_hostname_rrtype.md | 4 +- dns/dnspromises_reverse_ip.md | 2 +- errors/err_invalid_array_length.md | 4 - errors/err_invalid_domain_name.md | 4 - errors/err_missing_module.md | 6 - errors/err_module_resolution_legacy.md | 6 - errors/err_tls_handshake_timeout.md | 2 +- errors/err_tls_invalid_context.md | 7 + errors/err_tls_psk_set_identiy_hint_failed.md | 4 + errors/err_tls_renegotiate.md | 4 - errors/err_tls_sni_from_server.md | 2 +- errors/err_unknown_signal.md | 2 +- errors/err_unsupported_esm_url_scheme.md | 4 + errors/err_vm_module_not_module.md | 2 +- errors/err_vm_module_status.md | 2 +- errors/err_wasi_already_started.md | 4 + errors/err_worker_invalid_exec_argv.md | 2 +- errors/err_worker_out_of_memory.md | 4 + esm/approach_1_use_an_es_module_wrapper.md | 81 +++++++++++ esm/approach_2_isolate_state.md | 103 ++++++++++++++ ...d => code_dynamicinstantiate_code_hook.md} | 11 +- esm/code_getformat_code_hook.md | 38 +++++ esm/code_getsource_code_hook.md | 31 +++++ esm/code_import_code_statements.md | 31 ----- esm/code_package_json_code_code_main_code.md | 36 +++++ esm/code_resolve_code_hook.md | 33 +++++ esm/code_transformsource_code_hook.md | 43 ++++++ ..._with_commonjs_only_versions_of_node_js.md | 40 ------ esm/conditional_exports.md | 49 +++++++ ...zing_esm_specifier_resolution_algorithm.md | 12 +- esm/dual_commonjs_es_module_packages.md | 17 +++ esm/dual_package_hazard.md | 22 +++ esm/examples.md | 4 + ...oader_hooks.md => experimental_loaders.md} | 0 esm/exports_sugar.md | 68 +++++++++ ...ode_import_code_specifiers.md => hooks.md} | 0 esm/https_loader.md | 78 +++++++++++ ...e_expressions.md => import_expressions.md} | 0 ...rt_and_require.md => import_specifiers.md} | 0 esm/import_statements.md | 30 ++++ esm/in_same_folder_as_above_package_json.md | 17 --- ...t_type_code_flag.md => input_type_flag.md} | 0 esm/interop_with_existing_modules.md | 47 ------- esm/json_modules.md | 16 --- esm/loader_hooks.md | 9 -- esm/no_code_node_path_code.md | 4 - esm/no_code_require_cache_code.md | 3 - esm/no_code_require_extensions_code.md | 4 - ...xports_module_exports_filename_dirname.md} | 0 esm/package_entry_points.md | 44 ++---- esm/package_exports.md | 39 ++---- ...de_field.md => package_json_type_field.md} | 12 +- esm/{code_require_code.md => require.md} | 0 esm/resolve_hook.md | 99 ------------- esm/resolver_algorithm.md | 87 ++++++++---- esm/supported.md | 5 - esm/transpiler_loader.md | 88 ++++++++++++ esm/unsupported.md | 5 - ...es_while_avoiding_or_minimizing_hazards.md | 29 ++++ events/capture_rejections_of_promises.md | 52 +++++++ events/class_eventemitter.md | 12 +- ...for_nodejs_rejection_err_eventname_args.md | 35 +++++ events/error_events.md | 11 ++ events/eventemitter_errormonitor.md | 12 ++ events/events_capturerejections.md | 10 ++ events/events_capturerejectionsymbol.md | 10 ++ events/events_on_emitter_eventname.md | 49 +++++++ fs/fs_chmod_path_mode_callback.md | 2 +- fs/fs_chmodsync_path_mode.md | 2 +- fs/fs_close_fd_callback.md | 2 + fs/fs_closesync_fd.md | 3 + fs/fs_fchmod_fd_mode_callback.md | 2 +- fs/fs_fchmodsync_fd_mode.md | 2 +- fs/fs_mkdir_path_options_callback.md | 2 +- fs/fs_mkdirsync_path_options.md | 2 +- fs/fs_open_path_flags_mode_callback.md | 2 +- fs/fs_opendir_path_options_callback.md | 5 + fs/fs_opendirsync_path_options.md | 5 + fs/fs_opensync_path_flags_mode.md | 2 +- fs/fs_rmdir_path_options_callback.md | 14 +- fs/fs_rmdirsync_path_options.md | 10 ++ fs/fs_symlink_target_path_type_callback.md | 2 +- fs/fspromises_chmod_path_mode.md | 2 +- fs/fspromises_mkdir_path_options.md | 2 +- fs/fspromises_open_path_flags_mode.md | 2 +- fs/fspromises_opendir_path_options.md | 5 + fs/fspromises_rmdir_path_options.md | 14 +- ...agent_createconnection_options_callback.md | 4 +- http/agent_keepsocketalive_socket.md | 4 +- http/agent_reusesocket_socket_request.md | 4 +- http/class_http_incomingmessage.md | 4 + http/event_clienterror.md | 4 +- http/event_connect.md | 4 +- http/event_connect_1.md | 4 +- http/event_connection.md | 4 +- http/event_socket.md | 4 +- http/event_upgrade.md | 4 +- http/event_upgrade_1.md | 4 +- http/message_socket.md | 4 +- http/message_url.md | 56 +++----- http/request_connection.md | 2 +- http/request_finished.md | 3 + http/request_reusedsocket.md | 55 ++++++++ http/request_socket.md | 5 +- http/response_connection.md | 2 +- http/response_cork.md | 6 + http/response_finished.md | 3 + http/response_socket.md | 4 +- http/response_uncork.md | 6 + .../collecting_http_2_performance_metrics.md | 1 + http2/event_frameerror_1.md | 5 + http2/event_timeout_1.md | 1 + http2/event_trailers.md | 3 + ...tesecureserver_options_onrequesthandler.md | 15 ++ ...2_createserver_options_onrequesthandler.md | 15 ++ http2/http2session_settings_settings.md | 17 --- http2/response_finished.md | 3 + http2/settings_object.md | 3 +- https/event_keylog.md | 24 ++++ ....md => event_inspector_protocol_method.md} | 0 inspector/inspector_url.md | 15 ++ modules/all_together.md | 35 +++-- n-api/custom_asynchronous_operations.md | 1 + n-api/error_handling.md | 1 + n-api/exceptions.md | 1 + n-api/napi_acquire_threadsafe_function.md | 2 +- n-api/napi_adjust_external_memory.md | 4 +- n-api/napi_call_function.md | 7 +- n-api/napi_call_threadsafe_function.md | 8 +- n-api/napi_create_async_work.md | 18 +-- n-api/napi_create_buffer_copy.md | 4 +- n-api/napi_create_error.md | 8 +- n-api/napi_create_external.md | 8 +- n-api/napi_create_external_arraybuffer.md | 10 +- n-api/napi_create_external_buffer.md | 12 +- n-api/napi_create_function.md | 12 +- n-api/napi_create_function_1.md | 66 --------- n-api/napi_create_promise.md | 4 +- n-api/napi_create_range_error.md | 8 +- n-api/napi_create_reference.md | 4 +- n-api/napi_create_string_latin1.md | 4 +- n-api/napi_create_string_utf16.md | 2 +- n-api/napi_create_string_utf8.md | 4 +- n-api/napi_create_symbol.md | 2 +- n-api/napi_create_threadsafe_function.md | 22 +-- n-api/napi_create_type_error.md | 8 +- n-api/napi_create_typedarray.md | 2 +- n-api/napi_delete_element.md | 2 +- n-api/napi_delete_property.md | 2 +- n-api/napi_detach_arraybuffer.md | 25 ++++ n-api/napi_env.md | 1 + n-api/napi_escape_handle.md | 6 +- n-api/napi_fatal_error.md | 7 +- n-api/napi_get_and_clear_last_exception.md | 2 - n-api/napi_get_array_length.md | 2 +- n-api/napi_get_boolean.md | 2 +- n-api/napi_get_cb_info.md | 14 +- n-api/napi_get_date_value.md | 4 +- n-api/napi_get_instance_data.md | 2 +- n-api/napi_get_property_names.md | 6 +- n-api/napi_get_prototype.md | 4 +- n-api/napi_get_reference_value.md | 2 +- n-api/napi_get_uv_event_loop.md | 2 +- n-api/napi_get_value_bool.md | 2 +- n-api/napi_get_value_double.md | 2 +- n-api/napi_get_value_string_latin1.md | 6 +- n-api/napi_get_value_string_utf16.md | 6 +- n-api/napi_get_value_string_utf8.md | 6 +- n-api/napi_get_value_uint32.md | 2 +- n-api/napi_handle_scope.md | 1 + n-api/napi_instanceof.md | 6 +- n-api/napi_is_buffer.md | 2 +- n-api/napi_is_date.md | 2 +- n-api/napi_is_detached_arraybuffer.md | 24 ++++ n-api/napi_is_error.md | 2 +- n-api/napi_is_exception_pending.md | 2 - n-api/napi_make_callback.md | 7 +- n-api/napi_new_instance.md | 10 +- n-api/napi_open_callback_scope.md | 5 +- n-api/napi_property_descriptor.md | 42 +++--- n-api/napi_release_threadsafe_function.md | 13 +- n-api/napi_run_script.md | 13 ++ n-api/napi_set_instance_data.md | 6 +- n-api/napi_status.md | 2 + n-api/napi_threadsafe_function_call_js.md | 17 +-- n-api/napi_throw_error.md | 3 +- n-api/napi_throw_range_error.md | 3 +- n-api/napi_throw_type_error.md | 3 +- n-api/napi_unref_threadsafe_function.md | 5 + n-api/napi_value.md | 1 + n-api/return_values.md | 1 + n-api/simple_asynchronous_operations.md | 2 +- ...h_javascript_values_abstract_operations.md | 12 -- net/server_listen_handle_backlog_callback.md | 2 +- net/server_listen_options_callback.md | 2 +- net/server_listen_path_backlog_callback.md | 2 +- ...erver_listen_port_host_backlog_callback.md | 2 +- perf_hooks/performance_timing_api.md | 2 +- process/event_message.md | 3 + process/process_umask_mask.md | 2 +- process/signal_events.md | 2 + readline/rl_cursor.md | 13 ++ readline/rl_getcursorpos.md | 12 ++ readline/rl_line.md | 34 +++++ repl/class_replserver.md | 12 +- stream/event_finish.md | 2 +- .../stream_readable_from_iterable_options.md | 2 + stream/writable_cork.md | 10 +- stream/writable_writablecorked.md | 9 ++ tls/alpn_and_sni.md | 8 +- tls/event_session.md | 14 +- tls/pre_shared_keys.md | 33 +++++ tls/tls_checkserveridentity_host_cert.md | 48 ------- tls/tls_connect_options_callback.md | 20 +++ ..._requestcert_rejectunauthorized_options.md | 2 + ...server_options_secureconnectionlistener.md | 24 +++- tls/tlssocket_getcipher.md | 15 +- util/background_colors.md | 18 +++ util/customizing_util_inspect_colors.md | 5 +- util/foreground_colors.md | 18 +++ util/modifiers.md | 21 +++ util/util_debug_string.md | 11 -- util/util_error_strings.md | 11 -- ..._inspect_object_showhidden_depth_colors.md | 7 +- util/util_print_strings.md | 9 -- util/util_puts_strings.md | 63 --------- vm/class_vm_module.md | 102 ++++++++++++++ vm/class_vm_script.md | 4 +- vm/class_vm_sourcetextmodule.md | 94 +------------ vm/class_vm_syntheticmodule.md | 28 ++++ vm/constructor_new_vm_script_code_options.md | 4 +- ...or_new_vm_sourcetextmodule_code_options.md | 22 ++- ...le_exportnames_evaluatecallback_options.md | 19 +++ vm/module_dependencyspecifiers.md | 4 +- vm/module_error.md | 2 +- vm/module_evaluate_options.md | 2 +- vm/module_instantiate.md | 16 --- vm/module_link_linker.md | 7 +- vm/module_linkingstatus.md | 14 -- vm/module_status.md | 2 +- vm/module_url.md | 5 - ...runincontext_contextifiedobject_options.md | 42 ++++++ ...t_runinnewcontext_contextobject_options.md | 45 ++++++ vm/syntheticmodule_setexport_name_value.md | 26 ++++ vm/vm_compilefunction_code_params_options.md | 4 +- vm/vm_createcontext_contextobject_options.md | 49 +++++++ vm/vm_executing_javascript.md | 28 ++-- vm/vm_iscontext_object.md | 8 ++ ...context_code_contextifiedobject_options.md | 55 ++++++++ ...innewcontext_code_contextobject_options.md | 63 +++++++++ vm/vm_runinthiscontext_code_options.md | 4 +- ...at_does_it_mean_to_contextify_an_object.md | 6 +- wasi/class_wasi.md | 10 ++ wasi/new_wasi_options.md | 15 ++ wasi/wasi_start_instance.md | 14 ++ wasi/wasi_wasiimport.md | 13 ++ wasi/webassembly_system_interface_wasi.md | 33 +++++ worker_threads/new_worker_filename_options.md | 19 +++ worker_threads/worker_resourcelimits.md | 15 ++ worker_threads/worker_resourcelimits_1.md | 14 ++ worker_threads/worker_terminate_callback.md | 18 --- zlib/class_zlib_zlibbase.md | 7 +- 330 files changed, 3165 insertions(+), 1644 deletions(-) create mode 100644 assert/assert_doesnotmatch_string_regexp_message.md create mode 100644 assert/assert_match_string_regexp_message.md delete mode 100644 async_hooks/asyncresource_emitafter.md delete mode 100644 async_hooks/asyncresource_emitbefore.md delete mode 100644 async_hooks/asyncresource_type_options.md delete mode 100644 async_hooks/asyncresource_type_triggerasyncid.md delete mode 100644 async_hooks/triggerid.md create mode 100644 child_process/advanced_serialization.md create mode 100644 cli/disallow_code_generation_from_strings.md delete mode 100644 cli/es_module_specifier_resolution_mode.md delete mode 100644 cli/experimental_exports.md create mode 100644 cli/experimental_specifier_resolution_mode.md create mode 100644 cli/experimental_wasi_unstable_preview1.md delete mode 100644 cli/is_equivalent_to.md create mode 100644 cli/node_repl_external_module_file.md delete mode 100644 cli/the_inspector_will_be_available_on_port_5555.md create mode 100644 cli/tls_keylog_file.md create mode 100644 cli/trace_exit.md create mode 100644 cli/trace_uncaught.md create mode 100644 cli/use_largepages_mode.md delete mode 100644 crypto/crypto_createcredentials_details.md create mode 100644 crypto/hash_copy_options.md delete mode 100644 deprecations/dep0066_outgoingmessage_headers_outgoingmessage_headernames.md create mode 100644 deprecations/dep0136_http_finished.md create mode 100644 dgram/socket_addsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md create mode 100644 dgram/socket_dropsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md delete mode 100644 errors/err_invalid_array_length.md delete mode 100644 errors/err_invalid_domain_name.md delete mode 100644 errors/err_missing_module.md delete mode 100644 errors/err_module_resolution_legacy.md create mode 100644 errors/err_tls_invalid_context.md create mode 100644 errors/err_tls_psk_set_identiy_hint_failed.md delete mode 100644 errors/err_tls_renegotiate.md create mode 100644 errors/err_unsupported_esm_url_scheme.md create mode 100644 errors/err_wasi_already_started.md create mode 100644 errors/err_worker_out_of_memory.md create mode 100644 esm/approach_1_use_an_es_module_wrapper.md create mode 100644 esm/approach_2_isolate_state.md rename esm/{dynamic_instantiate_hook.md => code_dynamicinstantiate_code_hook.md} (68%) create mode 100644 esm/code_getformat_code_hook.md create mode 100644 esm/code_getsource_code_hook.md delete mode 100644 esm/code_import_code_statements.md create mode 100644 esm/code_package_json_code_code_main_code.md create mode 100644 esm/code_resolve_code_hook.md create mode 100644 esm/code_transformsource_code_hook.md delete mode 100644 esm/compatibility_with_commonjs_only_versions_of_node_js.md create mode 100644 esm/conditional_exports.md create mode 100644 esm/dual_commonjs_es_module_packages.md create mode 100644 esm/dual_package_hazard.md create mode 100644 esm/examples.md rename esm/{experimental_loader_hooks.md => experimental_loaders.md} (100%) create mode 100644 esm/exports_sugar.md rename esm/{code_import_code_specifiers.md => hooks.md} (100%) create mode 100644 esm/https_loader.md rename esm/{code_import_code_expressions.md => import_expressions.md} (100%) rename esm/{notable_differences_between_import_and_require.md => import_specifiers.md} (100%) create mode 100644 esm/import_statements.md delete mode 100644 esm/in_same_folder_as_above_package_json.md rename esm/{code_input_type_code_flag.md => input_type_flag.md} (100%) delete mode 100644 esm/interop_with_existing_modules.md delete mode 100644 esm/json_modules.md delete mode 100644 esm/loader_hooks.md delete mode 100644 esm/no_code_node_path_code.md delete mode 100644 esm/no_code_require_cache_code.md delete mode 100644 esm/no_code_require_extensions_code.md rename esm/{no_code_require_code_code_exports_code_code_module_exports_code_code_filename_code_code_dirname_code.md => no_require_exports_module_exports_filename_dirname.md} (100%) rename esm/{code_package_json_code_code_type_code_field.md => package_json_type_field.md} (73%) rename esm/{code_require_code.md => require.md} (100%) delete mode 100644 esm/resolve_hook.md delete mode 100644 esm/supported.md create mode 100644 esm/transpiler_loader.md delete mode 100644 esm/unsupported.md create mode 100644 esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md create mode 100644 events/capture_rejections_of_promises.md create mode 100644 events/emitter_symbol_for_nodejs_rejection_err_eventname_args.md create mode 100644 events/eventemitter_errormonitor.md create mode 100644 events/events_capturerejections.md create mode 100644 events/events_capturerejectionsymbol.md create mode 100644 events/events_on_emitter_eventname.md create mode 100644 http/request_reusedsocket.md create mode 100644 http/response_cork.md create mode 100644 http/response_uncork.md delete mode 100644 http2/http2session_settings_settings.md create mode 100644 https/event_keylog.md rename inspector/{event_lt_inspector_protocol_method_gt.md => event_inspector_protocol_method.md} (100%) delete mode 100644 n-api/napi_create_function_1.md create mode 100644 n-api/napi_detach_arraybuffer.md create mode 100644 n-api/napi_is_detached_arraybuffer.md delete mode 100644 n-api/working_with_javascript_values_abstract_operations.md create mode 100644 readline/rl_cursor.md create mode 100644 readline/rl_getcursorpos.md create mode 100644 readline/rl_line.md create mode 100644 stream/writable_writablecorked.md create mode 100644 tls/pre_shared_keys.md delete mode 100644 tls/tls_checkserveridentity_host_cert.md create mode 100644 util/background_colors.md create mode 100644 util/foreground_colors.md create mode 100644 util/modifiers.md delete mode 100644 util/util_debug_string.md delete mode 100644 util/util_error_strings.md delete mode 100644 util/util_print_strings.md delete mode 100644 util/util_puts_strings.md create mode 100644 vm/class_vm_module.md create mode 100644 vm/class_vm_syntheticmodule.md create mode 100644 vm/constructor_new_vm_syntheticmodule_exportnames_evaluatecallback_options.md delete mode 100644 vm/module_instantiate.md delete mode 100644 vm/module_linkingstatus.md delete mode 100644 vm/module_url.md create mode 100644 vm/script_runincontext_contextifiedobject_options.md create mode 100644 vm/script_runinnewcontext_contextobject_options.md create mode 100644 vm/syntheticmodule_setexport_name_value.md create mode 100644 vm/vm_createcontext_contextobject_options.md create mode 100644 vm/vm_iscontext_object.md create mode 100644 vm/vm_runincontext_code_contextifiedobject_options.md create mode 100644 vm/vm_runinnewcontext_code_contextobject_options.md create mode 100644 wasi/class_wasi.md create mode 100644 wasi/new_wasi_options.md create mode 100644 wasi/wasi_start_instance.md create mode 100644 wasi/wasi_wasiimport.md create mode 100644 wasi/webassembly_system_interface_wasi.md create mode 100644 worker_threads/worker_resourcelimits.md create mode 100644 worker_threads/worker_resourcelimits_1.md delete mode 100644 worker_threads/worker_terminate_callback.md diff --git a/addons/c_addons.md b/addons/c_addons.md index 3ddf8d35..e69550b8 100644 --- a/addons/c_addons.md +++ b/addons/c_addons.md @@ -2,8 +2,9 @@ -Node.js 插件是用 C++ 编写的动态链接共享对象,可以使用 [`require()`][require] 函数加载到 Node.js 中,且像普通的 Node.js 模块一样被使用。 -它们主要用于为运行在 Node.js 中的 JavaScript 与 C/C++ 库之间提供接口。 +插件是用 C++ 编写的动态链接共享对象。 +[`require()`][require] 函数可以将插件加载为普通的 Node.js 模块。 +插件提供了 JavaScript 和 C/C++ 库之间的接口。 实现插件有三种选择:N-API、nan、或直接使用内部的 V8、libuv 和 Node.js 库。 除非你需要直接访问 N-API 未公开的函数,否则请使用 N-API。 diff --git a/addons/context_aware_addons.md b/addons/context_aware_addons.md index eb801503..5d0c2eb1 100644 --- a/addons/context_aware_addons.md +++ b/addons/context_aware_addons.md @@ -32,8 +32,8 @@ NODE_MODULE_INITIALIZER(Local exports, 可以通过执行以下步骤来构造上下文感知的插件以避免全局静态数据: -* 定义一个持有每个插件实例数据的类。这样的类应该包含一个 `v8::Persistent` 持有 `exports` 对象的弱引用。与该弱引用关联的回调函数将会破坏该类的实例。 -* 在插件实例化过程中构造这个类的实例,把`v8::Persistent` 挂到 `exports` 对象上去。 +* 定义一个持有每个插件实例数据的类。这样的类应该包含一个 `v8::Global` 持有 `exports` 对象的弱引用。与该弱引用关联的回调函数将会破坏该类的实例。 +* 在插件实例化过程中构造这个类的实例,把`v8::Global` 挂到 `exports` 对象上去。 * 在 `v8::External` 中保存这个类的实例。 * 通过将 `v8::External` 传给 `v8::FunctionTemplate` 构造函数,该函数会创建本地支持的 JavaScript 函数,把 `v8::External` 传递给所有暴露给 JavaScript 的方法。 `v8::FunctionTemplate` 构造函数的第三个参数接受 `v8::External`。 @@ -56,14 +56,6 @@ class AddonData { exports_.SetWeak(this, DeleteMe, WeakCallbackType::kParameter); } - ~AddonData() { - if (!exports_.IsEmpty()) { - // 重新设置引用以避免数据泄露。 - exports_.ClearWeak(); - exports_.Reset(); - } - } - // 每个插件的数据。 int call_count; @@ -74,7 +66,7 @@ class AddonData { } // 导出对象弱句柄。该类的实例将与其若绑定的 exports 对象一起销毁。 - v8::Persistent exports_; + v8::Global exports_; }; static void Method(const v8::FunctionCallbackInfo& info) { diff --git a/addons/factory_of_wrapped_objects.md b/addons/factory_of_wrapped_objects.md index f8dc5b3a..62573945 100644 --- a/addons/factory_of_wrapped_objects.md +++ b/addons/factory_of_wrapped_objects.md @@ -62,7 +62,7 @@ class MyObject : public node::ObjectWrap { static void New(const v8::FunctionCallbackInfo& args); static void PlusOne(const v8::FunctionCallbackInfo& args); - static v8::Persistent constructor; + static v8::Global constructor; double value_; }; @@ -80,20 +80,22 @@ class MyObject : public node::ObjectWrap { namespace demo { +using node::AddEnvironmentCleanupHook; using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::Global; using v8::Isolate; using v8::Local; using v8::NewStringType; using v8::Number; using v8::Object; -using v8::Persistent; using v8::String; using v8::Value; -Persistent MyObject::constructor; +// 注意!这不是线程安全的,此插件不能用于工作线程。 +Global MyObject::constructor; MyObject::MyObject(double value) : value_(value) { } @@ -113,6 +115,10 @@ void MyObject::Init(Isolate* isolate) { Local context = isolate->GetCurrentContext(); constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked()); + + AddEnvironmentCleanupHook(isolate, [](void*) { + constructor.Reset(); + }, nullptr); } void MyObject::New(const FunctionCallbackInfo& args) { diff --git a/addons/passing_wrapped_objects_around.md b/addons/passing_wrapped_objects_around.md index 1c0f6519..d9d8605b 100644 --- a/addons/passing_wrapped_objects_around.md +++ b/addons/passing_wrapped_objects_around.md @@ -71,7 +71,7 @@ class MyObject : public node::ObjectWrap { ~MyObject(); static void New(const v8::FunctionCallbackInfo& args); - static v8::Persistent constructor; + static v8::Global constructor; double value_; }; @@ -89,19 +89,21 @@ class MyObject : public node::ObjectWrap { namespace demo { +using node::AddEnvironmentCleanupHook; using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::Global; using v8::Isolate; using v8::Local; using v8::NewStringType; using v8::Object; -using v8::Persistent; using v8::String; using v8::Value; -Persistent MyObject::constructor; +// 注意!这不是线程安全的,此插件不能用于工作线程。 +Global MyObject::constructor; MyObject::MyObject(double value) : value_(value) { } @@ -118,6 +120,10 @@ void MyObject::Init(Isolate* isolate) { Local context = isolate->GetCurrentContext(); constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked()); + + AddEnvironmentCleanupHook(isolate, [](void*) { + constructor.Reset(); + }, nullptr); } void MyObject::New(const FunctionCallbackInfo& args) { diff --git a/addons/worker_support.md b/addons/worker_support.md index 9ef66371..cb283e02 100644 --- a/addons/worker_support.md +++ b/addons/worker_support.md @@ -1,4 +1,9 @@ +为了从多个 Node.js 环境加载,例如主线程和工作线程,插件还需要: + +* 是一个 N-API 插件,或 +* 如上所述,使用 `NODE_MODULE_INIT()` 声明为上下文感知。 + 为了支持 [`Worker`] 线程,插件需要清理可能分配的任何资源(当存在这样的线程时)。 这可以通过使用 `AddEnvironmentCleanupHook()` 函数来实现: @@ -10,8 +15,62 @@ void AddEnvironmentCleanupHook(v8::Isolate* isolate, 此函数添加了一个钩子,该钩子将在给定的 Node.js 实例关闭之前运行。 如有必要,可以在运行之前使用 `RemoveEnvironmentCleanupHook()` 删除此类挂钩,它们具有相同的签名。 +回调以后进先出的顺序运行。 + +以下的 `addon.cc` 使用 `AddEnvironmentCleanupHook`: + +```cpp +// addon.cc +#include +#include +#include + +using node::AddEnvironmentCleanupHook; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Object; + +// 注意:在实际的应用程序中,请勿依赖静态/全局的数据。 +static char cookie[] = "yum yum"; +static int cleanup_cb1_called = 0; +static int cleanup_cb2_called = 0; + +static void cleanup_cb1(void* arg) { + Isolate* isolate = static_cast(arg); + HandleScope scope(isolate); + Local obj = Object::New(isolate); + assert(!obj.IsEmpty()); // 断言 VM 仍然存在。 + assert(obj->IsObject()); + cleanup_cb1_called++; +} + +static void cleanup_cb2(void* arg) { + assert(arg == static_cast(cookie)); + cleanup_cb2_called++; +} + +static void sanity_check(void*) { + assert(cleanup_cb1_called == 1); + assert(cleanup_cb2_called == 1); +} + +// 将此插件初始化为上下文感知的。 +NODE_MODULE_INIT(/* exports, module, context */) { + Isolate* isolate = context->GetIsolate(); + + AddEnvironmentCleanupHook(isolate, sanity_check, nullptr); + AddEnvironmentCleanupHook(isolate, cleanup_cb2, cookie); + AddEnvironmentCleanupHook(isolate, cleanup_cb1, isolate); +} +``` + +通过运行以下命令在 JavaScript 中进行测试: + +```js +// test.js +require('./build/Release/addon'); +``` + -为了从多个 Node.js 环境加载,例如主线程和工作线程,插件还需要: -- 是一个 N-API 插件,或 -- 如上所述,使用 `NODE_MODULE_INIT()` 声明为上下文感知。 diff --git a/addons/wrapping_c_objects.md b/addons/wrapping_c_objects.md index 223bbd06..5e8f0621 100644 --- a/addons/wrapping_c_objects.md +++ b/addons/wrapping_c_objects.md @@ -42,7 +42,7 @@ class MyObject : public node::ObjectWrap { static void New(const v8::FunctionCallbackInfo& args); static void PlusOne(const v8::FunctionCallbackInfo& args); - static v8::Persistent constructor; + double value_; }; @@ -70,12 +70,10 @@ using v8::Local; using v8::NewStringType; using v8::Number; using v8::Object; -using v8::Persistent; +using v8::ObjectTemplate; using v8::String; using v8::Value; -Persistent MyObject::constructor; - MyObject::MyObject(double value) : value_(value) { } @@ -84,9 +82,15 @@ MyObject::~MyObject() { void MyObject::Init(Local exports) { Isolate* isolate = exports->GetIsolate(); + Local context = isolate->GetCurrentContext(); + + Local addon_data_tpl = ObjectTemplate::New(isolate); + addon_data_tpl->SetInternalFieldCount(1); // MyObject::New() 的一个字段。 + Local addon_data = + addon_data_tpl->NewInstance(context).ToLocalChecked(); // 准备构造函数模版 - Local tpl = FunctionTemplate::New(isolate, New); + Local tpl = FunctionTemplate::New(isolate, New, addon_data); tpl->SetClassName(String::NewFromUtf8( isolate, "MyObject", NewStringType::kNormal).ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); @@ -94,11 +98,11 @@ void MyObject::Init(Local exports) { // 原型 NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne); - Local context = isolate->GetCurrentContext(); - constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked()); + Local constructor = tpl->GetFunction(context).ToLocalChecked(); + addon_data->SetInternalField(0, constructor); exports->Set(context, String::NewFromUtf8( isolate, "MyObject", NewStringType::kNormal).ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()).FromJust(); + constructor).FromJust(); } void MyObject::New(const FunctionCallbackInfo& args) { @@ -116,7 +120,8 @@ void MyObject::New(const FunctionCallbackInfo& args) { // 像普通方法 `MyObject(...)` 一样调用,转为构造调用。 const int argc = 1; Local argv[argc] = { args[0] }; - Local cons = Local::New(isolate, constructor); + Local cons = + args.Data().As()->GetInternalField(0).As(); Local result = cons->NewInstance(context, argc, argv).ToLocalChecked(); args.GetReturnValue().Set(result); diff --git a/assert/assert_doesnotmatch_string_regexp_message.md b/assert/assert_doesnotmatch_string_regexp_message.md new file mode 100644 index 00000000..0f36bfe6 --- /dev/null +++ b/assert/assert_doesnotmatch_string_regexp_message.md @@ -0,0 +1,35 @@ + + +* `string` {string} +* `regexp` {RegExp} +* `message` {string|Error} + +> Stability: 1 - Experimental + +Expects the `string` input not to match the regular expression. + +This feature is currently experimental and the name might change or it might be +completely removed again. + +```js +const assert = require('assert').strict; + +assert.doesNotMatch('I will fail', /fail/); +// AssertionError [ERR_ASSERTION]: The input was expected to not match the ... + +assert.doesNotMatch(123, /pass/); +// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string. + +assert.doesNotMatch('I will pass', /different/); +// OK +``` + +If the values do match, or if the `string` argument is of another type than +`string`, an [`AssertionError`][] is thrown with a `message` property set equal +to the value of the `message` parameter. If the `message` parameter is +undefined, a default error message is assigned. If the `message` parameter is an +instance of an [`Error`][] then it will be thrown instead of the +[`AssertionError`][]. + diff --git a/assert/assert_doesnotthrow_fn_error_message.md b/assert/assert_doesnotthrow_fn_error_message.md index c3df2131..f1c02438 100644 --- a/assert/assert_doesnotthrow_fn_error_message.md +++ b/assert/assert_doesnotthrow_fn_error_message.md @@ -8,6 +8,7 @@ changes: pr-url: https://github.com/nodejs/node/pull/3276 description: The `error` parameter can now be an arrow function. --> + * `fn` {Function} * `error` {RegExp|Function} * `message` {string} @@ -19,7 +20,7 @@ changes: 当调用 `assert.doesNotThrow()` 时,它将立即调用 `fn` 函数。 -如果抛出错误并且它与 `error` 参数指定的类型相同,则抛出 `AssertionError`。 +如果抛出错误并且它与 `error` 参数指定的类型相同,则抛出 [`AssertionError`]。 如果错误的类型不同,或者 `error` 参数未定义,则错误将传播回调用方。 如果指定,则 `error` 可以是 [`Class`]、[`RegExp`] 或验证函数。 @@ -38,7 +39,7 @@ assert.doesNotThrow( ); ``` -以下示例将导致 `AssertionError`,并显示消息 'Got unwanted exception...': +以下示例将导致 [`AssertionError`],并显示消息 'Got unwanted exception...': ```js @@ -50,7 +51,7 @@ assert.doesNotThrow( ); ``` -如果抛出 `AssertionError` 并为 `message` 参数提供了值,则 `message` 的值将附加到 `AssertionError` 消息: +如果抛出 [`AssertionError`] 并为 `message` 参数提供了值,则 `message` 的值将附加到 `AssertionError` 消息: ```js diff --git a/assert/assert_equal_actual_expected_message.md b/assert/assert_equal_actual_expected_message.md index ae0873eb..61b4458f 100644 --- a/assert/assert_equal_actual_expected_message.md +++ b/assert/assert_equal_actual_expected_message.md @@ -31,7 +31,7 @@ assert.equal({ a: { b: 1 } }, { a: { b: 1 } }); // AssertionError: { a: { b: 1 } } == { a: { b: 1 } } ``` -If the values are not equal, an `AssertionError` is thrown with a `message` +If the values are not equal, an [`AssertionError`][] is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` parameter is an instance of an [`Error`][] then it will be thrown instead of the diff --git a/assert/assert_fail_message.md b/assert/assert_fail_message.md index 84e09df1..76ffd717 100644 --- a/assert/assert_fail_message.md +++ b/assert/assert_fail_message.md @@ -3,8 +3,8 @@ added: v0.1.21 --> * `message` {string|Error} **默认值:** `'Failed'`。 -使用提供的错误消息或默认错误消息抛出 `AssertionError`。 -如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`。 +使用提供的错误消息或默认错误消息抛出 [`AssertionError`]。 +如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 [`AssertionError`]。 ```js diff --git a/assert/assert_iferror_value.md b/assert/assert_iferror_value.md index 835c2bf3..51cf2d32 100644 --- a/assert/assert_iferror_value.md +++ b/assert/assert_iferror_value.md @@ -4,12 +4,13 @@ changes: - version: v10.0.0 pr-url: https://github.com/nodejs/node/pull/18247 description: Instead of throwing the original error it is now wrapped into - an `AssertionError` that contains the full stack trace. + an [`AssertionError`][] that contains the full stack trace. - version: v10.0.0 pr-url: https://github.com/nodejs/node/pull/18247 description: Value may now only be `undefined` or `null`. Before all falsy values were handled the same as `null` and did not throw. --> + * `value` {any} 如果 `value` 不为 `undefined` 或 `null`,则抛出 `value`。 diff --git a/assert/assert_match_string_regexp_message.md b/assert/assert_match_string_regexp_message.md new file mode 100644 index 00000000..6f91cf15 --- /dev/null +++ b/assert/assert_match_string_regexp_message.md @@ -0,0 +1,35 @@ + + +* `string` {string} +* `regexp` {RegExp} +* `message` {string|Error} + +> Stability: 1 - Experimental + +Expects the `string` input to match the regular expression. + +This feature is currently experimental and the name might change or it might be +completely removed again. + +```js +const assert = require('assert').strict; + +assert.match('I will fail', /pass/); +// AssertionError [ERR_ASSERTION]: The input did not match the regular ... + +assert.match(123, /pass/); +// AssertionError [ERR_ASSERTION]: The "string" argument must be of type string. + +assert.match('I will pass', /pass/); +// OK +``` + +If the values do not match, or if the `string` argument is of another type than +`string`, an [`AssertionError`][] is thrown with a `message` property set equal +to the value of the `message` parameter. If the `message` parameter is +undefined, a default error message is assigned. If the `message` parameter is an +instance of an [`Error`][] then it will be thrown instead of the +[`AssertionError`][]. + diff --git a/assert/assert_notdeepequal_actual_expected_message.md b/assert/assert_notdeepequal_actual_expected_message.md index 73d01490..50ae36ed 100644 --- a/assert/assert_notdeepequal_actual_expected_message.md +++ b/assert/assert_notdeepequal_actual_expected_message.md @@ -65,9 +65,9 @@ assert.notDeepEqual(obj1, obj4); // OK ``` -If the values are deeply equal, an `AssertionError` is thrown with a `message` -property set equal to the value of the `message` parameter. If the `message` -parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an [`Error`][] then it will be thrown instead of the -`AssertionError`. +If the values are deeply equal, an [`AssertionError`][] is thrown with a +`message` property set equal to the value of the `message` parameter. If the +`message` parameter is undefined, a default error message is assigned. If the +`message` parameter is an instance of an [`Error`][] then it will be thrown +instead of the `AssertionError`. diff --git a/assert/assert_notdeepstrictequal_actual_expected_message.md b/assert/assert_notdeepstrictequal_actual_expected_message.md index e6d2e072..063a4d2d 100644 --- a/assert/assert_notdeepstrictequal_actual_expected_message.md +++ b/assert/assert_notdeepstrictequal_actual_expected_message.md @@ -39,7 +39,7 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); // 通过。 ``` -如果值深度且严格相等,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果值深度且严格相等,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 -如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`。 +如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 [`AssertionError`]。 diff --git a/assert/assert_notequal_actual_expected_message.md b/assert/assert_notequal_actual_expected_message.md index 76ec0977..a970ada0 100644 --- a/assert/assert_notequal_actual_expected_message.md +++ b/assert/assert_notequal_actual_expected_message.md @@ -30,9 +30,9 @@ assert.notEqual(1, '1'); // AssertionError: 1 != '1' ``` -If the values are equal, an `AssertionError` is thrown with a `message` property -set equal to the value of the `message` parameter. If the `message` parameter is -undefined, a default error message is assigned. If the `message` parameter is an -instance of an [`Error`][] then it will be thrown instead of the +If the values are equal, an [`AssertionError`][] is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. If the `message` +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. diff --git a/assert/assert_notstrictequal_actual_expected_message.md b/assert/assert_notstrictequal_actual_expected_message.md index 50c98deb..247dd6e1 100644 --- a/assert/assert_notstrictequal_actual_expected_message.md +++ b/assert/assert_notstrictequal_actual_expected_message.md @@ -26,7 +26,7 @@ assert.notStrictEqual(1, '1'); // 通过。 ``` -如果值严格相等,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果值严格相等,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`。 diff --git a/assert/assert_ok_value_message.md b/assert/assert_ok_value_message.md index da480dd0..b42ce3fa 100644 --- a/assert/assert_ok_value_message.md +++ b/assert/assert_ok_value_message.md @@ -12,7 +12,7 @@ changes: 测试 `value` 是否为真值。 等同于 `assert.equal(!!value, true, message)`。 -如果 `value` 不是真值,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果 `value` 不是真值,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`。 如果没有传入任何参数,则将 `message` 设置为字符串:``'No value argument passed to `assert.ok()`'``。 diff --git a/assert/assert_rejects_asyncfn_error_message.md b/assert/assert_rejects_asyncfn_error_message.md index f70c788e..1433eddd 100644 --- a/assert/assert_rejects_asyncfn_error_message.md +++ b/assert/assert_rejects_asyncfn_error_message.md @@ -16,7 +16,7 @@ added: v10.0.0 如果指定,则 `error` 可以是 [`Class`]、[`RegExp`]、验证函数、将测试每个属性的对象、或者将测试每个属性的错误实例(包括不可枚举的 `message` 和 `name` 属性)。 -如果指定 `message`,则当 `asyncFn` 无法拒绝时 `message` 将是 `AssertionError` 提供的消息。 +如果指定 `message`,则当 `asyncFn` 无法拒绝时 `message` 将是 [`AssertionError`] 提供的消息。 ```js (async () => { diff --git a/assert/assert_strictequal_actual_expected_message.md b/assert/assert_strictequal_actual_expected_message.md index 2c5dd5be..92cc367f 100644 --- a/assert/assert_strictequal_actual_expected_message.md +++ b/assert/assert_strictequal_actual_expected_message.md @@ -40,7 +40,7 @@ assert.strictEqual(1, '1', new TypeError('Inputs are not identical')); // TypeError: Inputs are not identical ``` -如果值不严格相等,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果值不严格相等,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 -如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`。 +如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 [`AssertionError`]。 diff --git a/assert/assert_throws_fn_error_message.md b/assert/assert_throws_fn_error_message.md index 711ce84c..ee5f0864 100644 --- a/assert/assert_throws_fn_error_message.md +++ b/assert/assert_throws_fn_error_message.md @@ -12,6 +12,7 @@ changes: pr-url: https://github.com/nodejs/node/pull/3276 description: The `error` parameter can now be an arrow function. --> + * `fn` {Function} * `error` {RegExp|Function|Object|Error} * `message` {string} @@ -80,10 +81,14 @@ assert.throws( assert.throws( () => { const otherErr = new Error('未找到'); - otherErr.code = 404; + // 将所有可枚举的属性从 `err` 拷贝到 `otherErr`。 + for (const [key, value] of Object.entries(err)) { + otherErr[key] = value; + } throw otherErr; }, - err // 测试 `message`、`name` 和 `code`。 + // 当使用错误作为验证对象时,也会检查错误的 `message` 和 `name` 属性。 + err ); ``` @@ -113,6 +118,9 @@ assert.throws( 自定义的错误验证函数: +该函数必须返回 `true`,以表明已通过所有的内部验证。 +否则它将会失败并带上 [`AssertionError`]。 + ```js assert.throws( () => { @@ -121,10 +129,9 @@ assert.throws( (err) => { assert(err instanceof Error); assert(/value/.test(err)); - // 除了 `true` 之外,不建议从验证函数返回任何内容。 - // 这样做会导致再次抛出捕获的错误。 - // 这通常不是理想的结果。 - // 抛出有关失败的特定验证的错误(如本例所示)。 + // 避免从验证函数返回 `true` 以外的任何东西。 + // 否则,会不清楚验证的哪一部分失败。 + // 应该抛出有关失败的特定验证的错误(如本例所示),并向该错误添加尽可能多的有用的调试信息。 return true; }, '不是期望的错误' @@ -166,10 +173,9 @@ assert.throws(notThrowing, '错误二'); // 它不会抛出错误,因为错误消息匹配。 assert.throws(throwingSecond, /错误二$/); -// 如果错误消息不匹配,则不会捕获函数内的错误。 +// 如果错误消息不匹配,则抛出 AssertionError。 assert.throws(throwingFirst, /错误二$/); -// Error: 错误一 -// at throwingFirst (repl:2:9) +// AssertionError [ERR_ASSERTION] ``` 由于令人困惑的表示法,建议不要使用字符串作为第二个参数。 diff --git a/assert/comparison_details.md b/assert/comparison_details.md index 84f437e5..29e1d8b7 100644 --- a/assert/comparison_details.md +++ b/assert/comparison_details.md @@ -11,7 +11,7 @@ * 可枚举的自身 [`Symbol`] 属性也会比较。 * [`WeakMap`] 和 [`WeakSet`] 的比较不依赖于它们的值。 -以下示例不会抛出 `AssertionError`,因为[抽象的相等性比较][Abstract Equality Comparison](`==`)会将原始类型视为相等。 +以下示例不会抛出 [`AssertionError`],因为[抽象的相等性比较][Abstract Equality Comparison](`==`)会将原始类型视为相等。 ```js // 不会抛出 AssertionError。 @@ -55,7 +55,7 @@ assert.deepEqual(obj1, obj4); // 抛出 AssertionError: { a: { b: 1 } } deepEqual {} ``` -如果值不相等,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果值不相等,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 -如果 `message` 参数是 [`Error`] 的实例,那么它将被抛出而不是 `AssertionError`。 +如果 `message` 参数是 [`Error`] 的实例,那么它将被抛出而不是 [`AssertionError`]。 diff --git a/assert/comparison_details_1.md b/assert/comparison_details_1.md index 9de11025..575939a6 100644 --- a/assert/comparison_details_1.md +++ b/assert/comparison_details_1.md @@ -102,7 +102,7 @@ assert.deepStrictEqual(weakMap1, weakMap3); // } ``` -如果值不相等,则抛出 `AssertionError`,并将 `message` 属性设置为等于 `message` 参数的值。 +如果值不相等,则抛出 [`AssertionError`],并将 `message` 属性设置为等于 `message` 参数的值。 如果未定义 `message` 参数,则会分配默认错误消息。 如果 `message` 参数是 [`Error`] 的实例,那么它将被抛出而不是 `AssertionError`。 diff --git a/assert/strict_mode.md b/assert/strict_mode.md index ab35780a..3f757a63 100644 --- a/assert/strict_mode.md +++ b/assert/strict_mode.md @@ -9,7 +9,7 @@ changes: description: Added strict mode to the assert module. --> -在严格模式中,任何 `assert` 函数都将使用严格函数模式中使用的相等性。 +在严格模式中(不要与 `"use strict"` 混淆),任何 `assert` 函数都将使用严格函数模式中使用的相等性。 例如,[`assert.deepEqual()`] 将与 [`assert.deepStrictEqual()`] 一样效果。 在严格模式中,对象的错误消息会显示差异。 diff --git a/async_hooks/asyncresource_emitafter.md b/async_hooks/asyncresource_emitafter.md deleted file mode 100644 index a51b3260..00000000 --- a/async_hooks/asyncresource_emitafter.md +++ /dev/null @@ -1,18 +0,0 @@ - -> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead. - -Call all `after` callbacks. If nested calls to `emitBefore()` were made, then -make sure the stack is unwound properly. Otherwise an error will be thrown. - -If the user's callback throws an exception, `emitAfter()` will automatically be -called for all `asyncId`s on the stack if the error is handled by a domain or -`'uncaughtException'` handler. - -`before` and `after` calls must be unwound in the same order that they -are called. Otherwise, an unrecoverable exception will occur and the process -will abort. For this reason, the `emitBefore` and `emitAfter` APIs are -considered deprecated. Please use `runInAsyncScope`, as it provides a much safer -alternative. - diff --git a/async_hooks/asyncresource_emitbefore.md b/async_hooks/asyncresource_emitbefore.md deleted file mode 100644 index 6de1a5e7..00000000 --- a/async_hooks/asyncresource_emitbefore.md +++ /dev/null @@ -1,15 +0,0 @@ - -> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead. - -Call all `before` callbacks to notify that a new asynchronous execution context -is being entered. If nested calls to `emitBefore()` are made, the stack of -`asyncId`s will be tracked and properly unwound. - -`before` and `after` calls must be unwound in the same order that they -are called. Otherwise, an unrecoverable exception will occur and the process -will abort. For this reason, the `emitBefore` and `emitAfter` APIs are -considered deprecated. Please use `runInAsyncScope`, as it provides a much safer -alternative. - diff --git a/async_hooks/asyncresource_type_options.md b/async_hooks/asyncresource_type_options.md deleted file mode 100644 index 84b8b51d..00000000 --- a/async_hooks/asyncresource_type_options.md +++ /dev/null @@ -1,35 +0,0 @@ - -* `type` {string} The type of async event. -* `options` {Object} - * `triggerAsyncId` {number} The ID of the execution context that created this - async event. **Default:** `executionAsyncId()` - * `requireManualDestroy` {boolean} Disables automatic `emitDestroy` when the - object is garbage collected. This usually does not need to be set (even if - `emitDestroy` is called manually), unless the resource's asyncId is retrieved - and the sensitive API's `emitDestroy` is called with it. - **Default:** `false` - -Example usage: - -```js -class DBQuery extends AsyncResource { - constructor(db) { - super('DBQuery'); - this.db = db; - } - - getInfo(query, callback) { - this.db.get(query, (err, data) => { - this.emitBefore(); - callback(err, data); - this.emitAfter(); - }); - } - - close() { - this.db = null; - this.emitDestroy(); - } -} -``` - diff --git a/async_hooks/asyncresource_type_triggerasyncid.md b/async_hooks/asyncresource_type_triggerasyncid.md deleted file mode 100644 index 6846137d..00000000 --- a/async_hooks/asyncresource_type_triggerasyncid.md +++ /dev/null @@ -1,29 +0,0 @@ - -* `type` {string} The type of async event. -* `triggerAsyncId` {number} The ID of the execution context that created this - async event. - -Example usage: - -```js -class DBQuery extends AsyncResource { - constructor(db) { - super('DBQuery'); - this.db = db; - } - - getInfo(query, callback) { - this.db.get(query, (err, data) => { - this.emitBefore(); - callback(err, data); - this.emitAfter(); - }); - } - - close() { - this.db = null; - this.emitDestroy(); - } -} -``` - diff --git a/async_hooks/triggerid.md b/async_hooks/triggerid.md deleted file mode 100644 index 213924ed..00000000 --- a/async_hooks/triggerid.md +++ /dev/null @@ -1,38 +0,0 @@ - -`triggerAsyncId` is the `asyncId` of the resource that caused (or "triggered") -the new resource to initialize and that caused `init` to call. This is different -from `async_hooks.executionAsyncId()` that only shows *when* a resource was -created, while `triggerAsyncId` shows *why* a resource was created. - - -The following is a simple demonstration of `triggerAsyncId`: - -```js -async_hooks.createHook({ - init(asyncId, type, triggerAsyncId) { - const eid = async_hooks.executionAsyncId(); - fs.writeSync( - 1, `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`); - } -}).enable(); - -require('net').createServer((conn) => {}).listen(8080); -``` - -Output when hitting the server with `nc localhost 8080`: - -```console -TCPSERVERWRAP(2): trigger: 1 execution: 1 -TCPWRAP(4): trigger: 2 execution: 0 -``` - -The `TCPSERVERWRAP` is the server which receives the connections. - -The `TCPWRAP` is the new connection from the client. When a new -connection is made the `TCPWrap` instance is immediately constructed. This -happens outside of any JavaScript stack (side note: a `executionAsyncId()` of `0` -means it's being executed from C++, with no JavaScript stack above it). -With only that information, it would be impossible to link resources together in -terms of what caused them to be created, so `triggerAsyncId` is given the task of -propagating what resource is responsible for the new resource's existence. - diff --git a/buffer/buf_tostring_encoding_start_end.md b/buffer/buf_tostring_encoding_start_end.md index 5a552190..f7865c42 100644 --- a/buffer/buf_tostring_encoding_start_end.md +++ b/buffer/buf_tostring_encoding_start_end.md @@ -9,6 +9,7 @@ added: v0.1.90 根据 `encoding` 指定的字符编码将 `buf` 解码成字符串。 传入 `start` 和 `end` 可以只解码 `buf` 的子集。 +如果输入中的字节序列在给定的 `encoding` 中无效,则将其替换为替换字符 `U+FFFD`。 字符串的最大长度(以 UTF-16 为单位)可查看 [`buffer.constants.MAX_STRING_LENGTH`]。 diff --git a/child_process/advanced_serialization.md b/child_process/advanced_serialization.md new file mode 100644 index 00000000..13e2091d --- /dev/null +++ b/child_process/advanced_serialization.md @@ -0,0 +1,56 @@ + + +Child processes support a serialization mechanism for IPC that is based on the +[serialization API of the `v8` module][v8.serdes], based on the +[HTML structured clone algorithm][]. This is generally more powerful and +supports more built-in JavaScript object types, such as `BigInt`, `Map` +and `Set`, `ArrayBuffer` and `TypedArray`, `Buffer`, `Error`, `RegExp` etc. + +However, this format is not a full superset of JSON, and e.g. properties set on +objects of such built-in types will not be passed on through the serialization +step. Additionally, performance may not be equivalent to that of JSON, depending +on the structure of the passed data. +Therefore, this feature requires opting in by setting the +`serialization` option to `'advanced'` when calling [`child_process.spawn()`][] +or [`child_process.fork()`][]. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/child_process/child_process_fork_modulepath_args_options.md b/child_process/child_process_fork_modulepath_args_options.md index 522f45cf..40cbcf1a 100644 --- a/child_process/child_process_fork_modulepath_args_options.md +++ b/child_process/child_process_fork_modulepath_args_options.md @@ -1,6 +1,9 @@ + +Make built-in language features like `eval` and `new Function` that generate +code from strings throw an exception instead. This does not affect the Node.js +`vm` module. + diff --git a/cli/es_module_specifier_resolution_mode.md b/cli/es_module_specifier_resolution_mode.md deleted file mode 100644 index 46467078..00000000 --- a/cli/es_module_specifier_resolution_mode.md +++ /dev/null @@ -1,13 +0,0 @@ - - -To be used in conjunction with `--experimental-modules`. Sets the resolution -algorithm for resolving specifiers. Valid options are `explicit` and `node`. - -The default is `explicit`, which requires providing the full path to a -module. The `node` mode will enable support for optional file extensions and -the ability to import a directory that has an index file. - -Please see [customizing esm specifier resolution][] for example usage. - diff --git a/cli/experimental_exports.md b/cli/experimental_exports.md deleted file mode 100644 index ac28d807..00000000 --- a/cli/experimental_exports.md +++ /dev/null @@ -1,6 +0,0 @@ - - -Enable experimental resolution using the `exports` field in `package.json`. - diff --git a/cli/experimental_loader_module.md b/cli/experimental_loader_module.md index 9ff0800c..0a0318b5 100644 --- a/cli/experimental_loader_module.md +++ b/cli/experimental_loader_module.md @@ -2,6 +2,6 @@ added: v9.0.0 --> -Specify the `module` of a custom [experimental ECMAScript Module][] loader. +Specify the `module` of a custom [experimental ECMAScript Module loader][]. `module` may be either a path to a file, or an ECMAScript Module name. diff --git a/cli/experimental_specifier_resolution_mode.md b/cli/experimental_specifier_resolution_mode.md new file mode 100644 index 00000000..2a4b4741 --- /dev/null +++ b/cli/experimental_specifier_resolution_mode.md @@ -0,0 +1,13 @@ + + +Sets the resolution algorithm for resolving ES module specifiers. Valid options +are `explicit` and `node`. + +The default is `explicit`, which requires providing the full path to a +module. The `node` mode will enable support for optional file extensions and +the ability to import a directory that has an index file. + +Please see [customizing ESM specifier resolution][] for example usage. + diff --git a/cli/experimental_wasi_unstable_preview1.md b/cli/experimental_wasi_unstable_preview1.md new file mode 100644 index 00000000..9f45b6e2 --- /dev/null +++ b/cli/experimental_wasi_unstable_preview1.md @@ -0,0 +1,6 @@ + + +Enable experimental WebAssembly System Interface (WASI) support. + diff --git a/cli/is_equivalent_to.md b/cli/is_equivalent_to.md deleted file mode 100644 index 05a0347c..00000000 --- a/cli/is_equivalent_to.md +++ /dev/null @@ -1,80 +0,0 @@ -node --require "./a.js" --require "./b.js" -``` - -Node.js options that are allowed are: - -- `--enable-fips` -- `--es-module-specifier-resolution` -- `--experimental-exports` -- `--experimental-modules` -- `--experimental-policy` -- `--experimental-repl-await` -- `--experimental-report` -- `--experimental-vm-modules` -- `--experimental-wasm-modules` -- `--force-fips` -- `--frozen-intrinsics` -- `--heapsnapshot-signal` -- `--http-parser` -- `--http-server-default-timeout` -- `--icu-data-dir` -- `--input-type` -- `--inspect-brk` -- `--inspect-port`, `--debug-port` -- `--inspect-publish-uid` -- `--inspect` -- `--loader` -- `--max-http-header-size` -- `--napi-modules` -- `--no-deprecation` -- `--no-force-async-hooks-checks` -- `--no-warnings` -- `--openssl-config` -- `--pending-deprecation` -- `--policy-integrity` -- `--preserve-symlinks-main` -- `--preserve-symlinks` -- `--prof-process` -- `--redirect-warnings` -- `--report-directory` -- `--report-filename` -- `--report-on-fatalerror` -- `--report-on-signal` -- `--report-signal` -- `--report-uncaught-exception` -- `--require`, `-r` -- `--throw-deprecation` -- `--title` -- `--tls-cipher-list` -- `--tls-max-v1.2` -- `--tls-max-v1.3` -- `--tls-min-v1.0` -- `--tls-min-v1.1` -- `--tls-min-v1.2` -- `--tls-min-v1.3` -- `--trace-deprecation` -- `--trace-event-categories` -- `--trace-event-file-pattern` -- `--trace-events-enabled` -- `--trace-sync-io` -- `--trace-tls` -- `--trace-warnings` -- `--track-heap-objects` -- `--unhandled-rejections` -- `--use-bundled-ca` -- `--use-openssl-ca` -- `--v8-pool-size` -- `--zero-fill-buffers` - - -V8 options that are allowed are: - -- `--abort-on-uncaught-exception` -- `--max-old-space-size` -- `--perf-basic-prof-only-functions` -- `--perf-basic-prof` -- `--perf-prof-unwinding-info` -- `--perf-prof` -- `--stack-trace-limit` - - diff --git a/cli/node_options_options.md b/cli/node_options_options.md index 87199277..ebfe3721 100644 --- a/cli/node_options_options.md +++ b/cli/node_options_options.md @@ -37,15 +37,15 @@ Node.js options that are allowed are: * `--enable-fips` * `--enable-source-maps` -* `--es-module-specifier-resolution` -* `--experimental-exports` * `--experimental-json-modules` * `--experimental-loader` * `--experimental-modules` * `--experimental-policy` * `--experimental-repl-await` * `--experimental-report` +* `--experimental-specifier-resolution` * `--experimental-vm-modules` +* `--experimental-wasi-unstable-preview1` * `--experimental-wasm-modules` * `--force-context-aware` * `--force-fips` @@ -82,6 +82,7 @@ Node.js options that are allowed are: * `--throw-deprecation` * `--title` * `--tls-cipher-list` +* `--tls-keylog` * `--tls-max-v1.2` * `--tls-max-v1.3` * `--tls-min-v1.0` @@ -92,12 +93,15 @@ Node.js options that are allowed are: * `--trace-event-categories` * `--trace-event-file-pattern` * `--trace-events-enabled` +* `--trace-exit` * `--trace-sync-io` * `--trace-tls` +* `--trace-uncaught` * `--trace-warnings` * `--track-heap-objects` * `--unhandled-rejections` * `--use-bundled-ca` +* `--use-largepages` * `--use-openssl-ca` * `--v8-pool-size` * `--zero-fill-buffers` @@ -106,6 +110,7 @@ Node.js options that are allowed are: V8 options that are allowed are: * `--abort-on-uncaught-exception` +* `--disallow-code-generation-from-strings` * `--interpreted-frames-native-stack` * `--max-old-space-size` * `--perf-basic-prof-only-functions` diff --git a/cli/node_repl_external_module_file.md b/cli/node_repl_external_module_file.md new file mode 100644 index 00000000..1cff0ce5 --- /dev/null +++ b/cli/node_repl_external_module_file.md @@ -0,0 +1,7 @@ + + +Path to a Node.js module which will be loaded in place of the built-in REPL. +Overriding this value to an empty string (`''`) will use the built-in REPL. + diff --git a/cli/the_inspector_will_be_available_on_port_5555.md b/cli/the_inspector_will_be_available_on_port_5555.md deleted file mode 100644 index 2013f0f1..00000000 --- a/cli/the_inspector_will_be_available_on_port_5555.md +++ /dev/null @@ -1,9 +0,0 @@ -NODE_OPTIONS='--inspect=localhost:4444' node --inspect=localhost:5555 -``` - -A flag that can be passed multiple times will be treated as if its -`NODE_OPTIONS` instances were passed first, and then its command line -instances afterwards: - -```bash -NODE_OPTIONS='--require "./a.js"' node --require "./b.js" diff --git a/cli/tls_keylog_file.md b/cli/tls_keylog_file.md new file mode 100644 index 00000000..bbcacce9 --- /dev/null +++ b/cli/tls_keylog_file.md @@ -0,0 +1,8 @@ + + +Log TLS key material to a file. The key material is in NSS `SSLKEYLOGFILE` +format and can be used by software (such as Wireshark) to decrypt the TLS +traffic. + diff --git a/cli/trace_exit.md b/cli/trace_exit.md new file mode 100644 index 00000000..4ed562cb --- /dev/null +++ b/cli/trace_exit.md @@ -0,0 +1,7 @@ + + +Prints a stack trace whenever an environment is exited proactively, +i.e. invoking `process.exit()`. + diff --git a/cli/trace_uncaught.md b/cli/trace_uncaught.md new file mode 100644 index 00000000..70cf2bd3 --- /dev/null +++ b/cli/trace_uncaught.md @@ -0,0 +1,11 @@ + + +Print stack traces for uncaught exceptions; usually, the stack trace associated +with the creation of an `Error` is printed, whereas this makes Node.js also +print the stack trace associated with throwing the value (which does not need +to be an `Error` instance). + +Enabling this option may affect garbage collection behavior negatively. + diff --git a/cli/use_largepages_mode.md b/cli/use_largepages_mode.md new file mode 100644 index 00000000..0fb7ae91 --- /dev/null +++ b/cli/use_largepages_mode.md @@ -0,0 +1,15 @@ + + +Re-map the Node.js static code to large memory pages at startup. If supported on +the target system, this will cause the Node.js static code to be moved onto 2 +MiB pages instead of 4 KiB pages. + +The following values are valid for `mode`: +* `off`: No mapping will be attempted. This is the default. +* `on`: If supported by the OS, mapping will be attempted. Failure to map will + be ignored and a message will be printed to standard error. +* `silent`: If supported by the OS, mapping will be attempted. Failure to map + will be ignored and will not be reported. + diff --git a/cluster/cluster_settings.md b/cluster/cluster_settings.md index fe2eb20c..af754bb1 100644 --- a/cluster/cluster_settings.md +++ b/cluster/cluster_settings.md @@ -1,6 +1,9 @@ -* `buffer` {Buffer} +* `buffer` {Buffer | TypedArray | DataView} * `options` {Object} [`stream.transform` options][] * `plaintextLength` {number} * Returns: {Cipher} for method chaining. diff --git a/crypto/crypto_createcredentials_details.md b/crypto/crypto_createcredentials_details.md deleted file mode 100644 index 8132c5b8..00000000 --- a/crypto/crypto_createcredentials_details.md +++ /dev/null @@ -1,18 +0,0 @@ - - -> Stability: 0 - Deprecated: Use [`tls.createSecureContext()`][] instead. - -- `details` {Object} Identical to [`tls.createSecureContext()`][]. -- Returns: {tls.SecureContext} - -The `crypto.createCredentials()` method is a deprecated function for creating -and returning a `tls.SecureContext`. It should not be used. Replace it with -[`tls.createSecureContext()`][] which has the exact same arguments and return -value. - -Returns a `tls.SecureContext`, as-if [`tls.createSecureContext()`][] had been -called. - diff --git a/crypto/crypto_creatediffiehellman_primelength_generator.md b/crypto/crypto_creatediffiehellman_primelength_generator.md index a2c898ab..13bf5449 100644 --- a/crypto/crypto_creatediffiehellman_primelength_generator.md +++ b/crypto/crypto_creatediffiehellman_primelength_generator.md @@ -3,8 +3,7 @@ added: v0.5.0 --> * `primeLength` {number} -* `generator` {number | string | Buffer | TypedArray | DataView} **Default:** - `2` +* `generator` {number} **Default:** `2` * Returns: {DiffieHellman} Creates a `DiffieHellman` key exchange object and generates a prime of diff --git a/crypto/crypto_sign_algorithm_data_key.md b/crypto/crypto_sign_algorithm_data_key.md index 9a109658..8d1d1a4d 100644 --- a/crypto/crypto_sign_algorithm_data_key.md +++ b/crypto/crypto_sign_algorithm_data_key.md @@ -15,6 +15,10 @@ If `key` is not a [`KeyObject`][], this function behaves as if `key` had been passed to [`crypto.createPrivateKey()`][]. If it is an object, the following additional properties can be passed: +* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the + format of the generated signature. It can be one of the following: + * `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. + * `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. * `padding` {integer} Optional padding value for RSA, one of the following: * `crypto.constants.RSA_PKCS1_PADDING` (default) * `crypto.constants.RSA_PKCS1_PSS_PADDING` diff --git a/crypto/crypto_verify_algorithm_data_key_signature.md b/crypto/crypto_verify_algorithm_data_key_signature.md index b2c05eca..e5173da1 100644 --- a/crypto/crypto_verify_algorithm_data_key_signature.md +++ b/crypto/crypto_verify_algorithm_data_key_signature.md @@ -16,6 +16,10 @@ If `key` is not a [`KeyObject`][], this function behaves as if `key` had been passed to [`crypto.createPublicKey()`][]. If it is an object, the following additional properties can be passed: +* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the + format of the generated signature. It can be one of the following: + * `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. + * `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. * `padding` {integer} Optional padding value for RSA, one of the following: * `crypto.constants.RSA_PKCS1_PADDING` (default) * `crypto.constants.RSA_PKCS1_PSS_PADDING` diff --git a/crypto/hash_copy_options.md b/crypto/hash_copy_options.md new file mode 100644 index 00000000..6b2c9475 --- /dev/null +++ b/crypto/hash_copy_options.md @@ -0,0 +1,34 @@ + + +* `options` {Object} [`stream.transform` options][] +* Returns: {Hash} + +Creates a new `Hash` object that contains a deep copy of the internal state +of the current `Hash` object. + +The optional `options` argument controls stream behavior. For XOF hash +functions such as `'shake256'`, the `outputLength` option can be used to +specify the desired output length in bytes. + +An error is thrown when an attempt is made to copy the `Hash` object after +its [`hash.digest()`][] method has been called. + +```js +// Calculate a rolling hash. +const crypto = require('crypto'); +const hash = crypto.createHash('sha256'); + +hash.update('one'); +console.log(hash.copy().digest('hex')); + +hash.update('two'); +console.log(hash.copy().digest('hex')); + +hash.update('three'); +console.log(hash.copy().digest('hex')); + +// Etc. +``` + diff --git a/crypto/openssl_engine_constants.md b/crypto/openssl_engine_constants.md index 94fa974e..86e26fc8 100644 --- a/crypto/openssl_engine_constants.md +++ b/crypto/openssl_engine_constants.md @@ -34,7 +34,7 @@ ENGINE_METHOD_PKEY_METHS - Limit engine usage to PKEY_METHS + Limit engine usage to PKEY_METHDS ENGINE_METHOD_PKEY_ASN1_METHS diff --git a/crypto/sign_sign_privatekey_outputencoding.md b/crypto/sign_sign_privatekey_outputencoding.md index 2bb44e24..923eb781 100644 --- a/crypto/sign_sign_privatekey_outputencoding.md +++ b/crypto/sign_sign_privatekey_outputencoding.md @@ -13,6 +13,7 @@ changes: --> * `privateKey` {Object | string | Buffer | KeyObject} + * `dsaEncoding` {string} * `padding` {integer} * `saltLength` {integer} * `outputEncoding` {string} The [encoding][] of the return value. @@ -25,6 +26,10 @@ If `privateKey` is not a [`KeyObject`][], this function behaves as if `privateKey` had been passed to [`crypto.createPrivateKey()`][]. If it is an object, the following additional properties can be passed: +* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the + format of the generated signature. It can be one of the following: + * `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. + * `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. * `padding` {integer} Optional padding value for RSA, one of the following: * `crypto.constants.RSA_PKCS1_PADDING` (default) * `crypto.constants.RSA_PKCS1_PSS_PADDING` diff --git a/crypto/verify_verify_object_signature_signatureencoding.md b/crypto/verify_verify_object_signature_signatureencoding.md index 1ca1f659..97985e27 100644 --- a/crypto/verify_verify_object_signature_signatureencoding.md +++ b/crypto/verify_verify_object_signature_signatureencoding.md @@ -13,6 +13,7 @@ changes: --> * `object` {Object | string | Buffer | KeyObject} + * `dsaEncoding` {string} * `padding` {integer} * `saltLength` {integer} * `signature` {string | Buffer | TypedArray | DataView} @@ -26,6 +27,10 @@ If `object` is not a [`KeyObject`][], this function behaves as if `object` had been passed to [`crypto.createPublicKey()`][]. If it is an object, the following additional properties can be passed: +* `dsaEncoding` {string} For DSA and ECDSA, this option specifies the + format of the generated signature. It can be one of the following: + * `'der'` (default): DER-encoded ASN.1 signature structure encoding `(r, s)`. + * `'ieee-p1363'`: Signature format `r || s` as proposed in IEEE-P1363. * `padding` {integer} Optional padding value for RSA, one of the following: * `crypto.constants.RSA_PKCS1_PADDING` (default) * `crypto.constants.RSA_PKCS1_PSS_PADDING` diff --git a/deprecations/dep0066_outgoingmessage_headers_outgoingmessage_headernames.md b/deprecations/dep0066_outgoingmessage_headers_outgoingmessage_headernames.md deleted file mode 100644 index 8a304778..00000000 --- a/deprecations/dep0066_outgoingmessage_headers_outgoingmessage_headernames.md +++ /dev/null @@ -1,20 +0,0 @@ - - -Type: Documentation-only - -The `http` module `outgoingMessage._headers` and `outgoingMessage._headerNames` -properties are deprecated. Use one of the public methods -(e.g. `outgoingMessage.getHeader()`, `outgoingMessage.getHeaders()`, -`outgoingMessage.getHeaderNames()`, `outgoingMessage.hasHeader()`, -`outgoingMessage.removeHeader()`, `outgoingMessage.setHeader()`) for working -with outgoing headers. - -The `outgoingMessage._headers` and `outgoingMessage._headerNames` properties -were never documented as officially supported properties. - - diff --git a/deprecations/dep0134_process_tickcallback.md b/deprecations/dep0134_process_tickcallback.md index b8692d3c..2a453bf1 100644 --- a/deprecations/dep0134_process_tickcallback.md +++ b/deprecations/dep0134_process_tickcallback.md @@ -9,107 +9,4 @@ Type: Documentation-only (supports [`--pending-deprecation`][]) The `process._tickCallback` property was never documented as an officially supported API. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/deprecations/dep0136_http_finished.md b/deprecations/dep0136_http_finished.md new file mode 100644 index 00000000..d7c45848 --- /dev/null +++ b/deprecations/dep0136_http_finished.md @@ -0,0 +1,131 @@ + + +Type: Documentation-only + +[`response.finished`][] indicates whether [`response.end()`][] has been +called, not whether `'finish'` has been emitted and the underlying data +is flushed. + +Use [`response.writableFinished`][] or [`response.writableEnded`][] +accordingly instead to avoid the ambigiuty. + +To maintain existing behaviour `response.finished` should be replaced with +`response.writableEnded`. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dgram/socket_addsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md b/dgram/socket_addsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md new file mode 100644 index 00000000..e00efafe --- /dev/null +++ b/dgram/socket_addsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md @@ -0,0 +1,14 @@ + +* `sourceAddress` {string} +* `groupAddress` {string} +* `multicastInterface` {string} + +Tells the kernel to join a source-specific multicast channel at the given +`sourceAddress` and `groupAddress`, using the `multicastInterface` with the +`IP_ADD_SOURCE_MEMBERSHIP` socket option. If the `multicastInterface` argument +is not specified, the operating system will choose one interface and will add +membership to it. To add membership to every available interface, call +`socket.addSourceSpecificMembership()` multiple times, once per interface. + diff --git a/dgram/socket_dropsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md b/dgram/socket_dropsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md new file mode 100644 index 00000000..420066b1 --- /dev/null +++ b/dgram/socket_dropsourcespecificmembership_sourceaddress_groupaddress_multicastinterface.md @@ -0,0 +1,17 @@ + + +* `sourceAddress` {string} +* `groupAddress` {string} +* `multicastInterface` {string} + +Instructs the kernel to leave a source-specific multicast channel at the given +`sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` +socket option. This method is automatically called by the kernel when the +socket is closed or the process terminates, so most apps will never have +reason to call this. + +If `multicastInterface` is not specified, the operating system will attempt to +drop membership on all valid interfaces. + diff --git a/dns/dns.md b/dns/dns.md index c5f4d428..a7fdfde6 100644 --- a/dns/dns.md +++ b/dns/dns.md @@ -3,49 +3,47 @@ > 稳定性: 2 - 稳定 -`dns` 模块包含属于两个不同类别的函数: - -1. 使用底层操作系统工具执行名称解析但不一定执行任何网络通信的函数。 - 此类别仅包含一个函数:[`dns.lookup()`]。 - 希望以与同一操作系统上的其他应用程序相同的方式执行名称解析的开发者应使用 [`dns.lookup()`]。 - - 示例,查找 `iana.org`: - - ```js - const dns = require('dns'); - - dns.lookup('iana.org', (err, address, family) => { - console.log('地址: %j 地址族: IPv%s', address, family); - }); - // 地址: "192.0.43.8" 地址族: IPv4 - ``` - -2. 连接到实际 DNS 服务器以执行名称解析并始终使用网络执行 DNS 查询的函数。 - 此类别包含 `dns` 模块中除 [`dns.lookup()`] 之外的所有函数。 - 这些函数不使用与 [`dns.lookup()`] 使用的同一组配置文件(例如 `/etc/hosts`)。 - 这些函数应该由不希望使用底层操作系统的工具进行名称解析、而希望始终执行 DNS 查询的开发者使用,。 - - 示例,解析 `'archive.org'` 然后逆向解析返回的 IP 地址: - - ```js - const dns = require('dns'); - - dns.resolve4('archive.org', (err, addresses) => { - if (err) throw err; - - console.log(`地址: ${JSON.stringify(addresses)}`); - - addresses.forEach((a) => { - dns.reverse(a, (err, hostnames) => { - if (err) { - throw err; - } - console.log(`地址 ${a} 逆向解析到域名: ${JSON.stringify(hostnames)}`); - }); - }); +`dns` 模块用于启用名称解析。 +例如,使用它来查找主机名的 IP 地址。 + +尽管以域名系统(DNS)命名,但它并不总是使用 DNS 协议进行查找。 +[`dns.lookup()`] 使用操作系统功能来执行名称解析。 +它可能不需要执行任何网络通信。 +希望以与同一操作系统上其他应用程序相同的方式执行名称解析的开发者应使用 [`dns.lookup()`]。 + +```js +const dns = require('dns'); + +dns.lookup('example.org', (err, address, family) => { +console.log('地址: %j 地址族: IPv%s', address, family); +}); +// 地址: "93.184.216.34" 地址族: IPv4 +``` + +`dns` 模块中的所有其他函数都连接到实际的 DNS 服务器以执行名称解析。 +它们将会始终使用网络执行 DNS 查询。 +这些函数不使用与 [`dns.lookup()`] 使用的同一组配置文件(例如 `/etc/hosts`)。 +这些函数应由不想使用底层操作系统的功能进行名称解析、而希望始终执行 DNS 查询的开发者使用。 + +```js +const dns = require('dns'); + +dns.resolve4('archive.org', (err, addresses) => { + if (err) throw err; + + console.log(`地址: ${JSON.stringify(addresses)}`); + + addresses.forEach((a) => { + dns.reverse(a, (err, hostnames) => { + if (err) { + throw err; + } + console.log(`地址 ${a} 逆向到: ${JSON.stringify(hostnames)}`); }); - ``` + }); +}); +``` -两类函数有微妙的差别,详见[实现的注意事项][Implementation considerations section]。 +有关更多信息,参阅[实现的注意事项][Implementation considerations section]。 diff --git a/dns/dnspromises_lookup_hostname_options.md b/dns/dnspromises_lookup_hostname_options.md index e2ee3243..d84d5102 100644 --- a/dns/dnspromises_lookup_hostname_options.md +++ b/dns/dnspromises_lookup_hostname_options.md @@ -18,7 +18,7 @@ added: v10.6.0 expected to change in the not too distant future. New code should use `{ verbatim: true }`. -Resolves a hostname (e.g. `'nodejs.org'`) into the first found A (IPv4) or +Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or AAAA (IPv6) record. All `option` properties are optional. If `options` is an integer, then it must be `4` or `6` – if `options` is not provided, then IPv4 and IPv6 addresses are both returned if found. @@ -29,7 +29,7 @@ being an array of objects with the properties `address` and `family`. On error, the `Promise` is rejected with an [`Error`][] object, where `err.code` is the error code. Keep in mind that `err.code` will be set to `'ENOTFOUND'` not only when -the hostname does not exist but also when the lookup fails in other ways +the host name does not exist but also when the lookup fails in other ways such as no available file descriptors. [`dnsPromises.lookup()`][] does not necessarily have anything to do with the DNS diff --git a/dns/dnspromises_lookupservice_address_port.md b/dns/dnspromises_lookupservice_address_port.md index 5fee10be..19269cab 100644 --- a/dns/dnspromises_lookupservice_address_port.md +++ b/dns/dnspromises_lookupservice_address_port.md @@ -5,7 +5,7 @@ added: v10.6.0 * `address` {string} * `port` {number} -Resolves the given `address` and `port` into a hostname and service using +Resolves the given `address` and `port` into a host name and service using the operating system's underlying `getnameinfo` implementation. If `address` is not a valid IP address, a `TypeError` will be thrown. diff --git a/dns/dnspromises_resolve4_hostname_options.md b/dns/dnspromises_resolve4_hostname_options.md index 76187c41..5b8091c3 100644 --- a/dns/dnspromises_resolve4_hostname_options.md +++ b/dns/dnspromises_resolve4_hostname_options.md @@ -2,7 +2,7 @@ added: v10.6.0 --> -* `hostname` {string} Hostname to resolve. +* `hostname` {string} Host name to resolve. * `options` {Object} * `ttl` {boolean} Retrieve the Time-To-Live value (TTL) of each record. When `true`, the `Promise` is resolved with an array of diff --git a/dns/dnspromises_resolve6_hostname_options.md b/dns/dnspromises_resolve6_hostname_options.md index cce087b9..fa03f682 100644 --- a/dns/dnspromises_resolve6_hostname_options.md +++ b/dns/dnspromises_resolve6_hostname_options.md @@ -2,7 +2,7 @@ added: v10.6.0 --> -* `hostname` {string} Hostname to resolve. +* `hostname` {string} Host name to resolve. * `options` {Object} * `ttl` {boolean} Retrieve the Time-To-Live value (TTL) of each record. When `true`, the `Promise` is resolved with an array of diff --git a/dns/dnspromises_resolve_hostname_rrtype.md b/dns/dnspromises_resolve_hostname_rrtype.md index 1db3c4a8..94630015 100644 --- a/dns/dnspromises_resolve_hostname_rrtype.md +++ b/dns/dnspromises_resolve_hostname_rrtype.md @@ -2,10 +2,10 @@ added: v10.6.0 --> -* `hostname` {string} Hostname to resolve. +* `hostname` {string} Host name to resolve. * `rrtype` {string} Resource record type. **Default:** `'A'`. -Uses the DNS protocol to resolve a hostname (e.g. `'nodejs.org'`) into an array +Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array of the resource records. When successful, the `Promise` is resolved with an array of resource records. The type and structure of individual results vary based on `rrtype`: diff --git a/dns/dnspromises_reverse_ip.md b/dns/dnspromises_reverse_ip.md index af704434..8fb2d528 100644 --- a/dns/dnspromises_reverse_ip.md +++ b/dns/dnspromises_reverse_ip.md @@ -5,7 +5,7 @@ added: v10.6.0 * `ip` {string} Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an -array of hostnames. +array of host names. On error, the `Promise` is rejected with an [`Error`][] object, where `err.code` is one of the [DNS error codes](#dns_error_codes). diff --git a/errors/err_invalid_array_length.md b/errors/err_invalid_array_length.md deleted file mode 100644 index 54e5693a..00000000 --- a/errors/err_invalid_array_length.md +++ /dev/null @@ -1,4 +0,0 @@ - -An array was not of the expected length or in a valid range. - - diff --git a/errors/err_invalid_domain_name.md b/errors/err_invalid_domain_name.md deleted file mode 100644 index 32e8f965..00000000 --- a/errors/err_invalid_domain_name.md +++ /dev/null @@ -1,4 +0,0 @@ - -`hostname` can not be parsed from a provided URL. - - diff --git a/errors/err_missing_module.md b/errors/err_missing_module.md deleted file mode 100644 index 26df541e..00000000 --- a/errors/err_missing_module.md +++ /dev/null @@ -1,6 +0,0 @@ - -> Stability: 1 - Experimental - -An [ES6 module][] could not be resolved. - - diff --git a/errors/err_module_resolution_legacy.md b/errors/err_module_resolution_legacy.md deleted file mode 100644 index 4f20dbc3..00000000 --- a/errors/err_module_resolution_legacy.md +++ /dev/null @@ -1,6 +0,0 @@ - -> Stability: 1 - Experimental - -A failure occurred resolving imports in an [ES6 module][]. - - diff --git a/errors/err_tls_handshake_timeout.md b/errors/err_tls_handshake_timeout.md index be4c7964..561c47e9 100644 --- a/errors/err_tls_handshake_timeout.md +++ b/errors/err_tls_handshake_timeout.md @@ -2,4 +2,4 @@ A TLS/SSL handshake timed out. In this case, the server must also abort the connection. - + diff --git a/errors/err_tls_invalid_context.md b/errors/err_tls_invalid_context.md new file mode 100644 index 00000000..f2157a0d --- /dev/null +++ b/errors/err_tls_invalid_context.md @@ -0,0 +1,7 @@ + + +The context must be a `SecureContext`. + + diff --git a/errors/err_tls_psk_set_identiy_hint_failed.md b/errors/err_tls_psk_set_identiy_hint_failed.md new file mode 100644 index 00000000..00e5619f --- /dev/null +++ b/errors/err_tls_psk_set_identiy_hint_failed.md @@ -0,0 +1,4 @@ + +Failed to set PSK identity hint. Hint may be too long. + + diff --git a/errors/err_tls_renegotiate.md b/errors/err_tls_renegotiate.md deleted file mode 100644 index 63e22d0a..00000000 --- a/errors/err_tls_renegotiate.md +++ /dev/null @@ -1,4 +0,0 @@ - -An attempt to renegotiate the TLS session failed. - - diff --git a/errors/err_tls_sni_from_server.md b/errors/err_tls_sni_from_server.md index fef29479..32d58d27 100644 --- a/errors/err_tls_sni_from_server.md +++ b/errors/err_tls_sni_from_server.md @@ -2,4 +2,4 @@ An attempt was made to issue Server Name Indication from a TLS server-side socket, which is only valid from a client. - + diff --git a/errors/err_unknown_signal.md b/errors/err_unknown_signal.md index e40f762b..4d1a307a 100644 --- a/errors/err_unknown_signal.md +++ b/errors/err_unknown_signal.md @@ -2,4 +2,4 @@ An invalid or unknown process signal was passed to an API expecting a valid signal (such as [`subprocess.kill()`][]). - + diff --git a/errors/err_unsupported_esm_url_scheme.md b/errors/err_unsupported_esm_url_scheme.md new file mode 100644 index 00000000..92dfcdf6 --- /dev/null +++ b/errors/err_unsupported_esm_url_scheme.md @@ -0,0 +1,4 @@ + +`import` with URL schemes other than `file` and `data` is unsupported. + + diff --git a/errors/err_vm_module_not_module.md b/errors/err_vm_module_not_module.md index e0668c48..de2ba301 100644 --- a/errors/err_vm_module_not_module.md +++ b/errors/err_vm_module_not_module.md @@ -1,4 +1,4 @@ -The fulfilled value of a linking promise is not a `vm.SourceTextModule` object. +The fulfilled value of a linking promise is not a `vm.Module` object. diff --git a/errors/err_vm_module_status.md b/errors/err_vm_module_status.md index b3002530..357e144a 100644 --- a/errors/err_vm_module_status.md +++ b/errors/err_vm_module_status.md @@ -2,4 +2,4 @@ The current module's status does not allow for this operation. The specific meaning of the error depends on the specific function. - + diff --git a/errors/err_wasi_already_started.md b/errors/err_wasi_already_started.md new file mode 100644 index 00000000..c88243fe --- /dev/null +++ b/errors/err_wasi_already_started.md @@ -0,0 +1,4 @@ + +The WASI instance has already started. + + diff --git a/errors/err_worker_invalid_exec_argv.md b/errors/err_worker_invalid_exec_argv.md index 8b4d0361..654d8fae 100644 --- a/errors/err_worker_invalid_exec_argv.md +++ b/errors/err_worker_invalid_exec_argv.md @@ -2,4 +2,4 @@ The `execArgv` option passed to the `Worker` constructor contains invalid flags. - + diff --git a/errors/err_worker_out_of_memory.md b/errors/err_worker_out_of_memory.md new file mode 100644 index 00000000..55376e3b --- /dev/null +++ b/errors/err_worker_out_of_memory.md @@ -0,0 +1,4 @@ + +The `Worker` instance terminated because it reached its memory limit. + + diff --git a/esm/approach_1_use_an_es_module_wrapper.md b/esm/approach_1_use_an_es_module_wrapper.md new file mode 100644 index 00000000..14800c09 --- /dev/null +++ b/esm/approach_1_use_an_es_module_wrapper.md @@ -0,0 +1,81 @@ + +Write the package in CommonJS or transpile ES module sources into CommonJS, and +create an ES module wrapper file that defines the named exports. Using +[Conditional Exports][], the ES module wrapper is used for `import` and the +CommonJS entry point for `require`. + + +```js +// ./node_modules/pkg/package.json +{ + "type": "module", + "main": "./index.cjs", + "exports": { + "require": "./index.cjs", + "import": "./wrapper.mjs" + } +} +``` + +```js +// ./node_modules/pkg/index.cjs +exports.name = 'value'; +``` + +```js +// ./node_modules/pkg/wrapper.mjs +import cjsModule from './index.cjs'; +export const name = cjsModule.name; +``` + +In this example, the `name` from `import { name } from 'pkg'` is the same +singleton as the `name` from `const { name } = require('pkg')`. Therefore `===` +returns `true` when comparing the two `name`s and the divergent specifier hazard +is avoided. + +If the module is not simply a list of named exports, but rather contains a +unique function or object export like `module.exports = function () { ... }`, +or if support in the wrapper for the `import pkg from 'pkg'` pattern is desired, +then the wrapper would instead be written to export the default optionally +along with any named exports as well: + +```js +import cjsModule from './index.cjs'; +export const name = cjsModule.name; +export default cjsModule; +``` + +This approach is appropriate for any of the following use cases: +* The package is currently written in CommonJS and the author would prefer not + to refactor it into ES module syntax, but wishes to provide named exports for + ES module consumers. +* The package has other packages that depend on it, and the end user might + install both this package and those other packages. For example a `utilities` + package is used directly in an application, and a `utilities-plus` package + adds a few more functions to `utilities`. Because the wrapper exports + underlying CommonJS files, it doesn’t matter if `utilities-plus` is written in + CommonJS or ES module syntax; it will work either way. +* The package stores internal state, and the package author would prefer not to + refactor the package to isolate its state management. See the next section. + +A variant of this approach not requiring conditional exports for consumers could +be to add an export, e.g. `"./module"`, to point to an all-ES module-syntax +version of the package. This could be used via `import 'pkg/module'` by users +who are certain that the CommonJS version will not be loaded anywhere in the +application, such as by dependencies; or if the CommonJS version can be loaded +but doesn’t affect the ES module version (for example, because the package is +stateless): + + +```js +// ./node_modules/pkg/package.json +{ + "type": "module", + "main": "./index.cjs", + "exports": { + ".": "./index.cjs", + "./module": "./wrapper.mjs" + } +} +``` + diff --git a/esm/approach_2_isolate_state.md b/esm/approach_2_isolate_state.md new file mode 100644 index 00000000..4dbb3add --- /dev/null +++ b/esm/approach_2_isolate_state.md @@ -0,0 +1,103 @@ + +The most straightforward `package.json` would be one that defines the separate +CommonJS and ES module entry points directly: + + +```js +// ./node_modules/pkg/package.json +{ + "type": "module", + "main": "./index.cjs", + "exports": { + "import": "./index.mjs", + "require": "./index.cjs" + } +} +``` + +This can be done if both the CommonJS and ES module versions of the package are +equivalent, for example because one is the transpiled output of the other; and +the package’s management of state is carefully isolated (or the package is +stateless). + +The reason that state is an issue is because both the CommonJS and ES module +versions of the package may get used within an application; for example, the +user’s application code could `import` the ES module version while a dependency +`require`s the CommonJS version. If that were to occur, two copies of the +package would be loaded in memory and therefore two separate states would be +present. This would likely cause hard-to-troubleshoot bugs. + +Aside from writing a stateless package (if JavaScript’s `Math` were a package, +for example, it would be stateless as all of its methods are static), there are +some ways to isolate state so that it’s shared between the potentially loaded +CommonJS and ES module instances of the package: + +1. If possible, contain all state within an instantiated object. JavaScript’s + `Date`, for example, needs to be instantiated to contain state; if it were a + package, it would be used like this: + + ```js + import Date from 'date'; + const someDate = new Date(); + // someDate contains state; Date does not + ``` + + The `new` keyword isn’t required; a package’s function can return a new + object, or modify a passed-in object, to keep the state external to the + package. + +1. Isolate the state in one or more CommonJS files that are shared between the + CommonJS and ES module versions of the package. For example, if the CommonJS + and ES module entry points are `index.cjs` and `index.mjs`, respectively: + + ```js + // ./node_modules/pkg/index.cjs + const state = require('./state.cjs'); + module.exports.state = state; + ``` + + ```js + // ./node_modules/pkg/index.mjs + import state from './state.cjs'; + export { + state + }; + ``` + + Even if `pkg` is used via both `require` and `import` in an application (for + example, via `import` in application code and via `require` by a dependency) + each reference of `pkg` will contain the same state; and modifying that + state from either module system will apply to both. + +Any plugins that attach to the package’s singleton would need to separately +attach to both the CommonJS and ES module singletons. + +This approach is appropriate for any of the following use cases: +* The package is currently written in ES module syntax and the package author + wants that version to be used wherever such syntax is supported. +* The package is stateless or its state can be isolated without too much + difficulty. +* The package is unlikely to have other public packages that depend on it, or if + it does, the package is stateless or has state that need not be shared between + dependencies or with the overall application. + +Even with isolated state, there is still the cost of possible extra code +execution between the CommonJS and ES module versions of a package. + +As with the previous approach, a variant of this approach not requiring +conditional exports for consumers could be to add an export, e.g. +`"./module"`, to point to an all-ES module-syntax version of the package: + + +```js +// ./node_modules/pkg/package.json +{ + "type": "module", + "main": "./index.cjs", + "exports": { + ".": "./index.cjs", + "./module": "./index.mjs" + } +} +``` + diff --git a/esm/dynamic_instantiate_hook.md b/esm/code_dynamicinstantiate_code_hook.md similarity index 68% rename from esm/dynamic_instantiate_hook.md rename to esm/code_dynamicinstantiate_code_hook.md index 4ddd108e..cb3afc82 100644 --- a/esm/dynamic_instantiate_hook.md +++ b/esm/code_dynamicinstantiate_code_hook.md @@ -1,10 +1,19 @@ +> Note: The loaders API is being redesigned. This hook may disappear or its +> signature may change. Do not rely on the API described below. + To create a custom dynamic module that doesn't correspond to one of the existing `format` interpretations, the `dynamicInstantiate` hook can be used. This hook is called only for modules that return `format: 'dynamic'` from -the `resolve` hook. +the [`getFormat` hook][]. ```js +/** + * @param {string} url + * @returns {object} response + * @returns {array} response.exports + * @returns {function} response.execute + */ export async function dynamicInstantiate(url) { return { exports: ['customExportName'], diff --git a/esm/code_getformat_code_hook.md b/esm/code_getformat_code_hook.md new file mode 100644 index 00000000..4c567b40 --- /dev/null +++ b/esm/code_getformat_code_hook.md @@ -0,0 +1,38 @@ + +> Note: The loaders API is being redesigned. This hook may disappear or its +> signature may change. Do not rely on the API described below. + +The `getFormat` hook provides a way to define a custom method of determining how +a URL should be interpreted. This can be one of the following: + +| `format` | Description | +| --- | --- | +| `'builtin'` | Load a Node.js builtin module | +| `'commonjs'` | Load a Node.js CommonJS module | +| `'dynamic'` | Use a [dynamic instantiate hook][] | +| `'json'` | Load a JSON file | +| `'module'` | Load a standard JavaScript module (ES module) | +| `'wasm'` | Load a WebAssembly module | + +```js +/** + * @param {string} url + * @param {object} context (currently empty) + * @param {function} defaultGetFormat + * @returns {object} response + * @returns {string} response.format + */ +export async function getFormat(url, context, defaultGetFormat) { + if (someCondition) { + // For some or all URLs, do some custom logic for determining format. + // Always return an object of the form {format: }, where the + // format is one of the strings in the table above. + return { + format: 'module' + }; + } + // Defer to Node.js for all other URLs. + return defaultGetFormat(url, context, defaultGetFormat); +} +``` + diff --git a/esm/code_getsource_code_hook.md b/esm/code_getsource_code_hook.md new file mode 100644 index 00000000..863eea10 --- /dev/null +++ b/esm/code_getsource_code_hook.md @@ -0,0 +1,31 @@ + +> Note: The loaders API is being redesigned. This hook may disappear or its +> signature may change. Do not rely on the API described below. + +The `getSource` hook provides a way to define a custom method for retrieving +the source code of an ES module specifier. This would allow a loader to +potentially avoid reading files from disk. + +```js +/** + * @param {string} url + * @param {object} context + * @param {string} context.format + * @param {function} defaultGetSource + * @returns {object} response + * @returns {string|buffer} response.source + */ +export async function getSource(url, context, defaultGetSource) { + const { format } = context; + if (someCondition) { + // For some or all URLs, do some custom logic for retrieving the source. + // Always return an object of the form {source: }. + return { + source: '...' + }; + } + // Defer to Node.js for all other URLs. + return defaultGetSource(url, context, defaultGetSource); +} +``` + diff --git a/esm/code_import_code_statements.md b/esm/code_import_code_statements.md deleted file mode 100644 index 771c1778..00000000 --- a/esm/code_import_code_statements.md +++ /dev/null @@ -1,31 +0,0 @@ - -An `import` statement can reference an ES module, a CommonJS module, or JSON. -Other file types such as Native modules are not supported. For those, -use [`module.createRequire()`][]. - -`import` statements are permitted only in ES modules. For similar functionality -in CommonJS, see [`import()`][]. - -The _specifier_ of an `import` statement (the string after the `from` keyword) -can either be an URL-style relative path like `'./file.mjs'` or a package name -like `'fs'`. - -Like in CommonJS, files within packages can be accessed by appending a path to -the package name. - -```js -import { sin, cos } from 'geometry/trigonometry-functions.mjs'; -``` - -> Currently only the “default export” is supported for CommonJS files or -> packages: -> -> -> ```js -> import packageMain from 'commonjs-package'; // Works -> -> import { method } from 'commonjs-package'; // Errors -> ``` -> -> There are ongoing efforts to make the latter code possible. - diff --git a/esm/code_package_json_code_code_main_code.md b/esm/code_package_json_code_code_main_code.md new file mode 100644 index 00000000..4587284b --- /dev/null +++ b/esm/code_package_json_code_code_main_code.md @@ -0,0 +1,36 @@ + +The `package.json` `"main"` field defines the entry point for a package, +whether the package is included into CommonJS via `require` or into an ES +module via `import`. + + +```js +// ./node_modules/es-module-package/package.json +{ + "type": "module", + "main": "./src/index.js" +} +``` + +```js +// ./my-app.mjs + +import { something } from 'es-module-package'; +// Loads from ./node_modules/es-module-package/src/index.js +``` + +An attempt to `require` the above `es-module-package` would attempt to load +`./node_modules/es-module-package/src/index.js` as CommonJS, which would throw +an error as Node.js would not be able to parse the `export` statement in +CommonJS. + +As with `import` statements, for ES module usage the value of `"main"` must be +a full path including extension: `"./index.mjs"`, not `"./index"`. + +If the `package.json` `"type"` field is omitted, a `.js` file in `"main"` will +be interpreted as CommonJS. + +The `"main"` field can point to exactly one file, regardless of whether the +package is referenced via `require` (in a CommonJS context) or `import` (in an +ES module context). + diff --git a/esm/code_resolve_code_hook.md b/esm/code_resolve_code_hook.md new file mode 100644 index 00000000..e9d77756 --- /dev/null +++ b/esm/code_resolve_code_hook.md @@ -0,0 +1,33 @@ + +> Note: The loaders API is being redesigned. This hook may disappear or its +> signature may change. Do not rely on the API described below. + +The `resolve` hook returns the resolved file URL for a given module specifier +and parent URL. The module specifier is the string in an `import` statement or +`import()` expression, and the parent URL is the URL of the module that imported +this one, or `undefined` if this is the main entry point for the application. + +```js +/** + * @param {string} specifier + * @param {object} context + * @param {string} context.parentURL + * @param {function} defaultResolve + * @returns {object} response + * @returns {string} response.url + */ +export async function resolve(specifier, context, defaultResolve) { + const { parentURL = null } = context; + if (someCondition) { + // For some or all specifiers, do some custom logic for resolving. + // Always return an object of the form {url: } + return { + url: (parentURL) ? + new URL(specifier, parentURL).href : new URL(specifier).href + }; + } + // Defer to Node.js for all other specifiers. + return defaultResolve(specifier, context, defaultResolve); +} +``` + diff --git a/esm/code_transformsource_code_hook.md b/esm/code_transformsource_code_hook.md new file mode 100644 index 00000000..5cc6b265 --- /dev/null +++ b/esm/code_transformsource_code_hook.md @@ -0,0 +1,43 @@ + +```console +NODE_OPTIONS='--experimental-modules --experimental-loader ./custom-loader.mjs' node x.js +``` + +> Note: The loaders API is being redesigned. This hook may disappear or its +> signature may change. Do not rely on the API described below. + +The `transformSource` hook provides a way to modify the source code of a loaded +ES module file after the source string has been loaded but before Node.js has +done anything with it. + +If this hook is used to convert unknown-to-Node.js file types into executable +JavaScript, a resolve hook is also necessary in order to register any +unknown-to-Node.js file extensions. See the [transpiler loader example][] below. + +```js +/** + * @param {string|buffer} source + * @param {object} context + * @param {string} context.url + * @param {string} context.format + * @param {function} defaultTransformSource + * @returns {object} response + * @returns {string|buffer} response.source + */ +export async function transformSource(source, + context, + defaultTransformSource) { + const { url, format } = context; + if (someCondition) { + // For some or all URLs, do some custom logic for modifying the source. + // Always return an object of the form {source: }. + return { + source: '...' + }; + } + // Defer to Node.js for all other sources. + return defaultTransformSource( + source, context, defaultTransformSource); +} +``` + diff --git a/esm/compatibility_with_commonjs_only_versions_of_node_js.md b/esm/compatibility_with_commonjs_only_versions_of_node_js.md deleted file mode 100644 index c5f13c5d..00000000 --- a/esm/compatibility_with_commonjs_only_versions_of_node_js.md +++ /dev/null @@ -1,40 +0,0 @@ - -Prior to the introduction of support for ES modules in Node.js, it was a common -pattern for package authors to include both CommonJS and ES module JavaScript -sources in their package, with `package.json` `"main"` specifying the CommonJS -entry point and `package.json` `"module"` specifying the ES module entry point. -This enabled Node.js to run the CommonJS entry point while build tools such as -bundlers used the ES module entry point, since Node.js ignored (and still -ignores) `"module"`. - -Node.js can now run ES module entry points, but it remains impossible for a -package to define separate CommonJS and ES module entry points. This is for good -reason: the `pkg` variable created from `import pkg from 'pkg'` is not the same -singleton as the `pkg` variable created from `const pkg = require('pkg')`, so if -both are referenced within the same app (including dependencies), unexpected -behavior might occur. - -There are two general approaches to addressing this limitation while still -publishing a package that contains both CommonJS and ES module sources: - -1. Document a new ES module entry point that’s not the package `"main"`, e.g. - `import pkg from 'pkg/module.mjs'` (or `import 'pkg/esm'`, if using [package - exports][]). The package `"main"` would still point to a CommonJS file, and - thus the package would remain compatible with older versions of Node.js that - lack support for ES modules. - -1. Switch the package `"main"` entry point to an ES module file as part of a - breaking change version bump. This version and above would only be usable on - ES module-supporting versions of Node.js. If the package still contains a - CommonJS version, it would be accessible via a path within the package, e.g. - `require('pkg/commonjs')`; this is essentially the inverse of the previous - approach. Package consumers who are using CommonJS-only versions of Node.js - would need to update their code from `require('pkg')` to e.g. - `require('pkg/commonjs')`. - -Of course, a package could also include only CommonJS or only ES module sources. -An existing package could make a semver major bump to an ES module-only version, -that would only be supported in ES module-supporting versions of Node.js (and -other runtimes). New packages could be published containing only ES module -sources, and would be compatible only with ES module-supporting runtimes. - diff --git a/esm/conditional_exports.md b/esm/conditional_exports.md new file mode 100644 index 00000000..9d2617e5 --- /dev/null +++ b/esm/conditional_exports.md @@ -0,0 +1,49 @@ + +Conditional exports provide a way to map to different paths depending on +certain conditions. They are supported for both CommonJS and ES module imports. + +For example, a package that wants to provide different ES module exports for +Node.js and the browser can be written: + + +```js +// ./node_modules/pkg/package.json +{ + "type": "module", + "main": "./index.js", + "exports": { + "./feature": { + "import": "./feature-default.js", + "browser": "./feature-browser.js" + } + } +} +``` + +When resolving the `"."` export, if no matching target is found, the `"main"` +will be used as the final fallback. + +The conditions supported in Node.js condition matching: + +* `"default"` - the generic fallback that will always match. Can be a CommonJS + or ES module file. +* `"import"` - matched when the package is loaded via `import` or + `import()`. Can be any module format, this field does not set the type + interpretation. +* `"node"` - matched for any Node.js environment. Can be a CommonJS or ES + module file. +* `"require"` - matched when the package is loaded via `require()`. + +Condition matching is applied in object order from first to last within the +`"exports"` object. + +Using the `"require"` condition it is possible to define a package that will +have a different exported value for CommonJS and ES modules, which can be a +hazard in that it can result in having two separate instances of the same +package in use in an application, which can cause a number of bugs. + +Other conditions such as `"browser"`, `"electron"`, `"deno"`, `"react-native"`, +etc. could be defined in other runtimes or tools. Condition names must not start +with `"."` or be numbers. Further restrictions, definitions or guidance on +condition names may be provided in future. + diff --git a/esm/customizing_esm_specifier_resolution_algorithm.md b/esm/customizing_esm_specifier_resolution_algorithm.md index 843bf061..81d43c35 100644 --- a/esm/customizing_esm_specifier_resolution_algorithm.md +++ b/esm/customizing_esm_specifier_resolution_algorithm.md @@ -4,7 +4,7 @@ the CommonJS loader. One of the behavior differences is automatic resolution of file extensions and the ability to import directories that have an index file. -The `--es-module-specifier-resolution=[mode]` flag can be used to customize +The `--experimental-specifier-resolution=[mode]` flag can be used to customize the extension resolution algorithm. The default mode is `explicit`, which requires the full path to a module be provided to the loader. To enable the automatic extension resolution and importing from directories that include an @@ -15,7 +15,7 @@ $ node --experimental-modules index.mjs success! $ node --experimental-modules index #Failure! Error: Cannot find module -$ node --experimental-modules --es-module-specifier-resolution=node index +$ node --experimental-modules --experimental-specifier-resolution=node index success! ``` @@ -30,6 +30,14 @@ success! + + + + + + + + diff --git a/esm/dual_commonjs_es_module_packages.md b/esm/dual_commonjs_es_module_packages.md new file mode 100644 index 00000000..2458c796 --- /dev/null +++ b/esm/dual_commonjs_es_module_packages.md @@ -0,0 +1,17 @@ + +Prior to the introduction of support for ES modules in Node.js, it was a common +pattern for package authors to include both CommonJS and ES module JavaScript +sources in their package, with `package.json` `"main"` specifying the CommonJS +entry point and `package.json` `"module"` specifying the ES module entry point. +This enabled Node.js to run the CommonJS entry point while build tools such as +bundlers used the ES module entry point, since Node.js ignored (and still +ignores) the top-level `"module"` field. + +Node.js can now run ES module entry points, and a package can contain both +CommonJS and ES module entry points (either via separate specifiers such as +`'pkg'` and `'pkg/es-module'`, or both at the same specifier via [Conditional +Exports][]). Unlike in the scenario where `"module"` is only used by bundlers, +or ES module files are transpiled into CommonJS on the fly before evaluation by +Node.js, the files referenced by the ES module entry point are evaluated as ES +modules. + diff --git a/esm/dual_package_hazard.md b/esm/dual_package_hazard.md new file mode 100644 index 00000000..7085654e --- /dev/null +++ b/esm/dual_package_hazard.md @@ -0,0 +1,22 @@ + +When an application is using a package that provides both CommonJS and ES module +sources, there is a risk of certain bugs if both versions of the package get +loaded. This potential comes from the fact that the `pkgInstance` created by +`const pkgInstance = require('pkg')` is not the same as the `pkgInstance` +created by `import pkgInstance from 'pkg'` (or an alternative main path like +`'pkg/module'`). This is the “dual package hazard,” where two versions of the +same package can be loaded within the same runtime environment. While it is +unlikely that an application or package would intentionally load both versions +directly, it is common for an application to load one version while a dependency +of the application loads the other version. This hazard can happen because +Node.js supports intermixing CommonJS and ES modules, and can lead to unexpected +behavior. + +If the package main export is a constructor, an `instanceof` comparison of +instances created by the two versions returns `false`, and if the export is an +object, properties added to one (like `pkgInstance.foo = 3`) are not present on +the other. This differs from how `import` and `require` statements work in +all-CommonJS or all-ES module environments, respectively, and therefore is +surprising to users. It also differs from the behavior users are familiar with +when using transpilation via tools like [Babel][] or [`esm`][]. + diff --git a/esm/examples.md b/esm/examples.md new file mode 100644 index 00000000..c28c64b6 --- /dev/null +++ b/esm/examples.md @@ -0,0 +1,4 @@ + +The various loader hooks can be used together to accomplish wide-ranging +customizations of Node.js’ code loading and evaluation behaviors. + diff --git a/esm/experimental_loader_hooks.md b/esm/experimental_loaders.md similarity index 100% rename from esm/experimental_loader_hooks.md rename to esm/experimental_loaders.md diff --git a/esm/exports_sugar.md b/esm/exports_sugar.md new file mode 100644 index 00000000..ffee250c --- /dev/null +++ b/esm/exports_sugar.md @@ -0,0 +1,68 @@ + +If the `"."` export is the only export, the `"exports"` field provides sugar +for this case being the direct `"exports"` field value. + +If the `"."` export has a fallback array or string value, then the `"exports"` +field can be set to this value directly. + + +```js +{ + "exports": { + ".": "./main.js" + } +} +``` + +can be written: + + +```js +{ + "exports": "./main.js" +} +``` + +When using [Conditional Exports][], the rule is that all keys in the object +mapping must not start with a `"."` otherwise they would be indistinguishable +from exports subpaths. + + +```js +{ + "exports": { + ".": { + "import": "./main.js", + "require": "./main.cjs" + } + } +} +``` + +can be written: + + +```js +{ + "exports": { + "import": "./main.js", + "require": "./main.cjs" + } +} +``` + +If writing any exports value that mixes up these two forms, an error will be +thrown: + + +```js +{ + // Throws on resolution! + "exports": { + "./feature": "./lib/feature.js", + "import": "./main.js", + "require": "./main.cjs" + } +} +``` + diff --git a/esm/code_import_code_specifiers.md b/esm/hooks.md similarity index 100% rename from esm/code_import_code_specifiers.md rename to esm/hooks.md diff --git a/esm/https_loader.md b/esm/https_loader.md new file mode 100644 index 00000000..2efed03c --- /dev/null +++ b/esm/https_loader.md @@ -0,0 +1,78 @@ + +In current Node.js, specifiers starting with `https://` are unsupported. The +loader below registers hooks to enable rudimentary support for such specifiers. +While this may seem like a significant improvement to Node.js core +functionality, there are substantial downsides to actually using this loader: +performance is much slower than loading files from disk, there is no caching, +and there is no security. + +```js +// https-loader.mjs +import { get } from 'https'; + +export function resolve(specifier, context, defaultResolve) { + const { parentURL = null } = context; + + // Normally Node.js would error on specifiers starting with 'https://', so + // this hook intercepts them and converts them into absolute URLs to be + // passed along to the later hooks below. + if (specifier.startsWith('https://')) { + return { + url: specifier + }; + } else if (parentURL && parentURL.startsWith('https://')) { + return { + url: new URL(specifier, parentURL).href + }; + } + + // Let Node.js handle all other specifiers. + return defaultResolve(specifier, context, defaultResolve); +} + +export function getFormat(url, context, defaultGetFormat) { + // This loader assumes all network-provided JavaScript is ES module code. + if (url.startsWith('https://')) { + return { + format: 'module' + }; + } + + // Let Node.js handle all other URLs. + return defaultGetFormat(url, context, defaultGetFormat); +} + +export function getSource(url, context, defaultGetSource) { + // For JavaScript to be loaded over the network, we need to fetch and + // return it. + if (url.startsWith('https://')) { + return new Promise((resolve, reject) => { + get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => resolve({ source: data })); + }).on('error', (err) => reject(err)); + }); + } + + // Let Node.js handle all other URLs. + return defaultGetSource(url, context, defaultGetSource); +} +``` + +```js +// main.mjs +import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js'; + +console.log(VERSION); +``` + +With this loader, running: + +```console +node --experimental-loader ./https-loader.mjs ./main.js +``` + +Will print the current version of CoffeeScript per the module at the URL in +`main.mjs`. + diff --git a/esm/code_import_code_expressions.md b/esm/import_expressions.md similarity index 100% rename from esm/code_import_code_expressions.md rename to esm/import_expressions.md diff --git a/esm/notable_differences_between_import_and_require.md b/esm/import_specifiers.md similarity index 100% rename from esm/notable_differences_between_import_and_require.md rename to esm/import_specifiers.md diff --git a/esm/import_statements.md b/esm/import_statements.md new file mode 100644 index 00000000..7b0a0bd2 --- /dev/null +++ b/esm/import_statements.md @@ -0,0 +1,30 @@ + +An `import` statement can reference an ES module or a CommonJS module. Other +file types such as JSON or Native modules are not supported. For those, use +[`module.createRequire()`][]. + +`import` statements are permitted only in ES modules. For similar functionality +in CommonJS, see [`import()`][]. + +The _specifier_ of an `import` statement (the string after the `from` keyword) +can either be an URL-style relative path like `'./file.mjs'` or a package name +like `'fs'`. + +Like in CommonJS, files within packages can be accessed by appending a path to +the package name; unless the package’s `package.json` contains an [`"exports"` +field][], in which case files within packages need to be accessed via the path +defined in `"exports"`. + +```js +import { sin, cos } from 'geometry/trigonometry-functions.mjs'; +``` + +Only the “default export” is supported for CommonJS files or packages: + + +```js +import packageMain from 'commonjs-package'; // Works + +import { method } from 'commonjs-package'; // Errors +``` + diff --git a/esm/in_same_folder_as_above_package_json.md b/esm/in_same_folder_as_above_package_json.md deleted file mode 100644 index 7616af69..00000000 --- a/esm/in_same_folder_as_above_package_json.md +++ /dev/null @@ -1,17 +0,0 @@ -node --experimental-modules my-app.js # Runs as ES module -``` - -If the nearest parent `package.json` lacks a `"type"` field, or contains -`"type": "commonjs"`, extensionless and `.js` files are treated as CommonJS. -If the volume root is reached and no `package.json` is found, -Node.js defers to the default, a `package.json` with no `"type"` -field. - -`import` statements of `.js` and extensionless files are treated as ES modules -if the nearest parent `package.json` contains `"type": "module"`. - -```js -// my-app.js, part of the same example as above -import './startup.js'; // Loaded as ES module because of package.json -``` - diff --git a/esm/code_input_type_code_flag.md b/esm/input_type_flag.md similarity index 100% rename from esm/code_input_type_code_flag.md rename to esm/input_type_flag.md diff --git a/esm/interop_with_existing_modules.md b/esm/interop_with_existing_modules.md deleted file mode 100644 index c2d4e8aa..00000000 --- a/esm/interop_with_existing_modules.md +++ /dev/null @@ -1,47 +0,0 @@ - -All CommonJS, JSON, and C++ modules can be used with `import`. - -Modules loaded this way will only be loaded once, even if their query -or fragment string differs between `import` statements. - -When loaded via `import` these modules will provide a single `default` export -representing the value of `module.exports` at the time they finished evaluating. - -```js -// foo.js -module.exports = { one: 1 }; - -// bar.mjs -import foo from './foo.js'; -foo.one === 1; // true -``` - -Builtin modules will provide named exports of their public API, as well as a -default export which can be used for, among other things, modifying the named -exports. Named exports of builtin modules are updated when the corresponding -exports property is accessed, redefined, or deleted. - -```js -import EventEmitter from 'events'; -const e = new EventEmitter(); -``` - -```js -import { readFile } from 'fs'; -readFile('./foo.txt', (err, source) => { - if (err) { - console.error(err); - } else { - console.log(source); - } -}); -``` - -```js -import fs, { readFileSync } from 'fs'; - -fs.readFileSync = () => Buffer.from('Hello, ESM'); - -fs.readFileSync === readFileSync; -``` - diff --git a/esm/json_modules.md b/esm/json_modules.md deleted file mode 100644 index 966a0d49..00000000 --- a/esm/json_modules.md +++ /dev/null @@ -1,16 +0,0 @@ - -JSON modules follow the [WHATWG JSON modules specification][]. - -The imported JSON only exposes a `default`. There is no -support for named exports. A cache entry is created in the CommonJS -cache, to avoid duplication. The same object will be returned in -CommonJS if the JSON module has already been imported from the -same path. - -Assuming an `index.mjs` with - - -```js -import packageConfig from './package.json'; -``` - diff --git a/esm/loader_hooks.md b/esm/loader_hooks.md deleted file mode 100644 index f1c67605..00000000 --- a/esm/loader_hooks.md +++ /dev/null @@ -1,9 +0,0 @@ - - - -To customize the default module resolution, loader hooks can optionally be -provided via a `--loader ./loader-name.mjs` argument to Node.js. - -When hooks are used they only apply to ES module loading and not to any -CommonJS modules loaded. - diff --git a/esm/no_code_node_path_code.md b/esm/no_code_node_path_code.md deleted file mode 100644 index c2590455..00000000 --- a/esm/no_code_node_path_code.md +++ /dev/null @@ -1,4 +0,0 @@ - -`NODE_PATH` is not part of resolving `import` specifiers. Please use symlinks -if this behavior is desired. - diff --git a/esm/no_code_require_cache_code.md b/esm/no_code_require_cache_code.md deleted file mode 100644 index 3d3f4e13..00000000 --- a/esm/no_code_require_cache_code.md +++ /dev/null @@ -1,3 +0,0 @@ - -`require.cache` is not used by `import`. It has a separate cache. - diff --git a/esm/no_code_require_extensions_code.md b/esm/no_code_require_extensions_code.md deleted file mode 100644 index 051ece78..00000000 --- a/esm/no_code_require_extensions_code.md +++ /dev/null @@ -1,4 +0,0 @@ - -`require.extensions` is not used by `import`. The expectation is that loader -hooks can provide this workflow in the future. - diff --git a/esm/no_code_require_code_code_exports_code_code_module_exports_code_code_filename_code_code_dirname_code.md b/esm/no_require_exports_module_exports_filename_dirname.md similarity index 100% rename from esm/no_code_require_code_code_exports_code_code_module_exports_code_code_filename_code_code_dirname_code.md rename to esm/no_require_exports_module_exports_filename_dirname.md diff --git a/esm/package_entry_points.md b/esm/package_entry_points.md index 4587284b..f6e1e022 100644 --- a/esm/package_entry_points.md +++ b/esm/package_entry_points.md @@ -1,36 +1,12 @@ -The `package.json` `"main"` field defines the entry point for a package, -whether the package is included into CommonJS via `require` or into an ES -module via `import`. - - -```js -// ./node_modules/es-module-package/package.json -{ - "type": "module", - "main": "./src/index.js" -} -``` - -```js -// ./my-app.mjs - -import { something } from 'es-module-package'; -// Loads from ./node_modules/es-module-package/src/index.js -``` - -An attempt to `require` the above `es-module-package` would attempt to load -`./node_modules/es-module-package/src/index.js` as CommonJS, which would throw -an error as Node.js would not be able to parse the `export` statement in -CommonJS. - -As with `import` statements, for ES module usage the value of `"main"` must be -a full path including extension: `"./index.mjs"`, not `"./index"`. - -If the `package.json` `"type"` field is omitted, a `.js` file in `"main"` will -be interpreted as CommonJS. - -The `"main"` field can point to exactly one file, regardless of whether the -package is referenced via `require` (in a CommonJS context) or `import` (in an -ES module context). +There are two fields that can define entry points for a package: `"main"` and +`"exports"`. The `"main"` field is supported in all versions of Node.js, but its +capabilities are limited: it only defines the main entry point of the package. +The `"exports"` field, part of [Package Exports][], provides an alternative to +`"main"` where the package main entry point can be defined while also +encapsulating the package, preventing any other entry points besides those +defined in `"exports"`. If package entry points are defined in both `"main"` and +`"exports"`, the latter takes precedence in versions of Node.js that support +`"exports"`. [Conditional Exports][] can also be used within `"exports"` to +define different package entry points per environment. diff --git a/esm/package_exports.md b/esm/package_exports.md index 4f221595..3047c7ae 100644 --- a/esm/package_exports.md +++ b/esm/package_exports.md @@ -50,48 +50,37 @@ If a package has no exports, setting `"exports": false` can be used instead of `"exports": {}` to indicate the package does not intend for submodules to be exposed. -Exports can also be used to map the main entry point of a package: +Any invalid exports entries will be ignored. This includes exports not +starting with `"./"` or a missing trailing `"/"` for directory exports. + +Array fallback support is provided for exports, similarly to import maps +in order to be forwards-compatible with possible fallback workflows in future: ```js -// ./node_modules/es-module-package/package.json { "exports": { - ".": "./main.js" + "./submodule": ["not:valid", "./submodule.js"] } } ``` -where the "." indicates loading the package without any subpath. Exports will -always override any existing `"main"` value for both CommonJS and -ES module packages. - -For packages with only a main entry point, an `"exports"` value of just -a string is also supported: - - -```js -// ./node_modules/es-module-package/package.json -{ - "exports": "./main.js" -} -``` +Since `"not:valid"` is not a supported target, `"./submodule.js"` is used +instead as the fallback, as if it were the only target. -Any invalid exports entries will be ignored. This includes exports not -starting with `"./"` or a missing trailing `"/"` for directory exports. +Defining a `"."` export will define the main entry point for the package, +and will always take precedence over the `"main"` field in the `package.json`. -Array fallback support is provided for exports, similarly to import maps -in order to be forward-compatible with fallback workflows in future: +This allows defining a different entry point for Node.js versions that support +ECMAScript modules and versions that don't, for example: ```js { + "main": "./main-legacy.cjs", "exports": { - "./submodule": ["not:valid", "./submodule.js"] + ".": "./main-modern.cjs" } } ``` -Since `"not:valid"` is not a supported target, `"./submodule.js"` is used -instead as the fallback, as if it were the only target. - diff --git a/esm/code_package_json_code_code_type_code_field.md b/esm/package_json_type_field.md similarity index 73% rename from esm/code_package_json_code_code_type_code_field.md rename to esm/package_json_type_field.md index 1404c758..9c7fc496 100644 --- a/esm/code_package_json_code_code_type_code_field.md +++ b/esm/package_json_type_field.md @@ -1,7 +1,7 @@ -Files ending with `.js` or `.mjs`, or lacking any extension, -will be loaded as ES modules when the nearest parent `package.json` file -contains a top-level field `"type"` with a value of `"module"`. +Files ending with `.js` or lacking any extension will be loaded as ES modules +when the nearest parent `package.json` file contains a top-level field `"type"` +with a value of `"module"`. The nearest parent `package.json` is defined as the first `package.json` found when searching in the current folder, that folder’s parent, and so on up @@ -24,7 +24,8 @@ If the nearest parent `package.json` lacks a `"type"` field, or contains `"type": "commonjs"`, extensionless and `.js` files are treated as CommonJS. If the volume root is reached and no `package.json` is found, Node.js defers to the default, a `package.json` with no `"type"` -field. +field. "Extensionless" refers to file paths which do not contain +an extension as opposed to optionally dropping a file extension in a specifier. `import` statements of `.js` and extensionless files are treated as ES modules if the nearest parent `package.json` contains `"type": "module"`. @@ -40,3 +41,6 @@ future-proof the package in case the default type of Node.js ever changes, and it will also make things easier for build tools and loaders to determine how the files in the package should be interpreted. +Regardless of the value of the `"type"` field, `.mjs` files are always treated +as ES modules and `.cjs` files are always treated as CommonJS. + diff --git a/esm/code_require_code.md b/esm/require.md similarity index 100% rename from esm/code_require_code.md rename to esm/require.md diff --git a/esm/resolve_hook.md b/esm/resolve_hook.md deleted file mode 100644 index aa123a6a..00000000 --- a/esm/resolve_hook.md +++ /dev/null @@ -1,99 +0,0 @@ - -The resolve hook returns the resolved file URL and module format for a -given module specifier and parent file URL: - -```js -import { URL, pathToFileURL } from 'url'; -const baseURL = pathToFileURL(process.cwd()).href; - -/** - * @param {string} specifier - * @param {string} parentModuleURL - * @param {function} defaultResolver - */ -export async function resolve(specifier, - parentModuleURL = baseURL, - defaultResolver) { - return { - url: new URL(specifier, parentModuleURL).href, - format: 'module' - }; -} -``` - -The `parentModuleURL` is provided as `undefined` when performing main Node.js -load itself. - -The default Node.js ES module resolution function is provided as a third -argument to the resolver for easy compatibility workflows. - -In addition to returning the resolved file URL value, the resolve hook also -returns a `format` property specifying the module format of the resolved -module. This can be one of the following: - -| `format` | Description | -| --- | --- | -| `'builtin'` | Load a Node.js builtin module | -| `'commonjs'` | Load a Node.js CommonJS module | -| `'dynamic'` | Use a [dynamic instantiate hook][] | -| `'json'` | Load a JSON file | -| `'module'` | Load a standard JavaScript module | -| `'wasm'` | Load a WebAssembly module | - -For example, a dummy loader to load JavaScript restricted to browser resolution -rules with only JS file extension and Node.js builtin modules support could -be written: - -```js -import path from 'path'; -import process from 'process'; -import Module from 'module'; -import { URL, pathToFileURL } from 'url'; - -const builtins = Module.builtinModules; -const JS_EXTENSIONS = new Set(['.js', '.mjs']); - -const baseURL = pathToFileURL(process.cwd()).href; - -/** - * @param {string} specifier - * @param {string} parentModuleURL - * @param {function} defaultResolver - */ -export async function resolve(specifier, - parentModuleURL = baseURL, - defaultResolver) { - if (builtins.includes(specifier)) { - return { - url: specifier, - format: 'builtin' - }; - } - if (/^\.{0,2}[/]/.test(specifier) !== true && !specifier.startsWith('file:')) { - // For node_modules support: - // return defaultResolver(specifier, parentModuleURL); - throw new Error( - `imports must begin with '/', './', or '../'; '${specifier}' does not`); - } - const resolved = new URL(specifier, parentModuleURL); - const ext = path.extname(resolved.pathname); - if (!JS_EXTENSIONS.has(ext)) { - throw new Error( - `Cannot load file with non-JavaScript file extension ${ext}.`); - } - return { - url: resolved.href, - format: 'module' - }; -} -``` - -With this loader, running: - -```console -NODE_OPTIONS='--experimental-modules --experimental-loader ./custom-loader.mjs' node x.js -``` - -would load the module `x.js` as an ES module with relative resolution support -(with `node_modules` loading skipped in this example). - diff --git a/esm/resolver_algorithm.md b/esm/resolver_algorithm.md index 4e69fe75..24708a8a 100644 --- a/esm/resolver_algorithm.md +++ b/esm/resolver_algorithm.md @@ -12,12 +12,13 @@ updates. In the following algorithms, all subroutine errors are propagated as errors of these top-level routines unless stated otherwise. -_isMain_ is **true** when resolving the Node.js application entry point. +_defaultEnv_ is the conditional environment name priority array, +`["node", "import"]`.
Resolver algorithm specification -**ESM_RESOLVE**(_specifier_, _parentURL_, _isMain_) +**ESM_RESOLVE**(_specifier_, _parentURL_) > 1. Let _resolvedURL_ be **undefined**. > 1. If _specifier_ is a valid URL, then @@ -38,7 +39,7 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. If the file at _resolvedURL_ does not exist, then > 1. Throw a _Module Not Found_ error. > 1. Set _resolvedURL_ to the real path of _resolvedURL_. -> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_, _isMain_). +> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_). > 1. Load _resolvedURL_ as module format, _format_. **PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_) @@ -47,9 +48,6 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. Let _packageSubpath_ be *undefined*. > 1. If _packageSpecifier_ is an empty string, then > 1. Throw an _Invalid Specifier_ error. -> 1. If _packageSpecifier_ does not start with _"@"_, then -> 1. Set _packageName_ to the substring of _packageSpecifier_ until the -> first _"/"_ separator or the end of the string. > 1. Otherwise, > 1. If _packageSpecifier_ does not contain a _"/"_ separator, then > 1. Throw an _Invalid Specifier_ error. @@ -63,8 +61,11 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. Set _packageSubpath_ to _"."_ concatenated with the substring of > _packageSpecifier_ from the position at the length of _packageName_. > 1. If _packageSubpath_ contains any _"."_ or _".."_ segments or percent -> encoded strings for _"/"_ or _"\\"_ then, +> encoded strings for _"/"_ or _"\\"_, then > 1. Throw an _Invalid Specifier_ error. +> 1. Set _selfUrl_ to the result of +> **SELF_REFERENCE_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_). +> 1. If _selfUrl_ isn't empty, return _selfUrl_. > 1. If _packageSubpath_ is _undefined_ and _packageName_ is a Node.js builtin > module, then > 1. Return the string _"node:"_ concatenated with _packageSpecifier_. @@ -88,19 +89,41 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. Return the URL resolution of _packageSubpath_ in _packageURL_. > 1. Throw a _Module Not Found_ error. +**SELF_REFERENCE_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_) + +> 1. Let _packageURL_ be the result of **READ_PACKAGE_SCOPE**(_parentURL_). +> 1. If _packageURL_ is **null**, then +> 1. Return **undefined**. +> 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_). +> 1. If _pjson_ does not include an _"exports"_ property, then +> 1. Return **undefined**. +> 1. If _pjson.name_ is equal to _packageName_, then +> 1. If _packageSubpath_ is _undefined_, then +> 1. Return the result of **PACKAGE_MAIN_RESOLVE**(_packageURL_, _pjson_). +> 1. Otherwise, +> 1. If _pjson_ is not **null** and _pjson_ has an _"exports"_ key, then +> 1. Let _exports_ be _pjson.exports_. +> 1. If _exports_ is not **null** or **undefined**, then +> 1. Return **PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _subpath_, +> _pjson.exports_). +> 1. Return the URL resolution of _subpath_ in _packageURL_. +> 1. Otherwise, return **undefined**. + **PACKAGE_MAIN_RESOLVE**(_packageURL_, _pjson_) > 1. If _pjson_ is **null**, then > 1. Throw a _Module Not Found_ error. > 1. If _pjson.exports_ is not **null** or **undefined**, then -> 1. If _pjson.exports_ is a String or Array, then -> 1. Return _PACKAGE_EXPORTS_TARGET_RESOLVE(packageURL, pjson.exports, -> "")_. -> 1. If _pjson.exports is an Object, then -> 1. If _pjson.exports_ contains a _"."_ property, then -> 1. Let _mainExport_ be the _"."_ property in _pjson.exports_. -> 1. Return _PACKAGE_EXPORTS_TARGET_RESOLVE(packageURL, mainExport, -> "")_. +> 1. If _exports_ is an Object with both a key starting with _"."_ and a key +> not starting with _"."_, throw an "Invalid Package Configuration" error. +> 1. If _pjson.exports_ is a String or Array, or an Object containing no +> keys starting with _"."_, then +> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, +> _pjson.exports_, _""_). +> 1. If _pjson.exports_ is an Object containing a _"."_ property, then +> 1. Let _mainExport_ be the _"."_ property in _pjson.exports_. +> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, +> _mainExport_, _""_). > 1. If _pjson.main_ is a String, then > 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and > _pjson.main_. @@ -114,13 +137,14 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. Return _legacyMainURL_. **PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _packagePath_, _exports_) - -> 1. If _exports_ is an Object, then +> 1. If _exports_ is an Object with both a key starting with _"."_ and a key not +> starting with _"."_, throw an "Invalid Package Configuration" error. +> 1. If _exports_ is an Object and all keys of _exports_ start with _"."_, then > 1. Set _packagePath_ to _"./"_ concatenated with _packagePath_. > 1. If _packagePath_ is a key of _exports_, then > 1. Let _target_ be the value of _exports\[packagePath\]_. > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, -> _""_). +> _""_, _defaultEnv_). > 1. Let _directoryKeys_ be the list of keys of _exports_ ending in > _"/"_, sorted by length descending. > 1. For each key _directory_ in _directoryKeys_, do @@ -129,10 +153,10 @@ _isMain_ is **true** when resolving the Node.js application entry point. > 1. Let _subpath_ be the substring of _target_ starting at the index > of the length of _directory_. > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, -> _subpath_). +> _subpath_, _defaultEnv_). > 1. Throw a _Module Not Found_ error. -**PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_) +**PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_, _env_) > 1. If _target_ is a String, then > 1. If _target_ does not start with _"./"_, throw a _Module Not Found_ @@ -148,31 +172,40 @@ _isMain_ is **true** when resolving the Node.js application entry point. > _subpath_ and _resolvedTarget_. > 1. If _resolved_ is contained in _resolvedTarget_, then > 1. Return _resolved_. +> 1. Otherwise, if _target_ is a non-null Object, then +> 1. If _exports_ contains any index property keys, as defined in ECMA-262 +> [6.1.7 Array Index][], throw an _Invalid Package Configuration_ error. +> 1. For each property _p_ of _target_, in object insertion order as, +> 1. If _env_ contains an entry for _p_, then +> 1. Let _targetValue_ be the value of the _p_ property in _target_. +> 1. Let _resolved_ be the result of **PACKAGE_EXPORTS_TARGET_RESOLVE** +> (_packageURL_, _targetValue_, _subpath_, _env_). +> 1. Assert: _resolved_ is a String. +> 1. Return _resolved_. > 1. Otherwise, if _target_ is an Array, then > 1. For each item _targetValue_ in _target_, do -> 1. If _targetValue_ is not a String, continue the loop. +> 1. If _targetValue_ is an Array, continue the loop. > 1. Let _resolved_ be the result of > **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _targetValue_, -> _subpath_), continuing the loop on abrupt completion. +> _subpath_, _env_), continuing the loop on abrupt completion. > 1. Assert: _resolved_ is a String. > 1. Return _resolved_. > 1. Throw a _Module Not Found_ error. -**ESM_FORMAT**(_url_, _isMain_) +**ESM_FORMAT**(_url_) -> 1. Assert: _url_ corresponds to an existing file. +> 1. Assert: _url_ corresponds to an existing file pathname. > 1. Let _pjson_ be the result of **READ_PACKAGE_SCOPE**(_url_). > 1. If _url_ ends in _".mjs"_, then > 1. Return _"module"_. > 1. If _url_ ends in _".cjs"_, then > 1. Return _"commonjs"_. > 1. If _pjson?.type_ exists and is _"module"_, then -> 1. If _isMain_ is **true** or _url_ ends in _".js"_, then +> 1. If _url_ ends in _".js"_ or lacks a file extension, then > 1. Return _"module"_. > 1. Throw an _Unsupported File Extension_ error. > 1. Otherwise, -> 1. If _isMain_ is **true** or _url_ ends in _".js"_, _".json"_ or -> _".node"_, then +> 1. If _url_ lacks a file extension, then > 1. Return _"commonjs"_. > 1. Throw an _Unsupported File Extension_ error. diff --git a/esm/supported.md b/esm/supported.md deleted file mode 100644 index 6de0dd61..00000000 --- a/esm/supported.md +++ /dev/null @@ -1,5 +0,0 @@ - -Only the CLI argument for the main entry point to the program can be an entry -point into an ESM graph. Dynamic import can also be used to create entry points -into ESM graphs at runtime. - diff --git a/esm/transpiler_loader.md b/esm/transpiler_loader.md new file mode 100644 index 00000000..5f865e30 --- /dev/null +++ b/esm/transpiler_loader.md @@ -0,0 +1,88 @@ + +Sources that are in formats Node.js doesn’t understand can be converted into +JavaScript using the [`transformSource` hook][]. Before that hook gets called, +however, other hooks need to tell Node.js not to throw an error on unknown file +types; and to tell Node.js how to load this new file type. + +This is obviously less performant than transpiling source files before running +Node.js; a transpiler loader should only be used for development and testing +purposes. + +```js +// coffeescript-loader.mjs +import { URL, pathToFileURL } from 'url'; +import CoffeeScript from 'coffeescript'; + +const baseURL = pathToFileURL(`${process.cwd()}/`).href; + +// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. +const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; + +export function resolve(specifier, context, defaultResolve) { + const { parentURL = baseURL } = context; + + // Node.js normally errors on unknown file extensions, so return a URL for + // specifiers ending in the CoffeeScript file extensions. + if (extensionsRegex.test(specifier)) { + return { + url: new URL(specifier, parentURL).href + }; + } + + // Let Node.js handle all other specifiers. + return defaultResolve(specifier, context, defaultResolve); +} + +export function getFormat(url, context, defaultGetFormat) { + // Now that we patched resolve to let CoffeeScript URLs through, we need to + // tell Node.js what format such URLs should be interpreted as. For the + // purposes of this loader, all CoffeeScript URLs are ES modules. + if (extensionsRegex.test(url)) { + return { + format: 'module' + }; + } + + // Let Node.js handle all other URLs. + return defaultGetFormat(url, context, defaultGetFormat); +} + +export function transformSource(source, context, defaultTransformSource) { + const { url, format } = context; + + if (extensionsRegex.test(url)) { + return { + source: CoffeeScript.compile(source, { bare: true }) + }; + } + + // Let Node.js handle all other sources. + return defaultTransformSource(source, context, defaultTransformSource); +} +``` + +```coffee +# main.coffee +import { scream } from './scream.coffee' +console.log scream 'hello, world' + +import { version } from 'process' +console.log "Brought to you by Node.js version #{version}" +``` + +```coffee +# scream.coffee +export scream = (str) -> str.toUpperCase() +``` + +With this loader, running: + +```console +node --experimental-loader ./coffeescript-loader.mjs main.coffee +``` + +Will cause `main.coffee` to be turned into JavaScript after its source code is +loaded from disk but before Node.js executes it; and so on for any `.coffee`, +`.litcoffee` or `.coffee.md` files referenced via `import` statements of any +loaded file. + diff --git a/esm/unsupported.md b/esm/unsupported.md deleted file mode 100644 index bd0aef8d..00000000 --- a/esm/unsupported.md +++ /dev/null @@ -1,5 +0,0 @@ - -| Feature | Reason | -| --- | --- | -| `require('./foo.mjs')` | ES Modules have differing resolution and timing, use dynamic import | - diff --git a/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md b/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md new file mode 100644 index 00000000..38217056 --- /dev/null +++ b/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md @@ -0,0 +1,29 @@ + +First, the hazard described in the previous section occurs when a package +contains both CommonJS and ES module sources and both sources are provided for +use in Node.js, either via separate main entry points or exported paths. A +package could instead be written where any version of Node.js receives only +CommonJS sources, and any separate ES module sources the package may contain +could be intended only for other environments such as browsers. Such a package +would be usable by any version of Node.js, since `import` can refer to CommonJS +files; but it would not provide any of the advantages of using ES module syntax. + +A package could also switch from CommonJS to ES module syntax in a breaking +change version bump. This has the obvious disadvantage that the newest version +of the package would only be usable in ES module-supporting versions of Node.js. + +Every pattern has tradeoffs, but there are two broad approaches that satisfy the +following conditions: + +1. The package is usable via both `require` and `import`. +1. The package is usable in both current Node.js and older versions of Node.js + that lack support for ES modules. +1. The package main entry point, e.g. `'pkg'` can be used by both `require` to + resolve to a CommonJS file and by `import` to resolve to an ES module file. + (And likewise for exported paths, e.g. `'pkg/feature'`.) +1. The package provides named exports, e.g. `import { name } from 'pkg'` rather + than `import pkg from 'pkg'; pkg.name`. +1. The package is potentially usable in other ES module environments such as + browsers. +1. The hazards described in the previous section are avoided or minimized. + diff --git a/events/capture_rejections_of_promises.md b/events/capture_rejections_of_promises.md new file mode 100644 index 00000000..9a448d3c --- /dev/null +++ b/events/capture_rejections_of_promises.md @@ -0,0 +1,52 @@ + +> Stability: 1 - captureRejections is experimental. + +Using `async` functions with event handlers is problematic, because it +can lead to an unhandled rejection in case of a thrown exception: + +```js +const ee = new EventEmitter(); +ee.on('something', async (value) => { + throw new Error('kaboom'); +}); +``` + +The `captureRejections` option in the `EventEmitter` constructor or the global +setting change this behavior, installing a `.then(undefined, handler)` +handler on the `Promise`. This handler routes the exception +asynchronously to the [`Symbol.for('nodejs.rejection')`][rejection] method +if there is one, or to [`'error'`][error] event handler if there is none. + +```js +const ee1 = new EventEmitter({ captureRejections: true }); +ee1.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee1.on('error', console.log); + +const ee2 = new EventEmitter({ captureRejections: true }); +ee2.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee2[Symbol.for('nodejs.rejection')] = console.log; +``` + +Setting `EventEmitter.captureRejections = true` will change the default for all +new instances of `EventEmitter`. + +```js +EventEmitter.captureRejections = true; +const ee1 = new EventEmitter(); +ee1.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee1.on('error', console.log); +``` + +The `'error'` events that are generated by the `captureRejections` behavior +do not have a catch handler to avoid infinite error loops: the +recommendation is to **not use `async` functions as `'error'` event handlers**. + diff --git a/events/class_eventemitter.md b/events/class_eventemitter.md index 110efa6b..d6bb9809 100644 --- a/events/class_eventemitter.md +++ b/events/class_eventemitter.md @@ -1,12 +1,20 @@ -`EventEmitter` 类由 `events` 模块定义: +`EventEmitter` 类由 `events` 模块定义和公开: ```js const EventEmitter = require('events'); ``` -当新增监听器时,会触发 `'newListener'` 事件;当移除已存在的监听器时,则触发 `'removeListener'` 事件。 +当添加新的监听器时,所有 `EventEmitter` 都会触发 `'newListener'` 事件;当移除现有的监听器时,则触发 `'removeListener'` 事件。 + +它支持以下选项: + +* `captureRejections` {boolean} 它可以[自动捕获 promise 的拒绝][capturerejections]。 默认值:`false`。 diff --git a/events/emitter_symbol_for_nodejs_rejection_err_eventname_args.md b/events/emitter_symbol_for_nodejs_rejection_err_eventname_args.md new file mode 100644 index 00000000..d328a975 --- /dev/null +++ b/events/emitter_symbol_for_nodejs_rejection_err_eventname_args.md @@ -0,0 +1,35 @@ + + +> Stability: 1 - captureRejections is experimental. + +* `err` Error +* `eventName` {string|symbol} +* `...args` {any} + +The `Symbol.for('nodejs.rejection')` method is called in case a +promise rejection happens when emitting an event and +[`captureRejections`][capturerejections] is enabled on the emitter. +It is possible to use [`events.captureRejectionSymbol`][rejectionsymbol] in +place of `Symbol.for('nodejs.rejection')`. + +```js +const { EventEmitter, captureRejectionSymbol } = require('events'); + +class MyClass extends EventEmitter { + constructor() { + super({ captureRejections: true }); + } + + [captureRejectionSymbol](err, event, ...args) { + console.log('rejection happened for', event, 'with', err, ...args); + this.destroy(err); + } + + destroy(err) { + // Tear the resource down here. + } +} +``` + diff --git a/events/error_events.md b/events/error_events.md index 8a689b60..1c82064d 100644 --- a/events/error_events.md +++ b/events/error_events.md @@ -24,3 +24,14 @@ myEmitter.emit('error', new Error('错误')); // 打印: 错误信息 ``` +通过使用符号 `errorMonitor` 安装监听器,可以监视 `'error'` 事件而不会消耗触发的错误。 + +```js +const myEmitter = new MyEmitter(); +myEmitter.on(EventEmitter.errorMonitor, (err) => { + MyMonitoringTool.log(err); +}); +myEmitter.emit('error', new Error('whoops!')); +// 仍然抛出并使 Node.js 奔溃。 +``` + diff --git a/events/eventemitter_errormonitor.md b/events/eventemitter_errormonitor.md new file mode 100644 index 00000000..f63e5d68 --- /dev/null +++ b/events/eventemitter_errormonitor.md @@ -0,0 +1,12 @@ + + +This symbol shall be used to install a listener for only monitoring `'error'` +events. Listeners installed using this symbol are called before the regular +`'error'` listeners are called. + +Installing a listener using this symbol does not change the behavior once an +`'error'` event is emitted, therefore the process will still crash if no +regular `'error'` listener is installed. + diff --git a/events/events_capturerejections.md b/events/events_capturerejections.md new file mode 100644 index 00000000..c1bee9b0 --- /dev/null +++ b/events/events_capturerejections.md @@ -0,0 +1,10 @@ + + +> Stability: 1 - captureRejections is experimental. + +Value: {boolean} + +Change the default `captureRejections` option on all new `EventEmitter` objects. + diff --git a/events/events_capturerejectionsymbol.md b/events/events_capturerejectionsymbol.md new file mode 100644 index 00000000..22bff5d6 --- /dev/null +++ b/events/events_capturerejectionsymbol.md @@ -0,0 +1,10 @@ + + +> Stability: 1 - captureRejections is experimental. + +Value: `Symbol.for('nodejs.rejection')` + +See how to write a custom [rejection handler][rejection]. + diff --git a/events/events_on_emitter_eventname.md b/events/events_on_emitter_eventname.md new file mode 100644 index 00000000..bcd3ac92 --- /dev/null +++ b/events/events_on_emitter_eventname.md @@ -0,0 +1,49 @@ + + +* `emitter` {EventEmitter} +* `eventName` {string|symbol} The name of the event being listened for +* Returns: {AsyncIterator} that iterates `eventName` events emitted by the `emitter` + +```js +const { on, EventEmitter } = require('events'); + +(async () => { + const ee = new EventEmitter(); + + // Emit later on + process.nextTick(() => { + ee.emit('foo', 'bar'); + ee.emit('foo', 42); + }); + + for await (const event of on(ee, 'foo')) { + // The execution of this inner block is synchronous and it + // processes one event at a time (even with await). Do not use + // if concurrent execution is required. + console.log(event); // prints ['bar'] [42] + } +})(); +``` + +Returns an `AsyncIterator` that iterates `eventName` events. It will throw +if the `EventEmitter` emits `'error'`. It removes all listeners when +exiting the loop. The `value` returned by each iteration is an array +composed of the emitted event arguments. + + + + + + + + + + + + + + + + diff --git a/fs/fs_chmod_path_mode_callback.md b/fs/fs_chmod_path_mode_callback.md index d0f39df7..535c001d 100644 --- a/fs/fs_chmod_path_mode_callback.md +++ b/fs/fs_chmod_path_mode_callback.md @@ -16,7 +16,7 @@ changes: --> * `path` {string|Buffer|URL} -* `mode` {integer} +* `mode` {string|integer} * `callback` {Function} * `err` {Error} diff --git a/fs/fs_chmodsync_path_mode.md b/fs/fs_chmodsync_path_mode.md index 4514b666..02f5be12 100644 --- a/fs/fs_chmodsync_path_mode.md +++ b/fs/fs_chmodsync_path_mode.md @@ -8,7 +8,7 @@ changes: --> * `path` {string|Buffer|URL} -* `mode` {integer} +* `mode` {string|integer} 有关详细信息,参阅此 API 的异步版本的文档:[`fs.chmod()`]。 diff --git a/fs/fs_close_fd_callback.md b/fs/fs_close_fd_callback.md index 18481cd5..331b9603 100644 --- a/fs/fs_close_fd_callback.md +++ b/fs/fs_close_fd_callback.md @@ -18,3 +18,5 @@ changes: 异步的 close(2)。 除了可能的异常,完成回调没有其他参数。 +通过任何其他 `fs` 操作在当前正在使用的任何文件描述符(`fd`)上调用 `fs.close()` 可能导致未定义的行为。 + diff --git a/fs/fs_closesync_fd.md b/fs/fs_closesync_fd.md index c90beedb..7d314146 100644 --- a/fs/fs_closesync_fd.md +++ b/fs/fs_closesync_fd.md @@ -6,3 +6,6 @@ added: v0.1.21 同步的 close(2)。返回 `undefined`。 +通过任何其他 `fs` 操作在当前正在使用的任何文件描述符(`fd`)上调用 `fs.closeSync()` 可能导致未定义的行为。 + + diff --git a/fs/fs_fchmod_fd_mode_callback.md b/fs/fs_fchmod_fd_mode_callback.md index bdbb7d2c..9caab74c 100644 --- a/fs/fs_fchmod_fd_mode_callback.md +++ b/fs/fs_fchmod_fd_mode_callback.md @@ -12,7 +12,7 @@ changes: --> * `fd` {integer} -* `mode` {integer} +* `mode` {string|integer} * `callback` {Function} * `err` {Error} diff --git a/fs/fs_fchmodsync_fd_mode.md b/fs/fs_fchmodsync_fd_mode.md index 61cb54e0..e4160bca 100644 --- a/fs/fs_fchmodsync_fd_mode.md +++ b/fs/fs_fchmodsync_fd_mode.md @@ -3,7 +3,7 @@ added: v0.4.7 --> * `fd` {integer} -* `mode` {integer} +* `mode` {string|integer} 同步的 fchmod(2)。返回 `undefined`。 diff --git a/fs/fs_mkdir_path_options_callback.md b/fs/fs_mkdir_path_options_callback.md index 4af66413..e22f3489 100644 --- a/fs/fs_mkdir_path_options_callback.md +++ b/fs/fs_mkdir_path_options_callback.md @@ -22,7 +22,7 @@ changes: * `path` {string|Buffer|URL} * `options` {Object|integer} * `recursive` {boolean} **默认值:** `false`。 - * `mode` {integer} Windows 上不支持。**默认值:** `0o777`。 + * `mode` {string|integer} Windows 上不支持。**默认值:** `0o777`。 * `callback` {Function} * `err` {Error} diff --git a/fs/fs_mkdirsync_path_options.md b/fs/fs_mkdirsync_path_options.md index 34552c57..90c9e9ef 100644 --- a/fs/fs_mkdirsync_path_options.md +++ b/fs/fs_mkdirsync_path_options.md @@ -14,7 +14,7 @@ changes: * `path` {string|Buffer|URL} * `options` {Object|integer} * `recursive` {boolean} **默认值:** `false`。 - * `mode` {integer} Windows 上不支持。**默认值:** `0o777`。 + * `mode` {string|integer} Windows 上不支持。**默认值:** `0o777`。 同步地创建目录。 返回 `undefined`。 diff --git a/fs/fs_open_path_flags_mode_callback.md b/fs/fs_open_path_flags_mode_callback.md index 207aaf94..b6dfaf25 100644 --- a/fs/fs_open_path_flags_mode_callback.md +++ b/fs/fs_open_path_flags_mode_callback.md @@ -15,7 +15,7 @@ changes: * `path` {string|Buffer|URL} * `flags` {string|number} 参阅[支持的文件系统标志][support of file system `flags`]。**默认值:** `'r'`。 -* `mode` {integer} **默认值:** `0o666`(可读写)。 +* `mode` {string|integer} **默认值:** `0o666`(可读写)。 * `callback` {Function} * `err` {Error} * `fd` {integer} diff --git a/fs/fs_opendir_path_options_callback.md b/fs/fs_opendir_path_options_callback.md index 43e638fd..cbef1891 100644 --- a/fs/fs_opendir_path_options_callback.md +++ b/fs/fs_opendir_path_options_callback.md @@ -1,10 +1,15 @@ * `path` {string|Buffer|URL} * `options` {Object} * `encoding` {string|null} **默认值:** `'utf8'`。 + * `bufferSize` {number} 当从目录读取时在内部缓冲的目录条目数。值越高,则性能越好,但内存占用更高。**默认值:** `32`。 * `callback` {Function} * `err` {Error} * `dir` {fs.Dir} diff --git a/fs/fs_opendirsync_path_options.md b/fs/fs_opendirsync_path_options.md index daf1f1b2..29dfc33b 100644 --- a/fs/fs_opendirsync_path_options.md +++ b/fs/fs_opendirsync_path_options.md @@ -1,10 +1,15 @@ * `path` {string|Buffer|URL} * `options` {Object} * `encoding` {string|null} **默认值:** `'utf8'`。 + * `bufferSize` {number} 当从目录读取时在内部缓冲的目录条目数。值越高,则性能越好,但内存占用更高。**默认值:** `32`。 * 返回: {fs.Dir} 同步地打开目录。 diff --git a/fs/fs_opensync_path_flags_mode.md b/fs/fs_opensync_path_flags_mode.md index f89fb8a8..a2a65575 100644 --- a/fs/fs_opensync_path_flags_mode.md +++ b/fs/fs_opensync_path_flags_mode.md @@ -15,7 +15,7 @@ changes: * `path` {string|Buffer|URL} * `flags` {string|number} **默认值:** `'r'`。参阅[支持的文件系统标志][support of file system `flags`]。 -* `mode` {integer} **默认值:** `0o666`。 +* `mode` {string|integer} **默认值:** `0o666`。 * 返回: {number} 返回表示文件描述符的整数。 diff --git a/fs/fs_rmdir_path_options_callback.md b/fs/fs_rmdir_path_options_callback.md index a0e4180c..936c58b9 100644 --- a/fs/fs_rmdir_path_options_callback.md +++ b/fs/fs_rmdir_path_options_callback.md @@ -1,6 +1,13 @@ * `path` {string|Buffer|URL} -* `mode` {integer} +* `mode` {string|integer} * 返回: {Promise} 更改文件的权限,然后在成功时解决 `Promise` 且不带参数。 diff --git a/fs/fspromises_mkdir_path_options.md b/fs/fspromises_mkdir_path_options.md index 1fa09a67..76b46984 100644 --- a/fs/fspromises_mkdir_path_options.md +++ b/fs/fspromises_mkdir_path_options.md @@ -5,7 +5,7 @@ added: v10.0.0 * `path` {string|Buffer|URL} * `options` {Object|integer} * `recursive` {boolean} **默认值:** `false`。 - * `mode` {integer} Windows 上不支持。**默认值:** `0o777`。 + * `mode` {string|integer} Windows 上不支持。**默认值:** `0o777`。 * 返回: {Promise} 异步地创建目录,然后在成功时解决 `Promise` 且不带参数。 diff --git a/fs/fspromises_open_path_flags_mode.md b/fs/fspromises_open_path_flags_mode.md index bf7e2348..76b17b1a 100644 --- a/fs/fspromises_open_path_flags_mode.md +++ b/fs/fspromises_open_path_flags_mode.md @@ -8,7 +8,7 @@ changes: * `path` {string|Buffer|URL} * `flags` {string|number} 参阅[支持的文件系统标志][support of file system `flags`]。**默认值:** `'r'`。 -* `mode` {integer} **默认值:** `0o666`(可读写)。 +* `mode` {string|integer} **默认值:** `0o666`(可读写)。 * 返回: {Promise} 异步地打开文件并返回一个 `Promise`,当解决时会带上一个 `FileHandle` 对象。 diff --git a/fs/fspromises_opendir_path_options.md b/fs/fspromises_opendir_path_options.md index 3069d8be..651a85b1 100644 --- a/fs/fspromises_opendir_path_options.md +++ b/fs/fspromises_opendir_path_options.md @@ -1,10 +1,15 @@ * `path` {string|Buffer|URL} * `options` {Object} * `encoding` {string|null} **默认值:** `'utf8'`。 + * `bufferSize` {number} 当从目录读取时在内部缓冲的目录条目数。值越高,则性能越好,但内存占用更高。**默认值:** `32`。 * 返回: {Promise} 包含 {fs.Dir}。 异步地打开目录。 diff --git a/fs/fspromises_rmdir_path_options.md b/fs/fspromises_rmdir_path_options.md index c5189c76..c981fbf3 100644 --- a/fs/fspromises_rmdir_path_options.md +++ b/fs/fspromises_rmdir_path_options.md @@ -1,6 +1,13 @@ -* `socket` {net.Socket} +* `socket` {stream.Duplex} 当 `socket` 与请求分离并且可以由 `Agent` 保留时调用。 默认行为是: @@ -16,4 +16,6 @@ return true; 此方法可以由特定的 `Agent` 子类重写。 如果此方法返回一个假值,则将销毁套接字而不是将其保留以用于下一个请求。 +`socket` 参数可以是 {net.Socket}({stream.Duplex} 的子类)的实例。 + diff --git a/http/agent_reusesocket_socket_request.md b/http/agent_reusesocket_socket_request.md index 00edfaf3..0707b3ba 100644 --- a/http/agent_reusesocket_socket_request.md +++ b/http/agent_reusesocket_socket_request.md @@ -2,7 +2,7 @@ added: v8.1.0 --> -* `socket` {net.Socket} +* `socket` {stream.Duplex} * `request` {http.ClientRequest} 由于 keep-alive 选项而在持久化后将 `socket` 附加到 `request` 时调用。 @@ -14,3 +14,5 @@ socket.ref(); 此方法可以由特定的 `Agent` 子类重写。 +`socket` 参数可以是 {net.Socket}({stream.Duplex} 的子类)的实例。 + diff --git a/http/class_http_incomingmessage.md b/http/class_http_incomingmessage.md index f91bf17e..f08dc512 100644 --- a/http/class_http_incomingmessage.md +++ b/http/class_http_incomingmessage.md @@ -1,5 +1,9 @@ * 继承自: {stream.Readable} diff --git a/http/event_clienterror.md b/http/event_clienterror.md index 74a24932..0d7749a1 100644 --- a/http/event_clienterror.md +++ b/http/event_clienterror.md @@ -18,12 +18,14 @@ changes: --> * `exception` {Error} -* `socket` {net.Socket} +* `socket` {stream.Duplex} 如果客户端连接触发 `'error'` 事件,则会在此处转发。 此事件的监听器负责关闭或销毁底层套接字。 例如,用户可能希望使用自定义 HTTP 响应更优雅地关闭套接字,而不是突然切断连接。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + 默认行为是尝试使用 HTTP `400 Bad Request` 关闭套接字、或者在 [`HPE_HEADER_OVERFLOW`] 错误的情况下尝试关闭 HTTP `431 Request Header Fields Too Large`。 如果套接字不可写,则会被立即销毁。 diff --git a/http/event_connect.md b/http/event_connect.md index 1ebe323c..366c1068 100644 --- a/http/event_connect.md +++ b/http/event_connect.md @@ -3,12 +3,14 @@ added: v0.7.0 --> * `response` {http.IncomingMessage} -* `socket` {net.Socket} +* `socket` {stream.Duplex} * `head` {Buffer} 每次服务器使用 `CONNECT` 方法响应请求时都会触发。 如果未监听此事件,则接收 `CONNECT` 方法的客户端将关闭其连接。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + 客户端和服务器对演示了如何监听 `'connect'` 事件: ```js diff --git a/http/event_connect_1.md b/http/event_connect_1.md index 8665dfa0..4d0e791e 100644 --- a/http/event_connect_1.md +++ b/http/event_connect_1.md @@ -3,11 +3,13 @@ added: v0.7.0 --> * `request` {http.IncomingMessage} HTTP 请求的参数,与 [`'request'`] 事件中的一样。 -* `socket` {net.Socket} 服务器和客户端之间的网络套接字。 +* `socket` {stream.Duplex} 服务器和客户端之间的网络套接字。 * `head` {Buffer} 隧道流的第一个数据包(可能为空)。 每次客户端请求 HTTP `CONNECT` 方法时触发。 如果未监听此事件,则请求 `CONNECT` 方法的客户端将关闭其连接。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + 触发此事件后,请求的套接字将没有 `'data'` 事件监听器,这意味着它需要绑定才能处理发送到该套接字上的服务器的数据。 diff --git a/http/event_connection.md b/http/event_connection.md index a2c738a3..fe782cf5 100644 --- a/http/event_connection.md +++ b/http/event_connection.md @@ -2,7 +2,7 @@ added: v0.1.0 --> -* `socket` {net.Socket} +* `socket` {stream.Duplex} 建立新的 TCP 流时会触发此事件。 `socket` 通常是 [`net.Socket`] 类型的对象。 @@ -15,3 +15,5 @@ added: v0.1.0 如果在此处调用 `socket.setTimeout()`,则当套接字已提供请求时(如果 `server.keepAliveTimeout` 为非零),超时将会被 `server.keepAliveTimeout` 替换。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + diff --git a/http/event_socket.md b/http/event_socket.md index ee1650d0..19fbb383 100644 --- a/http/event_socket.md +++ b/http/event_socket.md @@ -2,7 +2,7 @@ added: v0.5.3 --> -* `socket` {net.Socket} +* `socket` {stream.Duplex} -将套接字分配给此请求后触发。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 diff --git a/http/event_upgrade.md b/http/event_upgrade.md index d52ea297..2ef1a644 100644 --- a/http/event_upgrade.md +++ b/http/event_upgrade.md @@ -3,12 +3,14 @@ added: v0.1.94 --> * `response` {http.IncomingMessage} -* `socket` {net.Socket} +* `socket` {stream.Duplex} * `head` {Buffer} 每次服务器响应升级请求时发出。 如果未监听此事件且响应状态码为 `101 Switching Protocols`,则接收升级响应头的客户端将关闭其连接。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + 客户端服务器对,演示如何监听 `'upgrade'` 事件。 ```js diff --git a/http/event_upgrade_1.md b/http/event_upgrade_1.md index 14bdbff6..caacb417 100644 --- a/http/event_upgrade_1.md +++ b/http/event_upgrade_1.md @@ -8,7 +8,7 @@ changes: --> * `request` {http.IncomingMessage} HTTP 请求的参数,与 [`'request'`] 事件中的一样。 -* `socket` {net.Socket} 服务器与客户端之间的网络套接字。 +* `socket` {stream.Duplex} 服务器与客户端之间的网络套接字。 * `head` {Buffer} 升级后的流的第一个数据包(可能为空)。 每次客户端请求 HTTP 升级时发出。 @@ -16,3 +16,5 @@ changes: 触发此事件后,请求的套接字将没有 `'data'` 事件监听器,这意味着它需要绑定才能处理发送到该套接字上的服务器的数据。 +此事件保证传入 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + diff --git a/http/message_socket.md b/http/message_socket.md index 417e33c9..169a977a 100644 --- a/http/message_socket.md +++ b/http/message_socket.md @@ -2,10 +2,12 @@ added: v0.3.0 --> -* {net.Socket} +* {stream.Duplex} 与连接关联的 [`net.Socket`] 对象。 通过 HTTPS 的支持,使用 [`request.socket.getPeerCertificate()`] 获取客户端的身份验证详细信息。 +此属性保证是 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + diff --git a/http/message_url.md b/http/message_url.md index 36621987..fed4a010 100644 --- a/http/message_url.md +++ b/http/message_url.md @@ -7,7 +7,7 @@ added: v0.1.90 仅对从 [`http.Server`] 获取的请求有效。 请求的 URL 字符串。 -它仅包含实际 HTTP 请求中存在的 URL。 +它仅包含实际的 HTTP 请求中存在的 URL。 如果请求是: ```txt @@ -16,50 +16,30 @@ Accept: text/plain\r\n \r\n ``` -则 `request.url` 将是: +要将 URL 解析成各个部分: - ```js -'/status?name=ryan' +new URL(request.url, `http://${request.headers.host}`); ``` -要将 url 解析为其各个部分,可以使用 `require('url').parse(request.url)`: - -```txt -$ node -> require('url').parse('/status?name=ryan') -Url { - protocol: null, - slashes: null, - auth: null, - host: null, - port: null, - hostname: null, - hash: null, - search: '?name=ryan', - query: 'name=ryan', - pathname: '/status', - path: '/status?name=ryan', - href: '/status?name=ryan' } -``` - -要从查询字符串中提取参数,可以使用 `require('querystring').parse` 函数,或者可以将 `true` 作为第二个参数传递给 `require('url').parse`: +当 `request.url` 是 `'/status?name=ryan'` 且 `request.headers.host` 是 `'localhost:3000'` 时: ```console $ node -> require('url').parse('/status?name=ryan', true) -Url { - protocol: null, - slashes: null, - auth: null, - host: null, - port: null, - hostname: null, - hash: null, - search: '?name=ryan', - query: { name: 'ryan' }, +> new URL(request.url, request.headers.host) +URL { + href: 'http://localhost:3000/status?name=ryan', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', pathname: '/status', - path: '/status?name=ryan', - href: '/status?name=ryan' } + search: '?name=ryan', + searchParams: URLSearchParams { 'name' => 'ryan' }, + hash: '' +} ``` diff --git a/http/request_connection.md b/http/request_connection.md index d360af87..8865c333 100644 --- a/http/request_connection.md +++ b/http/request_connection.md @@ -2,7 +2,7 @@ added: v0.3.0 --> -* {net.Socket} +* {stream.Duplex} 请参阅 [`request.socket`]。 diff --git a/http/request_finished.md b/http/request_finished.md index fff5cef8..849f0524 100644 --- a/http/request_finished.md +++ b/http/request_finished.md @@ -1,7 +1,10 @@ +> Stability: 0 - Deprecated. Use [`request.writableEnded`][]. + * {boolean} 如果调用了 [`request.end()`],则 `request.finished` 属性将为 `true`。 diff --git a/http/request_reusedsocket.md b/http/request_reusedsocket.md new file mode 100644 index 00000000..20bfb6c8 --- /dev/null +++ b/http/request_reusedsocket.md @@ -0,0 +1,55 @@ + + + +* {boolean} Whether the request is send through a reused socket. + +When sending request through a keep-alive enabled agent, the underlying socket +might be reused. But if server closes connection at unfortunate time, client +may run into a 'ECONNRESET' error. + +```js +const http = require('http'); + +// Server has a 5 seconds keep-alive timeout by default +http + .createServer((req, res) => { + res.write('hello\n'); + res.end(); + }) + .listen(3000); + +setInterval(() => { + // Adapting a keep-alive agent + http.get('http://localhost:3000', { agent }, (res) => { + res.on('data', (data) => { + // Do nothing + }); + }); +}, 5000); // Sending request on 5s interval so it's easy to hit idle timeout +``` + +By marking a request whether it reused socket or not, we can do +automatic error retry base on it. + +```js +const http = require('http'); +const agent = new http.Agent({ keepAlive: true }); + +function retriableRequest() { + const req = http + .get('http://localhost:3000', { agent }, (res) => { + // ... + }) + .on('error', (err) => { + // Check if retry is needed + if (req.reusedSocket && err.code === 'ECONNRESET') { + retriableRequest(); + } + }); +} + +retriableRequest(); +``` + diff --git a/http/request_socket.md b/http/request_socket.md index ff849e62..a1a39238 100644 --- a/http/request_socket.md +++ b/http/request_socket.md @@ -2,7 +2,7 @@ added: v0.3.0 --> -* {net.Socket} +* {stream.Duplex} 指向底层套接字。 通常用户无需访问此属性。 @@ -24,3 +24,6 @@ req.once('response', (res) => { // 使用响应对象。 }); ``` + +此属性保证是 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + diff --git a/http/response_connection.md b/http/response_connection.md index 22a3dae3..abd7cce5 100644 --- a/http/response_connection.md +++ b/http/response_connection.md @@ -2,7 +2,7 @@ added: v0.3.0 --> -* {net.Socket} +* {stream.Duplex} 参阅 [`response.socket`]。 diff --git a/http/response_cork.md b/http/response_cork.md new file mode 100644 index 00000000..23a2c363 --- /dev/null +++ b/http/response_cork.md @@ -0,0 +1,6 @@ + + +See [`writable.cork()`][]. + diff --git a/http/response_finished.md b/http/response_finished.md index 8a38d8f3..d05bafb7 100644 --- a/http/response_finished.md +++ b/http/response_finished.md @@ -1,7 +1,10 @@ +> Stability: 0 - Deprecated. Use [`response.writableEnded`][]. + * {boolean} 如果调用了 [`response.end()`],则 `response.finished` 属性将会是 `true`。 diff --git a/http/response_socket.md b/http/response_socket.md index e9aa6a20..12b5c013 100644 --- a/http/response_socket.md +++ b/http/response_socket.md @@ -2,7 +2,7 @@ added: v0.3.0 --> -* {net.Socket} +* {stream.Duplex} 指向底层的套接字。 通常用户不需要访问此属性。 @@ -20,3 +20,5 @@ const server = http.createServer((req, res) => { }).listen(3000); ``` +此属性保证是 {net.Socket} 类({stream.Duplex} 的子类)的实例,除非用户指定了 {net.Socket} 以外的套接字类型。 + diff --git a/http/response_uncork.md b/http/response_uncork.md new file mode 100644 index 00000000..2e7aaa5c --- /dev/null +++ b/http/response_uncork.md @@ -0,0 +1,6 @@ + + +See [`writable.uncork()`][]. + diff --git a/http2/collecting_http_2_performance_metrics.md b/http2/collecting_http_2_performance_metrics.md index b50d542c..2801c9bc 100644 --- a/http2/collecting_http_2_performance_metrics.md +++ b/http2/collecting_http_2_performance_metrics.md @@ -109,5 +109,6 @@ following additional properties: + diff --git a/http2/event_frameerror_1.md b/http2/event_frameerror_1.md index 0276383b..c6514aea 100644 --- a/http2/event_frameerror_1.md +++ b/http2/event_frameerror_1.md @@ -2,6 +2,11 @@ added: v8.4.0 --> +* `type` {integer} The frame type. +* `code` {integer} The error code. +* `id` {integer} The stream id (or `0` if the frame isn't associated with a + stream). + The `'frameError'` event is emitted when an error occurs while attempting to send a frame. When invoked, the handler function will receive an integer argument identifying the frame type, and an integer argument identifying the diff --git a/http2/event_timeout_1.md b/http2/event_timeout_1.md index c8b62901..b0000b45 100644 --- a/http2/event_timeout_1.md +++ b/http2/event_timeout_1.md @@ -5,4 +5,5 @@ added: v8.4.0 The `'timeout'` event is emitted after no activity is received for this `Http2Stream` within the number of milliseconds set using `http2stream.setTimeout()`. +Its listener does not expect any arguments. diff --git a/http2/event_trailers.md b/http2/event_trailers.md index 4672a136..04e52670 100644 --- a/http2/event_trailers.md +++ b/http2/event_trailers.md @@ -2,6 +2,9 @@ added: v8.4.0 --> +* `headers` {HTTP/2 Headers Object} An object describing the headers +* `flags` {number} The associated numeric flags + The `'trailers'` event is emitted when a block of headers associated with trailing header fields is received. The listener callback is passed the [HTTP/2 Headers Object][] and flags associated with the headers. diff --git a/http2/http2_createsecureserver_options_onrequesthandler.md b/http2/http2_createsecureserver_options_onrequesthandler.md index f6cafb45..303bec5a 100644 --- a/http2/http2_createsecureserver_options_onrequesthandler.md +++ b/http2/http2_createsecureserver_options_onrequesthandler.md @@ -1,6 +1,12 @@ - -* `settings` {HTTP/2 Settings Object} - -Updates the current local settings for this `Http2Session` and sends a new -`SETTINGS` frame to the connected HTTP/2 peer. - -Once called, the `http2session.pendingSettingsAck` property will be `true` -while the session is waiting for the remote peer to acknowledge the new -settings. - -The new settings will not become effective until the `SETTINGS` acknowledgment -is received and the `'localSettings'` event is emitted. It is possible to send -multiple `SETTINGS` frames while acknowledgment is still pending. - diff --git a/http2/response_finished.md b/http2/response_finished.md index cc47c215..ba2a45fd 100644 --- a/http2/response_finished.md +++ b/http2/response_finished.md @@ -1,7 +1,10 @@ +> Stability: 0 - Deprecated. Use [`response.writableEnded`][]. + * {boolean} Boolean value that indicates whether the response has completed. Starts diff --git a/http2/settings_object.md b/http2/settings_object.md index 4585b3d5..a8bccf6d 100644 --- a/http2/settings_object.md +++ b/http2/settings_object.md @@ -20,7 +20,7 @@ properties. header compression. The minimum allowed value is 0. The maximum allowed value is 232-1. **Default:** `4,096 octets`. * `enablePush` {boolean} Specifies `true` if HTTP/2 Push Streams are to be - permitted on the `Http2Session` instances. + permitted on the `Http2Session` instances. **Default:** `true`. * `initialWindowSize` {number} Specifies the *senders* initial window size for stream-level flow control. The minimum allowed value is 0. The maximum allowed value is 232-1. **Default:** `65,535 bytes`. @@ -40,6 +40,7 @@ properties. Protocol" defined by [RFC 8441][] is to be enabled. This setting is only meaningful if sent by the server. Once the `enableConnectProtocol` setting has been enabled for a given `Http2Session`, it cannot be disabled. + **Default:** `false`. All additional properties on the settings object are ignored. diff --git a/https/event_keylog.md b/https/event_keylog.md new file mode 100644 index 00000000..ae5b216c --- /dev/null +++ b/https/event_keylog.md @@ -0,0 +1,24 @@ + + +* `line` {Buffer} Line of ASCII text, in NSS `SSLKEYLOGFILE` format. +* `tlsSocket` {tls.TLSSocket} The `tls.TLSSocket` instance on which it was + generated. + +The `keylog` event is emitted when key material is generated or received by a +connection managed by this agent (typically before handshake has completed, but +not necessarily). This keying material can be stored for debugging, as it +allows captured TLS traffic to be decrypted. It may be emitted multiple times +for each socket. + +A typical use case is to append received lines to a common text file, which is +later used by software (such as Wireshark) to decrypt the traffic: + +```js +// ... +https.globalAgent.on('keylog', (line, tlsSocket) => { + fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 }); +}); +``` + diff --git a/inspector/event_lt_inspector_protocol_method_gt.md b/inspector/event_inspector_protocol_method.md similarity index 100% rename from inspector/event_lt_inspector_protocol_method_gt.md rename to inspector/event_inspector_protocol_method.md diff --git a/inspector/inspector_url.md b/inspector/inspector_url.md index 8817376f..24719d7a 100644 --- a/inspector/inspector_url.md +++ b/inspector/inspector_url.md @@ -3,3 +3,18 @@ Return the URL of the active inspector, or `undefined` if there is none. +```console +$ node --inspect -p 'inspector.url()' +Debugger listening on ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34 +For help see https://nodejs.org/en/docs/inspector +ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34 + +$ node --inspect=localhost:3000 -p 'inspector.url()' +Debugger listening on ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a +For help see https://nodejs.org/en/docs/inspector +ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a + +$ node -p 'inspector.url()' +undefined +``` + diff --git a/modules/all_together.md b/modules/all_together.md index dda9c430..9a991961 100644 --- a/modules/all_together.md +++ b/modules/all_together.md @@ -16,8 +16,9 @@ require(X) from module at path Y a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) c. THROW "not found" -4. LOAD_NODE_MODULES(X, dirname(Y)) -5. THROW "not found" +4. LOAD_SELF_REFERENCE(X, dirname(Y)) +5. LOAD_NODE_MODULES(X, dirname(Y)) +7. THROW "not found" LOAD_AS_FILE(X) 1. If X is a file, load X as JavaScript text. STOP @@ -57,9 +58,17 @@ NODE_MODULES_PATHS(START) c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS + +LOAD_SELF_REFERENCE(X, START) +1. Find the closest package scope to START. +2. If no scope was found, return. +3. If the `package.json` has no "exports", return. +4. If the name in `package.json` isn't a prefix of X, throw "not found". +5. Otherwise, resolve the remainder of X relative to this package as if it + was loaded via `LOAD_NODE_MODULES` with a name in `package.json`. ``` -如果启用了 `--experimental-exports`,则 Node.js 允许通过 `LOAD_NODE_MODULES` 加载的包显式地声明要导入的文件路径以及如何解析它们。 +Node.js 允许通过 `LOAD_NODE_MODULES` 加载的包显式地声明要导入的文件路径以及如何解析它们。 这扩展了使用 `main` 字段已经拥有的控件包。 启用此功能后,`LOAD_NODE_MODULES` 将更改为: @@ -70,8 +79,8 @@ LOAD_NODE_MODULES(X, START) 1. let DIRS = NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. let FILE_PATH = RESOLVE_BARE_SPECIFIER(DIR, X) - a. LOAD_AS_FILE(FILE_PATH) - b. LOAD_AS_DIRECTORY(FILE_PATH) + b. LOAD_AS_FILE(FILE_PATH) + c. LOAD_AS_DIRECTORY(FILE_PATH) RESOLVE_BARE_SPECIFIER(DIR, X) 1. Try to interpret X as a combination of name and subpath where the name @@ -79,12 +88,18 @@ RESOLVE_BARE_SPECIFIER(DIR, X) 2. If X matches this pattern and DIR/name/package.json is a file: a. Parse DIR/name/package.json, and look for "exports" field. b. If "exports" is null or undefined, GOTO 3. - c. Find the longest key in "exports" that the subpath starts with. - d. If no such key can be found, throw "not found". - e. let RESOLVED_URL = + c. If "exports" is an object with some keys starting with "." and some keys + not starting with ".", throw "invalid config". + d. If "exports" is a string, or object with no keys starting with ".", treat + it as having that value as its "." object property. + e. If subpath is "." and "exports" does not have a "." entry, GOTO 3. + f. Find the longest key in "exports" that the subpath starts with. + g. If no such key can be found, throw "not found". + h. let RESOLVED_URL = PACKAGE_EXPORTS_TARGET_RESOLVE(pathToFileURL(DIR/name), exports[key], - subpath.slice(key.length)), as defined in the esm resolver. - f. return fileURLToPath(RESOLVED_URL) + subpath.slice(key.length), ["node", "require"]), as defined in the ESM + resolver. + i. return fileURLToPath(RESOLVED_URL) 3. return DIR/X ``` diff --git a/n-api/custom_asynchronous_operations.md b/n-api/custom_asynchronous_operations.md index 127065a5..c4462aa7 100644 --- a/n-api/custom_asynchronous_operations.md +++ b/n-api/custom_asynchronous_operations.md @@ -1,3 +1,4 @@ + The simple asynchronous work APIs above may not be appropriate for every scenario. When using any other asynchronous mechanism, the following APIs are necessary to ensure an asynchronous operation is properly tracked by diff --git a/n-api/error_handling.md b/n-api/error_handling.md index 5f5ce806..d88859d2 100644 --- a/n-api/error_handling.md +++ b/n-api/error_handling.md @@ -1,3 +1,4 @@ + N-API uses both return values and JavaScript exceptions for error handling. The following sections explain the approach for each case. diff --git a/n-api/exceptions.md b/n-api/exceptions.md index 47342cb7..ab516313 100644 --- a/n-api/exceptions.md +++ b/n-api/exceptions.md @@ -1,3 +1,4 @@ + Any N-API function call may result in a pending JavaScript exception. This is obviously the case for any function that may cause the execution of JavaScript, but N-API specifies that an exception may be pending diff --git a/n-api/napi_acquire_threadsafe_function.md b/n-api/napi_acquire_threadsafe_function.md index 8bace032..3ca25845 100644 --- a/n-api/napi_acquire_threadsafe_function.md +++ b/n-api/napi_acquire_threadsafe_function.md @@ -10,7 +10,7 @@ napi_acquire_threadsafe_function(napi_threadsafe_function func); ``` * `[in] func`: The asynchronous thread-safe JavaScript function to start making -use of. + use of. A thread should call this API before passing `func` to any other thread-safe function APIs to indicate that it will be making use of `func`. This prevents diff --git a/n-api/napi_adjust_external_memory.md b/n-api/napi_adjust_external_memory.md index 7d59a846..185746ed 100644 --- a/n-api/napi_adjust_external_memory.md +++ b/n-api/napi_adjust_external_memory.md @@ -10,8 +10,8 @@ NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] change_in_bytes`: The change in externally allocated memory that is -kept alive by JavaScript objects. +* `[in] change_in_bytes`: The change in externally allocated memory that is kept + alive by JavaScript objects. * `[out] result`: The adjusted value Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_call_function.md b/n-api/napi_call_function.md index a940622f..17c7af05 100644 --- a/n-api/napi_call_function.md +++ b/n-api/napi_call_function.md @@ -14,11 +14,10 @@ NAPI_EXTERN napi_status napi_call_function(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] recv`: The `this` object passed to the called function. -* `[in] func`: `napi_value` representing the JavaScript function -to be invoked. +* `[in] func`: `napi_value` representing the JavaScript function to be invoked. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of `napi_values` representing JavaScript values passed -in as arguments to the function. +* `[in] argv`: Array of `napi_values` representing JavaScript values passed in + as arguments to the function. * `[out] result`: `napi_value` representing the JavaScript object returned. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_call_threadsafe_function.md b/n-api/napi_call_threadsafe_function.md index b995a55f..d5e9c7fa 100644 --- a/n-api/napi_call_threadsafe_function.md +++ b/n-api/napi_call_threadsafe_function.md @@ -13,11 +13,11 @@ napi_call_threadsafe_function(napi_threadsafe_function func, * `[in] func`: The asynchronous thread-safe JavaScript function to invoke. * `[in] data`: Data to send into JavaScript via the callback `call_js_cb` -provided during the creation of the thread-safe JavaScript function. + provided during the creation of the thread-safe JavaScript function. * `[in] is_blocking`: Flag whose value can be either `napi_tsfn_blocking` to -indicate that the call should block if the queue is full or -`napi_tsfn_nonblocking` to indicate that the call should return immediately with -a status of `napi_queue_full` whenever the queue is full. + indicate that the call should block if the queue is full or + `napi_tsfn_nonblocking` to indicate that the call should return immediately + with a status of `napi_queue_full` whenever the queue is full. This API will return `napi_closing` if `napi_release_threadsafe_function()` was called with `abort` set to `napi_tsfn_abort` from any thread. The value is only diff --git a/n-api/napi_create_async_work.md b/n-api/napi_create_async_work.md index e6f1eed9..9d6cf69f 100644 --- a/n-api/napi_create_async_work.md +++ b/n-api/napi_create_async_work.md @@ -20,18 +20,18 @@ napi_status napi_create_async_work(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] async_resource`: An optional object associated with the async work that will be passed to possible `async_hooks` [`init` hooks][]. -* `[in] async_resource_name`: Identifier for the kind of resource that is -being provided for diagnostic information exposed by the `async_hooks` API. -* `[in] execute`: The native function which should be called to execute -the logic asynchronously. The given function is called from a worker pool -thread and can execute in parallel with the main event loop thread. +* `[in] async_resource_name`: Identifier for the kind of resource that is being + provided for diagnostic information exposed by the `async_hooks` API. +* `[in] execute`: The native function which should be called to execute the + logic asynchronously. The given function is called from a worker pool thread + and can execute in parallel with the main event loop thread. * `[in] complete`: The native function which will be called when the -asynchronous logic is completed or is cancelled. The given function is called -from the main event loop thread. + asynchronous logic is completed or is cancelled. The given function is called + from the main event loop thread. * `[in] data`: User-provided data context. This will be passed back into the -execute and complete functions. + execute and complete functions. * `[out] result`: `napi_async_work*` which is the handle to the newly created -async work. + async work. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_buffer_copy.md b/n-api/napi_create_buffer_copy.md index 442eb330..0e0f7030 100644 --- a/n-api/napi_create_buffer_copy.md +++ b/n-api/napi_create_buffer_copy.md @@ -12,8 +12,8 @@ napi_status napi_create_buffer_copy(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] size`: Size in bytes of the input buffer (should be the same as the - size of the new buffer). +* `[in] size`: Size in bytes of the input buffer (should be the same as the size + of the new buffer). * `[in] data`: Raw pointer to the underlying buffer to copy from. * `[out] result_data`: Pointer to the new `Buffer`'s underlying data buffer. * `[out] result`: A `napi_value` representing a `node::Buffer`. diff --git a/n-api/napi_create_error.md b/n-api/napi_create_error.md index 6b524ad8..ffad202f 100644 --- a/n-api/napi_create_error.md +++ b/n-api/napi_create_error.md @@ -11,10 +11,10 @@ NAPI_EXTERN napi_status napi_create_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_external.md b/n-api/napi_create_external.md index 489af1c7..0ab92b00 100644 --- a/n-api/napi_create_external.md +++ b/n-api/napi_create_external.md @@ -13,10 +13,10 @@ napi_status napi_create_external(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] data`: Raw pointer to the external data. -* `[in] finalize_cb`: Optional callback to call when the external value -is being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the external value is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing an external value. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_external_arraybuffer.md b/n-api/napi_create_external_arraybuffer.md index 58618029..ed7df023 100644 --- a/n-api/napi_create_external_arraybuffer.md +++ b/n-api/napi_create_external_arraybuffer.md @@ -15,12 +15,12 @@ napi_create_external_arraybuffer(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] external_data`: Pointer to the underlying byte buffer of the -`ArrayBuffer`. + `ArrayBuffer`. * `[in] byte_length`: The length in bytes of the underlying buffer. -* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is -being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing a JavaScript `ArrayBuffer`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_external_buffer.md b/n-api/napi_create_external_buffer.md index 1a1488b4..7594b47a 100644 --- a/n-api/napi_create_external_buffer.md +++ b/n-api/napi_create_external_buffer.md @@ -13,13 +13,13 @@ napi_status napi_create_external_buffer(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] length`: Size in bytes of the input buffer (should be the same as -the size of the new buffer). +* `[in] length`: Size in bytes of the input buffer (should be the same as the + size of the new buffer). * `[in] data`: Raw pointer to the underlying buffer to copy from. -* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is -being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing a `node::Buffer`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_function.md b/n-api/napi_create_function.md index 0d04ebe8..607608f9 100644 --- a/n-api/napi_create_function.md +++ b/n-api/napi_create_function.md @@ -14,15 +14,15 @@ napi_status napi_create_function(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] utf8Name`: The name of the function encoded as UTF8. This is visible -within JavaScript as the new function object's `name` property. -* `[in] length`: The length of the `utf8name` in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + within JavaScript as the new function object's `name` property. +* `[in] length`: The length of the `utf8name` in bytes, or `NAPI_AUTO_LENGTH` if + it is null-terminated. * `[in] cb`: The native function which should be called when this function -object is invoked. + object is invoked. * `[in] data`: User-provided data context. This will be passed back into the -function when invoked later. + function when invoked later. * `[out] result`: `napi_value` representing the JavaScript function object for -the newly created function. + the newly created function. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_function_1.md b/n-api/napi_create_function_1.md deleted file mode 100644 index c21aa30c..00000000 --- a/n-api/napi_create_function_1.md +++ /dev/null @@ -1,66 +0,0 @@ - -```C -napi_status napi_create_function(napi_env env, - const char* utf8name, - napi_callback cb, - void* data, - napi_value* result); -``` - -- `[in] env`: The environment that the API is invoked under. -- `[in] utf8Name`: The name of the function encoded as UTF8. This is visible -within JavaScript as the new function object's `name` property. -- `[in] cb`: The native function which should be called when this function -object is invoked. -- `[in] data`: User-provided data context. This will be passed back into the -function when invoked later. -- `[out] result`: `napi_value` representing the JavaScript function object for -the newly created function. - -Returns `napi_ok` if the API succeeded. - -This API allows an add-on author to create a function object in native code. -This is the primary mechanism to allow calling *into* the add-on's native code -*from* JavaScript. - -The newly created function is not automatically visible from script after this -call. Instead, a property must be explicitly set on any object that is visible -to JavaScript, in order for the function to be accessible from script. - -In order to expose a function as part of the -add-on's module exports, set the newly created function on the exports -object. A sample module might look as follows: -```C -napi_value SayHello(napi_env env, napi_callback_info info) { - printf("Hello\n"); - return NULL; -} - -napi_value Init(napi_env env, napi_value exports) { - napi_status status; - - napi_value fn; - status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn); - if (status != napi_ok) return NULL; - - status = napi_set_named_property(env, exports, "sayHello", fn); - if (status != napi_ok) return NULL; - - return exports; -} - -NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) -``` - -Given the above code, the add-on can be used from JavaScript as follows: -```js -const myaddon = require('./addon'); -myaddon.sayHello(); -``` - -The string passed to require is not necessarily the name passed into -`NAPI_MODULE` in the earlier snippet but the name of the target in `binding.gyp` -responsible for creating the `.node` file. - diff --git a/n-api/napi_create_promise.md b/n-api/napi_create_promise.md index b567b7f7..3db38c20 100644 --- a/n-api/napi_create_promise.md +++ b/n-api/napi_create_promise.md @@ -11,8 +11,8 @@ napi_status napi_create_promise(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[out] deferred`: A newly created deferred object which can later be passed to -`napi_resolve_deferred()` or `napi_reject_deferred()` to resolve resp. reject -the associated promise. + `napi_resolve_deferred()` or `napi_reject_deferred()` to resolve resp. reject + the associated promise. * `[out] promise`: The JavaScript promise associated with the deferred object. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_range_error.md b/n-api/napi_create_range_error.md index 189513a2..9995505f 100644 --- a/n-api/napi_create_range_error.md +++ b/n-api/napi_create_range_error.md @@ -11,10 +11,10 @@ NAPI_EXTERN napi_status napi_create_range_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_reference.md b/n-api/napi_create_reference.md index b422cb76..07ef0fec 100644 --- a/n-api/napi_create_reference.md +++ b/n-api/napi_create_reference.md @@ -11,8 +11,8 @@ NAPI_EXTERN napi_status napi_create_reference(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] value`: `napi_value` representing the `Object` to which we want -a reference. +* `[in] value`: `napi_value` representing the `Object` to which we want a + reference. * `[in] initial_refcount`: Initial reference count for the new reference. * `[out] result`: `napi_ref` pointing to the new reference. diff --git a/n-api/napi_create_string_latin1.md b/n-api/napi_create_string_latin1.md index d926f97c..a91f3852 100644 --- a/n-api/napi_create_string_latin1.md +++ b/n-api/napi_create_string_latin1.md @@ -12,8 +12,8 @@ napi_status napi_create_string_latin1(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing an ISO-8859-1-encoded string. -* `[in] length`: The length of the string in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. +* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it + is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_string_utf16.md b/n-api/napi_create_string_utf16.md index 351271f5..ce19e4f3 100644 --- a/n-api/napi_create_string_utf16.md +++ b/n-api/napi_create_string_utf16.md @@ -13,7 +13,7 @@ napi_status napi_create_string_utf16(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing a UTF16-LE-encoded string. * `[in] length`: The length of the string in two-byte code units, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + `NAPI_AUTO_LENGTH` if it is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_string_utf8.md b/n-api/napi_create_string_utf8.md index d6393956..7d12c82d 100644 --- a/n-api/napi_create_string_utf8.md +++ b/n-api/napi_create_string_utf8.md @@ -12,8 +12,8 @@ napi_status napi_create_string_utf8(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing a UTF8-encoded string. -* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` -if it is null-terminated. +* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it + is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_symbol.md b/n-api/napi_create_symbol.md index ee91a9a5..68511c9e 100644 --- a/n-api/napi_create_symbol.md +++ b/n-api/napi_create_symbol.md @@ -11,7 +11,7 @@ napi_status napi_create_symbol(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] description`: Optional `napi_value` which refers to a JavaScript -`String` to be set as the description for the symbol. + `String` to be set as the description for the symbol. * `[out] result`: A `napi_value` representing a JavaScript `Symbol`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_threadsafe_function.md b/n-api/napi_create_threadsafe_function.md index d1f4cb08..fb0959dc 100644 --- a/n-api/napi_create_threadsafe_function.md +++ b/n-api/napi_create_threadsafe_function.md @@ -24,24 +24,24 @@ napi_create_threadsafe_function(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] func`: An optional JavaScript function to call from another thread. -It must be provided if `NULL` is passed to `call_js_cb`. +* `[in] func`: An optional JavaScript function to call from another thread. It + must be provided if `NULL` is passed to `call_js_cb`. * `[in] async_resource`: An optional object associated with the async work that -will be passed to possible `async_hooks` [`init` hooks][]. + will be passed to possible `async_hooks` [`init` hooks][]. * `[in] async_resource_name`: A JavaScript string to provide an identifier for -the kind of resource that is being provided for diagnostic information exposed -by the `async_hooks` API. + the kind of resource that is being provided for diagnostic information exposed + by the `async_hooks` API. * `[in] max_queue_size`: Maximum size of the queue. `0` for no limit. * `[in] initial_thread_count`: The initial number of threads, including the main -thread, which will be making use of this function. + thread, which will be making use of this function. * `[in] thread_finalize_data`: Optional data to be passed to `thread_finalize_cb`. * `[in] thread_finalize_cb`: Optional function to call when the -`napi_threadsafe_function` is being destroyed. + `napi_threadsafe_function` is being destroyed. * `[in] context`: Optional data to attach to the resulting -`napi_threadsafe_function`. + `napi_threadsafe_function`. * `[in] call_js_cb`: Optional callback which calls the JavaScript function in -response to a call on a different thread. This callback will be called on the -main thread. If not given, the JavaScript function will be called with no -parameters and with `undefined` as its `this` value. + response to a call on a different thread. This callback will be called on the + main thread. If not given, the JavaScript function will be called with no + parameters and with `undefined` as its `this` value. * `[out] result`: The asynchronous thread-safe JavaScript function. diff --git a/n-api/napi_create_type_error.md b/n-api/napi_create_type_error.md index bc1aa484..871a50dd 100644 --- a/n-api/napi_create_type_error.md +++ b/n-api/napi_create_type_error.md @@ -11,10 +11,10 @@ NAPI_EXTERN napi_status napi_create_type_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_create_typedarray.md b/n-api/napi_create_typedarray.md index 1974a376..fbf517d7 100644 --- a/n-api/napi_create_typedarray.md +++ b/n-api/napi_create_typedarray.md @@ -17,7 +17,7 @@ napi_status napi_create_typedarray(napi_env env, * `[in] length`: Number of elements in the `TypedArray`. * `[in] arraybuffer`: `ArrayBuffer` underlying the typed array. * `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to -start projecting the `TypedArray`. + start projecting the `TypedArray`. * `[out] result`: A `napi_value` representing a JavaScript `TypedArray`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_delete_element.md b/n-api/napi_delete_element.md index 9a26959a..52aa4a73 100644 --- a/n-api/napi_delete_element.md +++ b/n-api/napi_delete_element.md @@ -14,7 +14,7 @@ napi_status napi_delete_element(napi_env env, * `[in] object`: The object to query. * `[in] index`: The index of the property to delete. * `[out] result`: Whether the element deletion succeeded or not. `result` can -optionally be ignored by passing `NULL`. + optionally be ignored by passing `NULL`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_delete_property.md b/n-api/napi_delete_property.md index eabe2d0d..1902ecd3 100644 --- a/n-api/napi_delete_property.md +++ b/n-api/napi_delete_property.md @@ -14,7 +14,7 @@ napi_status napi_delete_property(napi_env env, * `[in] object`: The object to query. * `[in] key`: The name of the property to delete. * `[out] result`: Whether the property deletion succeeded or not. `result` can -optionally be ignored by passing `NULL`. + optionally be ignored by passing `NULL`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_detach_arraybuffer.md b/n-api/napi_detach_arraybuffer.md new file mode 100644 index 00000000..d88dcca1 --- /dev/null +++ b/n-api/napi_detach_arraybuffer.md @@ -0,0 +1,25 @@ + + +> Stability: 1 - Experimental + +```C +napi_status napi_detach_arraybuffer(napi_env env, + napi_value arraybuffer) +``` + +* `[in] env`: The environment that the API is invoked under. +* `[in] arraybuffer`: The JavaScript `ArrayBuffer` to be detached. + +Returns `napi_ok` if the API succeeded. If a non-detachable `ArrayBuffer` is +passed in it returns `napi_detachable_arraybuffer_expected`. + +Generally, an `ArrayBuffer` is non-detachable if it has been detached before. +The engine may impose additional conditions on whether an `ArrayBuffer` is +detachable. For example, V8 requires that the `ArrayBuffer` be external, +that is, created with [`napi_create_external_arraybuffer`][]. + +This API represents the invocation of the `ArrayBuffer` detach operation as +defined in [Section 24.1.1.3][] of the ECMAScript Language Specification. + diff --git a/n-api/napi_env.md b/n-api/napi_env.md index 89e21b0c..185f75fc 100644 --- a/n-api/napi_env.md +++ b/n-api/napi_env.md @@ -1,3 +1,4 @@ + `napi_env` is used to represent a context that the underlying N-API implementation can use to persist VM-specific state. This structure is passed to native functions when they're invoked, and it must be passed back when diff --git a/n-api/napi_escape_handle.md b/n-api/napi_escape_handle.md index 44b11c4d..2ea301d6 100644 --- a/n-api/napi_escape_handle.md +++ b/n-api/napi_escape_handle.md @@ -13,9 +13,9 @@ napi_status napi_escape_handle(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] scope`: `napi_value` representing the current scope. * `[in] escapee`: `napi_value` representing the JavaScript `Object` to be -escaped. -* `[out] result`: `napi_value` representing the handle to the escaped -`Object` in the outer scope. + escaped. +* `[out] result`: `napi_value` representing the handle to the escaped `Object` + in the outer scope. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_fatal_error.md b/n-api/napi_fatal_error.md index cdfadc59..07eaea3f 100644 --- a/n-api/napi_fatal_error.md +++ b/n-api/napi_fatal_error.md @@ -12,11 +12,10 @@ NAPI_NO_RETURN void napi_fatal_error(const char* location, * `[in] location`: Optional location at which the error occurred. * `[in] location_len`: The length of the location in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + `NAPI_AUTO_LENGTH` if it is null-terminated. * `[in] message`: The message associated with the error. -* `[in] message_len`: The length of the message in bytes, or -`NAPI_AUTO_LENGTH` if it is -null-terminated. +* `[in] message_len`: The length of the message in bytes, or `NAPI_AUTO_LENGTH` + if it is null-terminated. The function call does not return, the process will be terminated. diff --git a/n-api/napi_get_and_clear_last_exception.md b/n-api/napi_get_and_clear_last_exception.md index 6b435ce1..59888929 100644 --- a/n-api/napi_get_and_clear_last_exception.md +++ b/n-api/napi_get_and_clear_last_exception.md @@ -13,7 +13,5 @@ napi_status napi_get_and_clear_last_exception(napi_env env, Returns `napi_ok` if the API succeeded. -This API returns true if an exception is pending. - This API can be called even if there is a pending JavaScript exception. diff --git a/n-api/napi_get_array_length.md b/n-api/napi_get_array_length.md index 90043d4a..33c648a3 100644 --- a/n-api/napi_get_array_length.md +++ b/n-api/napi_get_array_length.md @@ -11,7 +11,7 @@ napi_status napi_get_array_length(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing the JavaScript `Array` whose length is -being queried. + being queried. * `[out] result`: `uint32` representing length of the array. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_boolean.md b/n-api/napi_get_boolean.md index ce3851ba..392ead4e 100644 --- a/n-api/napi_get_boolean.md +++ b/n-api/napi_get_boolean.md @@ -10,7 +10,7 @@ napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The value of the boolean to retrieve. * `[out] result`: `napi_value` representing JavaScript `Boolean` singleton to -retrieve. + retrieve. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_cb_info.md b/n-api/napi_get_cb_info.md index 5c6dba9d..21da8682 100644 --- a/n-api/napi_get_cb_info.md +++ b/n-api/napi_get_cb_info.md @@ -14,13 +14,13 @@ napi_status napi_get_cb_info(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] cbinfo`: The callback info passed into the callback function. -* `[in-out] argc`: Specifies the size of the provided `argv` array -and receives the actual count of arguments. -* `[out] argv`: Buffer to which the `napi_value` representing the -arguments are copied. If there are more arguments than the provided -count, only the requested number of arguments are copied. If there are fewer -arguments provided than claimed, the rest of `argv` is filled with `napi_value` -values that represent `undefined`. +* `[in-out] argc`: Specifies the size of the provided `argv` array and receives + the actual count of arguments. +* `[out] argv`: Buffer to which the `napi_value` representing the arguments are + copied. If there are more arguments than the provided count, only the + requested number of arguments are copied. If there are fewer arguments + provided than claimed, the rest of `argv` is filled with `napi_value` values + that represent `undefined`. * `[out] this`: Receives the JavaScript `this` argument for the call. * `[out] data`: Receives the data pointer for the callback. diff --git a/n-api/napi_get_date_value.md b/n-api/napi_get_date_value.md index 505c3bd7..b413b004 100644 --- a/n-api/napi_get_date_value.md +++ b/n-api/napi_get_date_value.md @@ -11,8 +11,8 @@ napi_status napi_get_date_value(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing a JavaScript `Date`. -* `[out] result`: Time value as a `double` represented as milliseconds -since midnight at the beginning of 01 January, 1970 UTC. +* `[out] result`: Time value as a `double` represented as milliseconds since + midnight at the beginning of 01 January, 1970 UTC. This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification. diff --git a/n-api/napi_get_instance_data.md b/n-api/napi_get_instance_data.md index 6e5e27a4..7f6dfa3b 100644 --- a/n-api/napi_get_instance_data.md +++ b/n-api/napi_get_instance_data.md @@ -9,7 +9,7 @@ napi_status napi_get_instance_data(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[out] data`: The data item that was previously associated with the currently -running Agent by a call to `napi_set_instance_data()`. + running Agent by a call to `napi_set_instance_data()`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_property_names.md b/n-api/napi_get_property_names.md index bd8173bd..d65b918b 100644 --- a/n-api/napi_get_property_names.md +++ b/n-api/napi_get_property_names.md @@ -12,9 +12,9 @@ napi_status napi_get_property_names(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[in] object`: The object from which to retrieve the properties. * `[out] result`: A `napi_value` representing an array of JavaScript values -that represent the property names of the object. The API can be used to -iterate over `result` using [`napi_get_array_length`][] -and [`napi_get_element`][]. + that represent the property names of the object. The API can be used to + iterate over `result` using [`napi_get_array_length`][] + and [`napi_get_element`][]. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_prototype.md b/n-api/napi_get_prototype.md index bc8c5876..96cd1d48 100644 --- a/n-api/napi_get_prototype.md +++ b/n-api/napi_get_prototype.md @@ -11,8 +11,8 @@ napi_status napi_get_prototype(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] object`: `napi_value` representing JavaScript `Object` whose prototype -to return. This returns the equivalent of `Object.getPrototypeOf` (which is -not the same as the function's `prototype` property). + to return. This returns the equivalent of `Object.getPrototypeOf` (which is + not the same as the function's `prototype` property). * `[out] result`: `napi_value` representing prototype of the given object. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_reference_value.md b/n-api/napi_get_reference_value.md index d024b31b..85fe1c8e 100644 --- a/n-api/napi_get_reference_value.md +++ b/n-api/napi_get_reference_value.md @@ -15,7 +15,7 @@ object to which the reference is related. * `[in] env`: The environment that the API is invoked under. * `[in] ref`: `napi_ref` for which we requesting the corresponding `Object`. * `[out] result`: The `napi_value` for the `Object` referenced by the -`napi_ref`. + `napi_ref`. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_get_uv_event_loop.md b/n-api/napi_get_uv_event_loop.md index 7729d27e..6fb85939 100644 --- a/n-api/napi_get_uv_event_loop.md +++ b/n-api/napi_get_uv_event_loop.md @@ -7,7 +7,7 @@ napiVersion: 2 ```C NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, - uv_loop_t** loop); + struct uv_loop_s** loop); ``` * `[in] env`: The environment that the API is invoked under. diff --git a/n-api/napi_get_value_bool.md b/n-api/napi_get_value_bool.md index 4cacf8e1..bac92df8 100644 --- a/n-api/napi_get_value_bool.md +++ b/n-api/napi_get_value_bool.md @@ -10,7 +10,7 @@ napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Boolean`. * `[out] result`: C boolean primitive equivalent of the given JavaScript -`Boolean`. + `Boolean`. Returns `napi_ok` if the API succeeded. If a non-boolean `napi_value` is passed in it returns `napi_boolean_expected`. diff --git a/n-api/napi_get_value_double.md b/n-api/napi_get_value_double.md index 393b7e03..8a207e77 100644 --- a/n-api/napi_get_value_double.md +++ b/n-api/napi_get_value_double.md @@ -12,7 +12,7 @@ napi_status napi_get_value_double(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Number`. * `[out] result`: C double primitive equivalent of the given JavaScript -`Number`. + `Number`. Returns `napi_ok` if the API succeeded. If a non-number `napi_value` is passed in it returns `napi_number_expected`. diff --git a/n-api/napi_get_value_string_latin1.md b/n-api/napi_get_value_string_latin1.md index 57c0fec9..56990451 100644 --- a/n-api/napi_get_value_string_latin1.md +++ b/n-api/napi_get_value_string_latin1.md @@ -14,11 +14,11 @@ napi_status napi_get_value_string_latin1(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. * `[in] buf`: Buffer to write the ISO-8859-1-encoded string into. If NULL is -passed in, the length of the string (in bytes) is returned. + passed in, the length of the string (in bytes) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is -insufficient, the returned string will be truncated. + insufficient, the returned string will be truncated. * `[out] result`: Number of bytes copied into the buffer, excluding the null -terminator. + terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. diff --git a/n-api/napi_get_value_string_utf16.md b/n-api/napi_get_value_string_utf16.md index 8d9679b1..47b353a3 100644 --- a/n-api/napi_get_value_string_utf16.md +++ b/n-api/napi_get_value_string_utf16.md @@ -14,11 +14,11 @@ napi_status napi_get_value_string_utf16(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. * `[in] buf`: Buffer to write the UTF16-LE-encoded string into. If NULL is -passed in, the length of the string (in 2-byte code units) is returned. + passed in, the length of the string (in 2-byte code units) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is -insufficient, the returned string will be truncated. + insufficient, the returned string will be truncated. * `[out] result`: Number of 2-byte code units copied into the buffer, excluding -the null terminator. + the null terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. diff --git a/n-api/napi_get_value_string_utf8.md b/n-api/napi_get_value_string_utf8.md index 1a50fafe..6df7f8db 100644 --- a/n-api/napi_get_value_string_utf8.md +++ b/n-api/napi_get_value_string_utf8.md @@ -14,11 +14,11 @@ napi_status napi_get_value_string_utf8(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript string. * `[in] buf`: Buffer to write the UTF8-encoded string into. If NULL is passed - in, the length of the string (in bytes) is returned. + in, the length of the string (in bytes) is returned. * `[in] bufsize`: Size of the destination buffer. When this value is -insufficient, the returned string will be truncated. + insufficient, the returned string will be truncated. * `[out] result`: Number of bytes copied into the buffer, excluding the null -terminator. + terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. diff --git a/n-api/napi_get_value_uint32.md b/n-api/napi_get_value_uint32.md index 5c728faf..dae4bfab 100644 --- a/n-api/napi_get_value_uint32.md +++ b/n-api/napi_get_value_uint32.md @@ -12,7 +12,7 @@ napi_status napi_get_value_uint32(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Number`. * `[out] result`: C primitive equivalent of the given `napi_value` as a -`uint32_t`. + `uint32_t`. Returns `napi_ok` if the API succeeded. If a non-number `napi_value` is passed in it returns `napi_number_expected`. diff --git a/n-api/napi_handle_scope.md b/n-api/napi_handle_scope.md index 3100c6c0..c879af5c 100644 --- a/n-api/napi_handle_scope.md +++ b/n-api/napi_handle_scope.md @@ -1,3 +1,4 @@ + This is an abstraction used to control and modify the lifetime of objects created within a particular scope. In general, N-API values are created within the context of a handle scope. When a native method is called from diff --git a/n-api/napi_instanceof.md b/n-api/napi_instanceof.md index 656a15d8..5a1f1777 100644 --- a/n-api/napi_instanceof.md +++ b/n-api/napi_instanceof.md @@ -12,10 +12,10 @@ napi_status napi_instanceof(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] object`: The JavaScript value to check. -* `[in] constructor`: The JavaScript function object of the constructor -function to check against. +* `[in] constructor`: The JavaScript function object of the constructor function + to check against. * `[out] result`: Boolean that is set to true if `object instanceof constructor` -is true. + is true. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_is_buffer.md b/n-api/napi_is_buffer.md index b5419125..48f0aaef 100644 --- a/n-api/napi_is_buffer.md +++ b/n-api/napi_is_buffer.md @@ -10,7 +10,7 @@ napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The JavaScript value to check. * `[out] result`: Whether the given `napi_value` represents a `node::Buffer` -object. + object. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_is_date.md b/n-api/napi_is_date.md index ddee3217..de46f35f 100644 --- a/n-api/napi_is_date.md +++ b/n-api/napi_is_date.md @@ -10,7 +10,7 @@ napi_status napi_is_date(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The JavaScript value to check. * `[out] result`: Whether the given `napi_value` represents a JavaScript `Date` -object. + object. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_is_detached_arraybuffer.md b/n-api/napi_is_detached_arraybuffer.md new file mode 100644 index 00000000..f591993b --- /dev/null +++ b/n-api/napi_is_detached_arraybuffer.md @@ -0,0 +1,24 @@ + + +> Stability: 1 - Experimental + +```C +napi_status napi_is_detached_arraybuffer(napi_env env, + napi_value arraybuffer, + bool* result) +``` + +* `[in] env`: The environment that the API is invoked under. +* `[in] arraybuffer`: The JavaScript `ArrayBuffer` to be checked. +* `[out] result`: Whether the `arraybuffer` is detached. + +Returns `napi_ok` if the API succeeded. + +The `ArrayBuffer` is considered detached if its internal data is `null`. + +This API represents the invocation of the `ArrayBuffer` `IsDetachedBuffer` +operation as defined in [Section 24.1.1.2][] of the ECMAScript Language +Specification. + diff --git a/n-api/napi_is_error.md b/n-api/napi_is_error.md index c7d00839..ae34c868 100644 --- a/n-api/napi_is_error.md +++ b/n-api/napi_is_error.md @@ -12,7 +12,7 @@ NAPI_EXTERN napi_status napi_is_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: The `napi_value` to be checked. * `[out] result`: Boolean value that is set to true if `napi_value` represents -an error, false otherwise. + an error, false otherwise. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_is_exception_pending.md b/n-api/napi_is_exception_pending.md index 53bd69df..7ed4807f 100644 --- a/n-api/napi_is_exception_pending.md +++ b/n-api/napi_is_exception_pending.md @@ -12,7 +12,5 @@ napi_status napi_is_exception_pending(napi_env env, bool* result); Returns `napi_ok` if the API succeeded. -This API returns true if an exception is pending. - This API can be called even if there is a pending JavaScript exception. diff --git a/n-api/napi_make_callback.md b/n-api/napi_make_callback.md index e9f57ed5..11fbe61a 100644 --- a/n-api/napi_make_callback.md +++ b/n-api/napi_make_callback.md @@ -23,11 +23,10 @@ NAPI_EXTERN napi_status napi_make_callback(napi_env env, which indicates the current async context (if any) is to be used for the callback. * `[in] recv`: The `this` object passed to the called function. -* `[in] func`: `napi_value` representing the JavaScript function -to be invoked. +* `[in] func`: `napi_value` representing the JavaScript function to be invoked. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of JavaScript values as `napi_value` -representing the arguments to the function. +* `[in] argv`: Array of JavaScript values as `napi_value` representing the + arguments to the function. * `[out] result`: `napi_value` representing the JavaScript object returned. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_new_instance.md b/n-api/napi_new_instance.md index 4823f535..7757ea27 100644 --- a/n-api/napi_new_instance.md +++ b/n-api/napi_new_instance.md @@ -12,13 +12,13 @@ napi_status napi_new_instance(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] cons`: `napi_value` representing the JavaScript function -to be invoked as a constructor. +* `[in] cons`: `napi_value` representing the JavaScript function to be invoked + as a constructor. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of JavaScript values as `napi_value` -representing the arguments to the constructor. +* `[in] argv`: Array of JavaScript values as `napi_value` representing the + arguments to the constructor. * `[out] result`: `napi_value` representing the JavaScript object returned, -which in this case is the constructed object. + which in this case is the constructed object. This method is used to instantiate a new JavaScript value using a given `napi_value` that represents the constructor for the object. For example, diff --git a/n-api/napi_open_callback_scope.md b/n-api/napi_open_callback_scope.md index c3f1b644..e0d2edd5 100644 --- a/n-api/napi_open_callback_scope.md +++ b/n-api/napi_open_callback_scope.md @@ -13,9 +13,8 @@ NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] resource_object`: An object associated with the async work that will be passed to possible `async_hooks` [`init` hooks][]. -* `[in] context`: Context for the async operation that is -invoking the callback. This should be a value previously obtained -from [`napi_async_init`][]. +* `[in] context`: Context for the async operation that is invoking the callback. + This should be a value previously obtained from [`napi_async_init`][]. * `[out] result`: The newly created scope. There are cases (for example, resolving promises) where it is diff --git a/n-api/napi_property_descriptor.md b/n-api/napi_property_descriptor.md index c14ad7a1..25cd9307 100644 --- a/n-api/napi_property_descriptor.md +++ b/n-api/napi_property_descriptor.md @@ -16,30 +16,30 @@ typedef struct { ``` * `utf8name`: Optional `String` describing the key for the property, -encoded as UTF8. One of `utf8name` or `name` must be provided for the -property. + encoded as UTF8. One of `utf8name` or `name` must be provided for the + property. * `name`: Optional `napi_value` that points to a JavaScript string or symbol -to be used as the key for the property. One of `utf8name` or `name` must -be provided for the property. + to be used as the key for the property. One of `utf8name` or `name` must + be provided for the property. * `value`: The value that's retrieved by a get access of the property if the - property is a data property. If this is passed in, set `getter`, `setter`, - `method` and `data` to `NULL` (since these members won't be used). + property is a data property. If this is passed in, set `getter`, `setter`, + `method` and `data` to `NULL` (since these members won't be used). * `getter`: A function to call when a get access of the property is performed. -If this is passed in, set `value` and `method` to `NULL` (since these members -won't be used). The given function is called implicitly by the runtime when the -property is accessed from JavaScript code (or if a get on the property is -performed using a N-API call). + If this is passed in, set `value` and `method` to `NULL` (since these members + won't be used). The given function is called implicitly by the runtime when + the property is accessed from JavaScript code (or if a get on the property is + performed using a N-API call). * `setter`: A function to call when a set access of the property is performed. -If this is passed in, set `value` and `method` to `NULL` (since these members -won't be used). The given function is called implicitly by the runtime when the -property is set from JavaScript code (or if a set on the property is -performed using a N-API call). + If this is passed in, set `value` and `method` to `NULL` (since these members + won't be used). The given function is called implicitly by the runtime when + the property is set from JavaScript code (or if a set on the property is + performed using a N-API call). * `method`: Set this to make the property descriptor object's `value` -property to be a JavaScript function represented by `method`. If this is -passed in, set `value`, `getter` and `setter` to `NULL` (since these members -won't be used). -* `attributes`: The attributes associated with the particular property. -See [`napi_property_attributes`][]. -* `data`: The callback data passed into `method`, `getter` and `setter` if -this function is invoked. + property to be a JavaScript function represented by `method`. If this is + passed in, set `value`, `getter` and `setter` to `NULL` (since these members + won't be used). +* `attributes`: The attributes associated with the particular property. See + [`napi_property_attributes`][]. +* `data`: The callback data passed into `method`, `getter` and `setter` if this + function is invoked. diff --git a/n-api/napi_release_threadsafe_function.md b/n-api/napi_release_threadsafe_function.md index 5eb86d7a..b24297dd 100644 --- a/n-api/napi_release_threadsafe_function.md +++ b/n-api/napi_release_threadsafe_function.md @@ -11,13 +11,14 @@ napi_release_threadsafe_function(napi_threadsafe_function func, ``` * `[in] func`: The asynchronous thread-safe JavaScript function whose reference -count to decrement. + count to decrement. * `[in] mode`: Flag whose value can be either `napi_tsfn_release` to indicate -that the current thread will make no further calls to the thread-safe function, -or `napi_tsfn_abort` to indicate that in addition to the current thread, no -other thread should make any further calls to the thread-safe function. If set -to `napi_tsfn_abort`, further calls to `napi_call_threadsafe_function()` will -return `napi_closing`, and no further values will be placed in the queue. + that the current thread will make no further calls to the thread-safe + function, or `napi_tsfn_abort` to indicate that in addition to the current + thread, no other thread should make any further calls to the thread-safe + function. If set to `napi_tsfn_abort`, further calls to + `napi_call_threadsafe_function()` will return `napi_closing`, and no further + values will be placed in the queue. A thread should call this API when it stops making use of `func`. Passing `func` to any thread-safe APIs after having called this API has undefined results, as diff --git a/n-api/napi_run_script.md b/n-api/napi_run_script.md index 79994789..8329af7f 100644 --- a/n-api/napi_run_script.md +++ b/n-api/napi_run_script.md @@ -13,3 +13,16 @@ NAPI_EXTERN napi_status napi_run_script(napi_env env, * `[in] script`: A JavaScript string containing the script to execute. * `[out] result`: The value resulting from having executed the script. +This function executes a string of JavaScript code and returns its result with +the following caveats: + +* Unlike `eval`, this function does not allow the script to access the current + lexical scope, and therefore also does not allow to access the + [module scope][], meaning that pseudo-globals such as `require` will not be + available. +* The script can access the [global scope][]. Function and `var` declarations + in the script will be added to the [`global`][] object. Variable declarations + made using `let` and `const` will be visible globally, but will not be added + to the [`global`][] object. +* The value of `this` is [`global`][] within the script. + diff --git a/n-api/napi_set_instance_data.md b/n-api/napi_set_instance_data.md index 4d26cfc7..98562c44 100644 --- a/n-api/napi_set_instance_data.md +++ b/n-api/napi_set_instance_data.md @@ -12,9 +12,9 @@ napi_status napi_set_instance_data(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[in] data`: The data item to make available to bindings of this instance. * `[in] finalize_cb`: The function to call when the environment is being torn -down. The function receives `data` so that it might free it. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. + down. The function receives `data` so that it might free it. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_status.md b/n-api/napi_status.md index 89bc7a8e..a8d6448a 100644 --- a/n-api/napi_status.md +++ b/n-api/napi_status.md @@ -26,6 +26,8 @@ typedef enum { napi_closing, napi_bigint_expected, napi_date_expected, + napi_arraybuffer_expected, + napi_detachable_arraybuffer_expected, } napi_status; ``` diff --git a/n-api/napi_threadsafe_function_call_js.md b/n-api/napi_threadsafe_function_call_js.md index 5e6dc023..3e90cd42 100644 --- a/n-api/napi_threadsafe_function_call_js.md +++ b/n-api/napi_threadsafe_function_call_js.md @@ -27,15 +27,16 @@ typedef void (*napi_threadsafe_function_call_js)(napi_env env, ``` * `[in] env`: The environment to use for API calls, or `NULL` if the thread-safe -function is being torn down and `data` may need to be freed. + function is being torn down and `data` may need to be freed. * `[in] js_callback`: The JavaScript function to call, or `NULL` if the -thread-safe function is being torn down and `data` may need to be freed. It may -also be `NULL` if the thread-safe function was created without `js_callback`. + thread-safe function is being torn down and `data` may need to be freed. It + may also be `NULL` if the thread-safe function was created without + `js_callback`. * `[in] context`: The optional data with which the thread-safe function was -created. + created. * `[in] data`: Data created by the secondary thread. It is the responsibility of -the callback to convert this native data to JavaScript values (with N-API -functions) that can be passed as parameters when `js_callback` is invoked. This -pointer is managed entirely by the threads and this callback. Thus this callback -should free the data. + the callback to convert this native data to JavaScript values (with N-API + functions) that can be passed as parameters when `js_callback` is invoked. + This pointer is managed entirely by the threads and this callback. Thus this + callback should free the data. diff --git a/n-api/napi_throw_error.md b/n-api/napi_throw_error.md index 54859220..3a1d9267 100644 --- a/n-api/napi_throw_error.md +++ b/n-api/napi_throw_error.md @@ -11,8 +11,7 @@ NAPI_EXTERN napi_status napi_throw_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_throw_range_error.md b/n-api/napi_throw_range_error.md index 74dcd3e2..e483fe4c 100644 --- a/n-api/napi_throw_range_error.md +++ b/n-api/napi_throw_range_error.md @@ -11,8 +11,7 @@ NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_throw_type_error.md b/n-api/napi_throw_type_error.md index f4e742fa..5917210e 100644 --- a/n-api/napi_throw_type_error.md +++ b/n-api/napi_throw_type_error.md @@ -11,8 +11,7 @@ NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. diff --git a/n-api/napi_unref_threadsafe_function.md b/n-api/napi_unref_threadsafe_function.md index e6ae789d..03ba586a 100644 --- a/n-api/napi_unref_threadsafe_function.md +++ b/n-api/napi_unref_threadsafe_function.md @@ -113,6 +113,11 @@ This API may only be called from the main thread. + + + + + diff --git a/n-api/napi_value.md b/n-api/napi_value.md index a3331bf4..fddd19e3 100644 --- a/n-api/napi_value.md +++ b/n-api/napi_value.md @@ -1,2 +1,3 @@ + This is an opaque pointer that is used to represent a JavaScript value. diff --git a/n-api/return_values.md b/n-api/return_values.md index f5103c3b..3d0b5ad9 100644 --- a/n-api/return_values.md +++ b/n-api/return_values.md @@ -1,3 +1,4 @@ + All of the N-API functions share the same error handling pattern. The return type of all API functions is `napi_status`. diff --git a/n-api/simple_asynchronous_operations.md b/n-api/simple_asynchronous_operations.md index d84ffdb1..fb1e88ea 100644 --- a/n-api/simple_asynchronous_operations.md +++ b/n-api/simple_asynchronous_operations.md @@ -7,7 +7,7 @@ allows them to avoid blocking overall execution of the Node.js application. N-API provides an ABI-stable interface for these supporting functions which covers the most common asynchronous use cases. -N-API defines the `napi_work` structure which is used to manage +N-API defines the `napi_async_work` structure which is used to manage asynchronous workers. Instances are created/deleted with [`napi_create_async_work`][] and [`napi_delete_async_work`][]. diff --git a/n-api/working_with_javascript_values_abstract_operations.md b/n-api/working_with_javascript_values_abstract_operations.md deleted file mode 100644 index fca2416a..00000000 --- a/n-api/working_with_javascript_values_abstract_operations.md +++ /dev/null @@ -1,12 +0,0 @@ - -N-API exposes a set of APIs to perform some abstract operations on JavaScript -values. Some of these operations are documented under [Section 7][] -of the [ECMAScript Language Specification][]. - -These APIs support doing one of the following: - -1. Coerce JavaScript values to specific JavaScript types (such as `Number` or - `String`). -2. Check the type of a JavaScript value. -3. Check for equality between two JavaScript values. - diff --git a/net/server_listen_handle_backlog_callback.md b/net/server_listen_handle_backlog_callback.md index bdc2a524..b4caf1f9 100644 --- a/net/server_listen_handle_backlog_callback.md +++ b/net/server_listen_handle_backlog_callback.md @@ -4,7 +4,7 @@ added: v0.5.10 * `handle` {Object} * `backlog` {number} [`server.listen()`] 函数的通用参数。 -* `callback` {Function} [`server.listen()`] 函数的通用参数。 +* `callback` {Function} * 返回: {net.Server} 启动一个服务器,监听已经绑定到端口、Unix 域套接字或 Windows 命名管道的给定 `handle` 上的连接。 diff --git a/net/server_listen_options_callback.md b/net/server_listen_options_callback.md index 666fb4c4..c288e126 100644 --- a/net/server_listen_options_callback.md +++ b/net/server_listen_options_callback.md @@ -15,7 +15,7 @@ changes: * `readableAll` {boolean} 对于 IPC 服务器,使管道对所有用户都可读。**默认值:** `false`。 * `writableAll` {boolean} 对于 IPC 服务器,使管道对所有用户都可写。**默认值:** `false`。 * `ipv6Only` {boolean} 对于 TCP 服务器,将 `ipv6Only` 设置为 `true` 将会禁用双栈支持,即绑定到主机 `::` 不会使 `0.0.0.0` 绑定。**默认值:** `false`。 -* `callback` {Function} [`server.listen()`] 函数的通用参数。 +* `callback` {Function} * 返回: {net.Server} 如果指定了 `port` 参数,该方法的行为跟 [server.listen([port[, host[, backlog]]][, callback])][server_listen_port] 一样。 diff --git a/net/server_listen_path_backlog_callback.md b/net/server_listen_path_backlog_callback.md index 7316f719..6f753ec2 100644 --- a/net/server_listen_path_backlog_callback.md +++ b/net/server_listen_path_backlog_callback.md @@ -4,7 +4,7 @@ added: v0.1.90 * `path` {string} 服务器需要监听的路径。查看 [识别 IPC 连接的路径。][Identifying paths for IPC connections]。 * `backlog` {number} [`server.listen()`] 函数的通用参数。 -* `callback` {Function} [`server.listen()`] 函数的通用参数。 +* `callback` {Function} * 返回: {net.Server} 启动一个 [IPC] 服务器监听给定 `path` 的连接。 diff --git a/net/server_listen_port_host_backlog_callback.md b/net/server_listen_port_host_backlog_callback.md index 15a9fa35..af508a53 100644 --- a/net/server_listen_port_host_backlog_callback.md +++ b/net/server_listen_port_host_backlog_callback.md @@ -4,7 +4,7 @@ added: v0.1.90 * `port` {number} * `host` {string} * `backlog` {number} [`server.listen()`][] 函数的通用参数。 -* `callback` {Function} [`server.listen()`][] 函数的通用参数。 +* `callback` {Function} * 返回: {net.Server} 启动一个 TCP 服务监听输入的 `port` 和 `host`。 diff --git a/perf_hooks/performance_timing_api.md b/perf_hooks/performance_timing_api.md index f4639868..734043e7 100644 --- a/perf_hooks/performance_timing_api.md +++ b/perf_hooks/performance_timing_api.md @@ -1,7 +1,7 @@ -> Stability: 1 - Experimental +> Stability: 2 - Stable The Performance Timing API provides an implementation of the [W3C Performance Timeline][] specification. The purpose of the API diff --git a/process/event_message.md b/process/event_message.md index a24ae5be..c9593e2e 100644 --- a/process/event_message.md +++ b/process/event_message.md @@ -10,4 +10,7 @@ added: v0.5.10 消息会进行序列化和解析。 生成的消息可能与最初发送的消息不同。 +如果在衍生进程时使用了 `serialization` 选项设置为 `'advanced'`,则 `message` 参数可以包含 JSON 无法表示的数据。 +有关更多详细信息,请参阅 [`child_process` 的高级序列化][Advanced Serialization]。 + diff --git a/process/process_umask_mask.md b/process/process_umask_mask.md index c6b5ce4a..2159bc91 100644 --- a/process/process_umask_mask.md +++ b/process/process_umask_mask.md @@ -2,7 +2,7 @@ added: v0.1.19 --> -* `mask` {number} +* `mask` {string|integer} `process.umask()`方法用于返回或设置Node.js进程的默认创建文件的权限掩码。子进程从父进程继承这个掩码。 不传参数时,默认返回当前掩码,如果传递了参数,创建文件掩码就被设置为参数值,并且返回之前的掩码。 diff --git a/process/signal_events.md b/process/signal_events.md index 75173244..6c10d60d 100644 --- a/process/signal_events.md +++ b/process/signal_events.md @@ -4,6 +4,8 @@ 当 Node.js 进程接收到一个信号时,会触发信号事件。 signal(7) 列出了标准POSIX的信号名称列表,例如 `'SIGINT'`、`'SIGHUP'` 等等。 +信号在 [`Worker`] 线程上不可用。 + 信号处理程序将会接收信号的名称(`'SIGINT'`,`'SIGTERM'` 等)作为第一个参数。 每个事件名称,以信号名称的大写表示 (比如事件 `'SIGINT'` 对应信号 `SIGINT`)。 diff --git a/readline/rl_cursor.md b/readline/rl_cursor.md new file mode 100644 index 00000000..45f651d8 --- /dev/null +++ b/readline/rl_cursor.md @@ -0,0 +1,13 @@ + + +* {number|undefined} + +The cursor position relative to `rl.line`. + +This will track where the current cursor lands in the input string, when +reading input from a TTY stream. The position of cursor determines the +portion of the input string that will be modified as input is processed, +as well as the column where the terminal caret will be rendered. + diff --git a/readline/rl_getcursorpos.md b/readline/rl_getcursorpos.md new file mode 100644 index 00000000..54b1a994 --- /dev/null +++ b/readline/rl_getcursorpos.md @@ -0,0 +1,12 @@ + + +* Returns: {Object} + * `rows` {number} the row of the prompt the cursor currently lands on + * `cols` {number} the screen column the cursor currently lands on + +Returns the real position of the cursor in relation to the input +prompt + string. Long input (wrapping) strings, as well as multiple +line prompts are included in the calculations. + diff --git a/readline/rl_line.md b/readline/rl_line.md new file mode 100644 index 00000000..151afd04 --- /dev/null +++ b/readline/rl_line.md @@ -0,0 +1,34 @@ + + +* {string|undefined} + +The current input data being processed by node. + +This can be used when collecting input from a TTY stream to retrieve the +current value that has been processed thus far, prior to the `line` event +being emitted. Once the `line` event has been emitted, this property will +be an empty string. + +Be aware that modifying the value during the instance runtime may have +unintended consequences if `rl.cursor` is not also controlled. + +**If not using a TTY stream for input, use the [`'line'`][] event.** + +One possible use case would be as follows: + +```js +const values = ['lorem ipsum', 'dolor sit amet']; +const rl = readline.createInterface(process.stdin); +const showResults = debounce(() => { + console.log( + '\n', + values.filter((val) => val.startsWith(rl.line)).join(' ') + ); +}, 300); +process.stdin.on('keypress', (c, k) => { + showResults(); +}); +``` + diff --git a/repl/class_replserver.md b/repl/class_replserver.md index 477d4233..713f5a94 100644 --- a/repl/class_replserver.md +++ b/repl/class_replserver.md @@ -2,7 +2,17 @@ added: v0.1.91 --> +* `options` {Object|string} 参阅 [`repl.start()`]。 * 继承自: {readline.Interface} -`repl.REPLServer` 的实例是使用 `repl.start()` 方法创建的,不能直接地使用 JavaScript 的 `new` 关键字创建。 +`repl.REPLServer` 的实例是使用 [`repl.start()`] 方法或直接使用 JavaScript 的 `new` 关键字创建。 + +```js +const repl = require('repl'); + +const options = { useColors: true }; + +const firstInstance = repl.start(options); +const secondInstance = new repl.REPLServer(options); +``` diff --git a/stream/event_finish.md b/stream/event_finish.md index 065a6416..71072c2d 100644 --- a/stream/event_finish.md +++ b/stream/event_finish.md @@ -9,9 +9,9 @@ const writer = getWritableStreamSomehow(); for (let i = 0; i < 100; i++) { writer.write(`写入 #${i}!\n`); } -writer.end('写入结尾\n'); writer.on('finish', () => { console.error('写入已完成'); }); +writer.end('写入结尾\n'); ``` diff --git a/stream/stream_readable_from_iterable_options.md b/stream/stream_readable_from_iterable_options.md index e1b9a668..f1e7df1f 100644 --- a/stream/stream_readable_from_iterable_options.md +++ b/stream/stream_readable_from_iterable_options.md @@ -24,3 +24,5 @@ readable.on('data', (chunk) => { }); ``` +出于性能原因,调用 `Readable.from(string)` 或 `Readable.from(buffer)` 将不会迭代字符串或 buffer 以匹配其他流的语义。 + diff --git a/stream/writable_cork.md b/stream/writable_cork.md index 4ab01570..ca61517e 100644 --- a/stream/writable_cork.md +++ b/stream/writable_cork.md @@ -3,10 +3,12 @@ added: v0.11.2 --> `writable.cork()` 方法强制把所有写入的数据都缓冲到内存中。 -当调用 [`stream.uncork()`][] 或 [`stream.end()`][stream-end] 时,缓冲的数据才会被输出。 +当调用 [`stream.uncork()`][] 或 [`stream.end()`][stream-end] 方法时,缓冲的数据才会被输出。 -当写入大量小块数据到流时,内部缓冲可能失效,从而导致性能下降,`writable.cork()` 主要用于避免这种情况。 -对于这种情况,实现了 `writable._writev()` 的流可以用更优的方式对写入的数据进行缓冲。 +`writable.cork()` 的主要目的是为了适应将几个数据快速连续地写入流的情况。 +`writable.cork()` 不会立即将它们转发到底层的目标,而是缓冲所有数据块,直到调用 `writable.uncork()`,这会将它们全部传给 `writable._writev()`(如果存在)。 +这可以防止出现行头阻塞的情况,在这种情况下,正在等待第一个数据块被处理的同时对数据进行缓冲。 +但是,使用 `writable.cork()` 而不实现 `writable._writev()` 可能会对吞吐量产生不利影响。 -也可参阅:[`writable.uncork()`]。 +也可参阅:[`writable.uncork()`]、[`writable._writev()`][stream-_writev]。 diff --git a/stream/writable_writablecorked.md b/stream/writable_writablecorked.md new file mode 100644 index 00000000..80c2e679 --- /dev/null +++ b/stream/writable_writablecorked.md @@ -0,0 +1,9 @@ + + +* {integer} + +Number of times [`writable.uncork()`][stream-uncork] needs to be +called in order to fully uncork the stream. + diff --git a/tls/alpn_and_sni.md b/tls/alpn_and_sni.md index 902ed431..3070aaff 100644 --- a/tls/alpn_and_sni.md +++ b/tls/alpn_and_sni.md @@ -1,10 +1,8 @@ -ALPN (Application-Layer Protocol Negotiation Extension) and -SNI (Server Name Indication) are TLS handshake extensions: +ALPN(Application-Layer Protocol Negotiation Extension,应用层协议协商扩展)和SNI(Server Name Indication,服务器名称指示)是 TLS 的握手扩展: -* ALPN: Allows the use of one TLS server for multiple protocols (HTTP, HTTP/2) -* SNI: Allows the use of one TLS server for multiple hostnames with different - SSL certificates. +* ALPN:允许将一个 TLS 服务器用于多种协议(HTTP、HTTP/2)。 +* SNI:允许将一个 TLS 服务器用于具有不同 SSL 证书的多个主机名。 diff --git a/tls/event_session.md b/tls/event_session.md index e7e49c2b..9ed4dbc9 100644 --- a/tls/event_session.md +++ b/tls/event_session.md @@ -17,14 +17,14 @@ On the client, the `session` can be provided to the `session` option of See [Session Resumption][] for more information. -Note: For TLSv1.2 and below, [`tls.TLSSocket.getSession()`][] can be called once -the handshake is complete. For TLSv1.3, only ticket based resumption is allowed +For TLSv1.2 and below, [`tls.TLSSocket.getSession()`][] can be called once +the handshake is complete. For TLSv1.3, only ticket-based resumption is allowed by the protocol, multiple tickets are sent, and the tickets aren't sent until -later, after the handshake completes, so it is necessary to wait for the -`'session'` event to get a resumable session. Applications are -recommended to use the `'session'` event instead of `getSession()` to ensure -they will work for all TLS protocol versions. Applications that only expect to -get or use 1 session should listen for this event only once: +after the handshake completes. So it is necessary to wait for the +`'session'` event to get a resumable session. Applications +should use the `'session'` event instead of `getSession()` to ensure +they will work for all TLS versions. Applications that only expect to +get or use one session should listen for this event only once: ```js tlsSocket.once('session', (session) => { diff --git a/tls/pre_shared_keys.md b/tls/pre_shared_keys.md new file mode 100644 index 00000000..07691303 --- /dev/null +++ b/tls/pre_shared_keys.md @@ -0,0 +1,33 @@ + + + +TLS-PSK support is available as an alternative to normal certificate-based +authentication. It uses a pre-shared key instead of certificates to +authenticate a TLS connection, providing mutual authentication. +TLS-PSK and public key infrastructure are not mutually exclusive. Clients and +servers can accommodate both, choosing either of them during the normal cipher +negotiation step. + +TLS-PSK is only a good choice where means exist to securely share a +key with every connecting machine, so it does not replace PKI +(Public Key Infrastructure) for the majority of TLS uses. +The TLS-PSK implementation in OpenSSL has seen many security flaws in +recent years, mostly because it is used only by a minority of applications. +Please consider all alternative solutions before switching to PSK ciphers. +Upon generating PSK it is of critical importance to use sufficient entropy as +discussed in [RFC 4086][]. Deriving a shared secret from a password or other +low-entropy sources is not secure. + +PSK ciphers are disabled by default, and using TLS-PSK thus requires explicitly +specifying a cipher suite with the `ciphers` option. The list of available +ciphers can be retrieved via `openssl ciphers -v 'PSK'`. All TLS 1.3 +ciphers are eligible for PSK but currently only those that use SHA256 digest are +supported they can be retrieved via `openssl ciphers -v -s -tls1_3 -psk`. + +According to the [RFC 4279][], PSK identities up to 128 bytes in length and +PSKs up to 64 bytes in length must be supported. As of OpenSSL 1.1.0 +maximum identity size is 128 bytes, and maximum PSK length is 256 bytes. + +The current implementation doesn't support asynchronous PSK callbacks due to the +limitations of the underlying OpenSSL API. + diff --git a/tls/tls_checkserveridentity_host_cert.md b/tls/tls_checkserveridentity_host_cert.md deleted file mode 100644 index 80839d8b..00000000 --- a/tls/tls_checkserveridentity_host_cert.md +++ /dev/null @@ -1,48 +0,0 @@ - - -* `host` {string} The hostname to verify the certificate against -* `cert` {Object} An object representing the peer's certificate. The returned - object has some properties corresponding to the fields of the certificate. - -Verifies the certificate `cert` is issued to host `host`. - -Returns {Error} object, populating it with the reason, host, and cert on -failure. On success, returns {undefined}. - -*Note*: This function can be overwritten by providing alternative function -as part of the `options.checkServerIdentity` option passed to `tls.connect()`. -The overwriting function can call `tls.checkServerIdentity()` of course, to augment -the checks done with additional verification. - -*Note*: This function is only called if the certificate passed all other checks, such as -being issued by trusted CA (`options.ca`). - -The cert object contains the parsed certificate and will have a structure similar to: - -```text -{ subject: - { OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ], - CN: '*.nodejs.org' }, - issuer: - { C: 'GB', - ST: 'Greater Manchester', - L: 'Salford', - O: 'COMODO CA Limited', - CN: 'COMODO RSA Domain Validation Secure Server CA' }, - subjectaltname: 'DNS:*.nodejs.org, DNS:nodejs.org', - infoAccess: - { 'CA Issuers - URI': - [ 'http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt' ], - 'OCSP - URI': [ 'http://ocsp.comodoca.com' ] }, - modulus: 'B56CE45CB740B09A13F64AC543B712FF9EE8E4C284B542A1708A27E82A8D151CA178153E12E6DDA15BF70FFD96CB8A88618641BDFCCA03527E665B70D779C8A349A6F88FD4EF6557180BD4C98192872BCFE3AF56E863C09DDD8BC1EC58DF9D94F914F0369102B2870BECFA1348A0838C9C49BD1C20124B442477572347047506B1FCD658A80D0C44BCC16BC5C5496CFE6E4A8428EF654CD3D8972BF6E5BFAD59C93006830B5EB1056BBB38B53D1464FA6E02BFDF2FF66CD949486F0775EC43034EC2602AEFBF1703AD221DAA2A88353C3B6A688EFE8387811F645CEED7B3FE46E1F8B9F59FAD028F349B9BC14211D5830994D055EEA3D547911E07A0ADDEB8A82B9188E58720D95CD478EEC9AF1F17BE8141BE80906F1A339445A7EB5B285F68039B0F294598A7D1C0005FC22B5271B0752F58CCDEF8C8FD856FB7AE21C80B8A2CE983AE94046E53EDE4CB89F42502D31B5360771C01C80155918637490550E3F555E2EE75CC8C636DDE3633CFEDD62E91BF0F7688273694EEEBA20C2FC9F14A2A435517BC1D7373922463409AB603295CEB0BB53787A334C9CA3CA8B30005C5A62FC0715083462E00719A8FA3ED0A9828C3871360A73F8B04A4FC1E71302844E9BB9940B77E745C9D91F226D71AFCAD4B113AAF68D92B24DDB4A2136B55A1CD1ADF39605B63CB639038ED0F4C987689866743A68769CC55847E4A06D6E2E3F1', - exponent: '0x10001', - valid_from: 'Aug 14 00:00:00 2017 GMT', - valid_to: 'Nov 20 23:59:59 2019 GMT', - fingerprint: '01:02:59:D9:C3:D2:0D:08:F7:82:4E:44:A4:B4:53:C5:E2:3A:87:4D', - ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ], - serialNumber: '66593D57F20CBC573E433381B5FEC280', - raw: } -``` - diff --git a/tls/tls_connect_options_callback.md b/tls/tls_connect_options_callback.md index f12fffe5..364aa3f7 100644 --- a/tls/tls_connect_options_callback.md +++ b/tls/tls_connect_options_callback.md @@ -1,6 +1,9 @@ * Returns: {Object} - * `name` {string} The name of the cipher suite. + * `name` {string} OpenSSL name for the cipher suite. + * `standardName` {string} IETF name for the cipher suite. * `version` {string} The minimum TLS protocol version supported by this cipher suite. Returns an object containing information on the negotiated cipher suite. -For example: `{ name: 'AES256-SHA', version: 'TLSv1.2' }`. +For example: +```json +{ + "name": "AES128-SHA256", + "standardName": "TLS_RSA_WITH_AES_128_CBC_SHA256", + "version": "TLSv1.2" +} +``` See [SSL_CIPHER_get_name](https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_name.html) diff --git a/util/background_colors.md b/util/background_colors.md new file mode 100644 index 00000000..611dbb09 --- /dev/null +++ b/util/background_colors.md @@ -0,0 +1,18 @@ + +* `bgBlack` +* `bgRed` +* `bgGreen` +* `bgYellow` +* `bgBlue` +* `bgMagenta` +* `bgCyan` +* `bgWhite` +* `bgGray` (alias: `bgGrey`, `bgBlackBright`) +* `bgRedBright` +* `bgGreenBright` +* `bgYellowBright` +* `bgBlueBright` +* `bgMagentaBright` +* `bgCyanBright` +* `bgWhiteBright` + diff --git a/util/customizing_util_inspect_colors.md b/util/customizing_util_inspect_colors.md index 3e8cdd9d..a2ce640a 100644 --- a/util/customizing_util_inspect_colors.md +++ b/util/customizing_util_inspect_colors.md @@ -20,9 +20,8 @@ * `symbol` - `green` * `undefined` - `grey` -预定义的颜色代码有:`white`、`grey`、`black`、`blue`、`cyan`、`green`、`magenta`、`red` 和 `yellow`。 -还有 `bold`、`italic`、`underline` 和 `inverse` 代码。 - 颜色样式使用 ANSI 控制码,可能不是所有终端都支持。 要验证颜色支持,请使用 [`tty.hasColors()`]。 +下面列出了预定义的控制代码(分为“修饰符”、“前景颜色”和“背景颜色”)。 + diff --git a/util/foreground_colors.md b/util/foreground_colors.md new file mode 100644 index 00000000..ce6c8187 --- /dev/null +++ b/util/foreground_colors.md @@ -0,0 +1,18 @@ + +* `black` +* `red` +* `green` +* `yellow` +* `blue` +* `magenta` +* `cyan` +* `white` +* `gray` (alias: `grey`, `blackBright`) +* `redBright` +* `greenBright` +* `yellowBright` +* `blueBright` +* `magentaBright` +* `cyanBright` +* `whiteBright` + diff --git a/util/modifiers.md b/util/modifiers.md new file mode 100644 index 00000000..8554dd21 --- /dev/null +++ b/util/modifiers.md @@ -0,0 +1,21 @@ + +Modifier support varies throughout different terminals. They will mostly be +ignored, if not supported. + +* `reset` - Resets all (color) modifiers to their defaults +* **bold** - Make text bold +* _italic_ - Make text italic +* underline - Make text underlined +* ~~strikethrough~~ - Puts a horizontal line through the center of the text + (Alias: `strikeThrough`, `crossedout`, `crossedOut`) +* `hidden` - Prints the text, but makes it invisible (Alias: conceal) +* dim - Decreased color intensity (Alias: + `faint`) +* overlined - Make text overlined +* blink - Hides and shows the text in an interval +* inverse - Swap foreground and + background colors (Alias: `swapcolors`, `swapColors`) +* doubleunderline - Make text + double underlined (Alias: `doubleUnderline`) +* framed - Draw a frame around the text + diff --git a/util/util_debug_string.md b/util/util_debug_string.md deleted file mode 100644 index f099ed1c..00000000 --- a/util/util_debug_string.md +++ /dev/null @@ -1,11 +0,0 @@ - - -> Stability: 0 - Deprecated: Use [`console.error()`][] instead. - -* `string` {string} The message to print to `stderr` - -Deprecated predecessor of `console.error`. - diff --git a/util/util_error_strings.md b/util/util_error_strings.md deleted file mode 100644 index 60108992..00000000 --- a/util/util_error_strings.md +++ /dev/null @@ -1,11 +0,0 @@ - - -> Stability: 0 - Deprecated: Use [`console.error()`][] instead. - -* `...strings` {string} The message to print to `stderr` - -Deprecated predecessor of `console.error`. - diff --git a/util/util_inspect_object_showhidden_depth_colors.md b/util/util_inspect_object_showhidden_depth_colors.md index 586c814d..ac8c09ba 100644 --- a/util/util_inspect_object_showhidden_depth_colors.md +++ b/util/util_inspect_object_showhidden_depth_colors.md @@ -1,6 +1,10 @@ - -> Stability: 0 - Deprecated: Use [`console.log()`][] instead. - -Deprecated predecessor of `console.log`. - diff --git a/util/util_puts_strings.md b/util/util_puts_strings.md deleted file mode 100644 index 4be0b551..00000000 --- a/util/util_puts_strings.md +++ /dev/null @@ -1,63 +0,0 @@ - - -> Stability: 0 - Deprecated: Use [`console.log()`][] instead. - -Deprecated predecessor of `console.log`. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vm/class_vm_module.md b/vm/class_vm_module.md new file mode 100644 index 00000000..087a27a7 --- /dev/null +++ b/vm/class_vm_module.md @@ -0,0 +1,102 @@ + + +> Stability: 1 - Experimental + +*This feature is only available with the `--experimental-vm-modules` command +flag enabled.* + +The `vm.Module` class provides a low-level interface for using +ECMAScript modules in VM contexts. It is the counterpart of the `vm.Script` +class that closely mirrors [Module Record][]s as defined in the ECMAScript +specification. + +Unlike `vm.Script` however, every `vm.Module` object is bound to a context from +its creation. Operations on `vm.Module` objects are intrinsically asynchronous, +in contrast with the synchronous nature of `vm.Script` objects. With the help +of async functions, however, manipulating `vm.Module` objects is fairly +straightforward. + +Using a `vm.Module` object requires three distinct steps: creation/parsing, +linking, and evaluation. These three steps are illustrated in the following +example. + +This implementation lies at a lower level than the [ECMAScript Module +loader][]. There is also currently no way to interact with the Loader, though +support is planned. + +```js +const vm = require('vm'); + +const contextifiedObject = vm.createContext({ secret: 42 }); + +(async () => { + // Step 1 + // + // Create a Module by constructing a new `vm.SourceTextModule` object. This + // parses the provided source text, throwing a `SyntaxError` if anything goes + // wrong. By default, a Module is created in the top context. But here, we + // specify `contextifiedObject` as the context this Module belongs to. + // + // Here, we attempt to obtain the default export from the module "foo", and + // put it into local binding "secret". + + const bar = new vm.SourceTextModule(` + import s from 'foo'; + s; + `, { context: contextifiedObject }); + + // Step 2 + // + // "Link" the imported dependencies of this Module to it. + // + // The provided linking callback (the "linker") accepts two arguments: the + // parent module (`bar` in this case) and the string that is the specifier of + // the imported module. The callback is expected to return a Module that + // corresponds to the provided specifier, with certain requirements documented + // in `module.link()`. + // + // If linking has not started for the returned Module, the same linker + // callback will be called on the returned Module. + // + // Even top-level Modules without dependencies must be explicitly linked. The + // callback provided would never be called, however. + // + // The link() method returns a Promise that will be resolved when all the + // Promises returned by the linker resolve. + // + // Note: This is a contrived example in that the linker function creates a new + // "foo" module every time it is called. In a full-fledged module system, a + // cache would probably be used to avoid duplicated modules. + + async function linker(specifier, referencingModule) { + if (specifier === 'foo') { + return new vm.SourceTextModule(` + // The "secret" variable refers to the global variable we added to + // "contextifiedObject" when creating the context. + export default secret; + `, { context: referencingModule.context }); + + // Using `contextifiedObject` instead of `referencingModule.context` + // here would work as well. + } + throw new Error(`Unable to resolve dependency: ${specifier}`); + } + await bar.link(linker); + + // Step 3 + // + // Evaluate the Module. The evaluate() method returns a Promise with a single + // property "result" that contains the result of the very last statement + // executed in the Module. In the case of `bar`, it is `s;`, which refers to + // the default export of the `foo` module, the `secret` we set in the + // beginning to 42. + + const { result } = await bar.evaluate(); + + console.log(result); + // Prints 42. +})(); +``` + diff --git a/vm/class_vm_script.md b/vm/class_vm_script.md index 7974bad0..445bc58e 100644 --- a/vm/class_vm_script.md +++ b/vm/class_vm_script.md @@ -2,4 +2,6 @@ added: v0.3.1 --> - `vm.Script`类型的实例包含若干预编译的脚本,这些脚本能够在特定的沙箱(或者上下文)中被运行。 + +`vm.Script` 类的实例包含可以在特定上下文中执行的预编译脚本。 + diff --git a/vm/class_vm_sourcetextmodule.md b/vm/class_vm_sourcetextmodule.md index fe0adbc0..d9e9fdc8 100644 --- a/vm/class_vm_sourcetextmodule.md +++ b/vm/class_vm_sourcetextmodule.md @@ -7,96 +7,8 @@ added: v9.6.0 *This feature is only available with the `--experimental-vm-modules` command flag enabled.* -The `vm.SourceTextModule` class provides a low-level interface for using -ECMAScript modules in VM contexts. It is the counterpart of the `vm.Script` -class that closely mirrors [Source Text Module Record][]s as defined in the -ECMAScript specification. +* Extends: {vm.Module} -Unlike `vm.Script` however, every `vm.SourceTextModule` object is bound to a -context from its creation. Operations on `vm.SourceTextModule` objects are -intrinsically asynchronous, in contrast with the synchronous nature of -`vm.Script` objects. With the help of async functions, however, manipulating -`vm.SourceTextModule` objects is fairly straightforward. - -Using a `vm.SourceTextModule` object requires three distinct steps: -creation/parsing, linking, and evaluation. These three steps are illustrated in -the following example. - -This implementation lies at a lower level than the [ECMAScript Module -loader][]. There is also currently no way to interact with the Loader, though -support is planned. - -```js -const vm = require('vm'); - -const contextifiedSandbox = vm.createContext({ secret: 42 }); - -(async () => { - // Step 1 - // - // Create a Module by constructing a new `vm.SourceTextModule` object. This - // parses the provided source text, throwing a `SyntaxError` if anything goes - // wrong. By default, a Module is created in the top context. But here, we - // specify `contextifiedSandbox` as the context this Module belongs to. - // - // Here, we attempt to obtain the default export from the module "foo", and - // put it into local binding "secret". - - const bar = new vm.SourceTextModule(` - import s from 'foo'; - s; - `, { context: contextifiedSandbox }); - - // Step 2 - // - // "Link" the imported dependencies of this Module to it. - // - // The provided linking callback (the "linker") accepts two arguments: the - // parent module (`bar` in this case) and the string that is the specifier of - // the imported module. The callback is expected to return a Module that - // corresponds to the provided specifier, with certain requirements documented - // in `module.link()`. - // - // If linking has not started for the returned Module, the same linker - // callback will be called on the returned Module. - // - // Even top-level Modules without dependencies must be explicitly linked. The - // callback provided would never be called, however. - // - // The link() method returns a Promise that will be resolved when all the - // Promises returned by the linker resolve. - // - // Note: This is a contrived example in that the linker function creates a new - // "foo" module every time it is called. In a full-fledged module system, a - // cache would probably be used to avoid duplicated modules. - - async function linker(specifier, referencingModule) { - if (specifier === 'foo') { - return new vm.SourceTextModule(` - // The "secret" variable refers to the global variable we added to - // "contextifiedSandbox" when creating the context. - export default secret; - `, { context: referencingModule.context }); - - // Using `contextifiedSandbox` instead of `referencingModule.context` - // here would work as well. - } - throw new Error(`Unable to resolve dependency: ${specifier}`); - } - await bar.link(linker); - - // Step 3 - // - // Evaluate the Module. The evaluate() method returns a Promise with a single - // property "result" that contains the result of the very last statement - // executed in the Module. In the case of `bar`, it is `s;`, which refers to - // the default export of the `foo` module, the `secret` we set in the - // beginning to 42. - - const { result } = await bar.evaluate(); - - console.log(result); - // Prints 42. -})(); -``` +The `vm.SourceTextModule` class provides the [Source Text Module Record][] as +defined in the ECMAScript specification. diff --git a/vm/class_vm_syntheticmodule.md b/vm/class_vm_syntheticmodule.md new file mode 100644 index 00000000..4553cb14 --- /dev/null +++ b/vm/class_vm_syntheticmodule.md @@ -0,0 +1,28 @@ + + +> Stability: 1 - Experimental + +*This feature is only available with the `--experimental-vm-modules` command +flag enabled.* + +* Extends: {vm.Module} + +The `vm.SyntheticModule` class provides the [Synthetic Module Record][] as +defined in the WebIDL specification. The purpose of synthetic modules is to +provide a generic interface for exposing non-JavaScript sources to ECMAScript +module graphs. + +```js +const vm = require('vm'); + +const source = '{ "a": 1 }'; +const module = new vm.SyntheticModule(['default'], function() { + const obj = JSON.parse(source); + this.setExport('default', obj); +}); + +// Use `module` in linking... +``` + diff --git a/vm/constructor_new_vm_script_code_options.md b/vm/constructor_new_vm_script_code_options.md index 0f79d1ad..8e572f36 100644 --- a/vm/constructor_new_vm_script_code_options.md +++ b/vm/constructor_new_vm_script_code_options.md @@ -26,8 +26,8 @@ changes: 如果未指定此选项,则对 `import()` 的调用将拒绝 [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`]。 此选项是 `--experimental-modules` 标志的实验 API 的一部分,不应被视为稳定。 * `specifier` {string} 传给 `import()` 的说明符。 - * `module` {vm.SourceTextModule} - * 返回: {Module Namespace Object|vm.SourceTextModule} 返回 `vm.SourceTextModule` 以利用错误跟踪,并避免出现包含 `then` 函数导出的命名空间问题。 + * `module` {vm.Module} + * 返回: {Module Namespace Object|vm.Module} 返回 `vm.Module` 以利用错误跟踪,并避免出现包含 `then` 函数导出的命名空间问题。     如果 `options` 是字符串,则它指定文件名。 diff --git a/vm/constructor_new_vm_sourcetextmodule_code_options.md b/vm/constructor_new_vm_sourcetextmodule_code_options.md index 234ceda3..8d8f4298 100644 --- a/vm/constructor_new_vm_sourcetextmodule_code_options.md +++ b/vm/constructor_new_vm_sourcetextmodule_code_options.md @@ -18,23 +18,21 @@ when `import()` is called. If this option is not specified, calls to `import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][]. * `specifier` {string} specifier passed to `import()` - * `module` {vm.SourceTextModule} - * Returns: {Module Namespace Object|vm.SourceTextModule} Returning a - `vm.SourceTextModule` is recommended in order to take advantage of error - tracking, and to avoid issues with namespaces that contain `then` - function exports. + * `module` {vm.Module} + * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is + recommended in order to take advantage of error tracking, and to avoid + issues with namespaces that contain `then` function exports. -Creates a new ES `Module` object. +Creates a new `SourceTextModule` instance. Properties assigned to the `import.meta` object that are objects may -allow the `Module` to access information outside the specified `context`, if the -object is created in the top level context. Use `vm.runInContext()` to create -objects in a specific context. +allow the module to access information outside the specified `context`. Use +`vm.runInContext()` to create objects in a specific context. ```js const vm = require('vm'); -const contextifiedSandbox = vm.createContext({ secret: 42 }); +const contextifiedObject = vm.createContext({ secret: 42 }); (async () => { const module = new vm.SourceTextModule( @@ -44,7 +42,7 @@ const contextifiedSandbox = vm.createContext({ secret: 42 }); // Note: this object is created in the top context. As such, // Object.getPrototypeOf(import.meta.prop) points to the // Object.prototype in the top context rather than that in - // the sandbox. + // the contextified object. meta.prop = {}; } }); @@ -57,7 +55,7 @@ const contextifiedSandbox = vm.createContext({ secret: 42 }); // To fix this problem, replace // meta.prop = {}; // above with - // meta.prop = vm.runInContext('{}', contextifiedSandbox); + // meta.prop = vm.runInContext('{}', contextifiedObject); })(); ``` diff --git a/vm/constructor_new_vm_syntheticmodule_exportnames_evaluatecallback_options.md b/vm/constructor_new_vm_syntheticmodule_exportnames_evaluatecallback_options.md new file mode 100644 index 00000000..748412a5 --- /dev/null +++ b/vm/constructor_new_vm_syntheticmodule_exportnames_evaluatecallback_options.md @@ -0,0 +1,19 @@ + + +* `exportNames` {string[]} Array of names that will be exported from the module. +* `evaluateCallback` {Function} Called when the module is evaluated. +* `options` + * `identifier` {string} String used in stack traces. + **Default:** `'vm:module(i)'` where `i` is a context-specific ascending + index. + * `context` {Object} The [contextified][] object as returned by the + `vm.createContext()` method, to compile and evaluate this `Module` in. + +Creates a new `SyntheticModule` instance. + +Objects assigned to the exports of this instance may allow importers of +the module to access information outside the specified `context`. Use +`vm.runInContext()` to create objects in a specific context. + diff --git a/vm/module_dependencyspecifiers.md b/vm/module_dependencyspecifiers.md index 5ad8ddbc..f9478ead 100644 --- a/vm/module_dependencyspecifiers.md +++ b/vm/module_dependencyspecifiers.md @@ -4,6 +4,6 @@ The specifiers of all dependencies of this module. The returned array is frozen to disallow any changes to it. -Corresponds to the `[[RequestedModules]]` field of -[Source Text Module Record][]s in the ECMAScript specification. +Corresponds to the `[[RequestedModules]]` field of [Cyclic Module Record][]s in +the ECMAScript specification. diff --git a/vm/module_error.md b/vm/module_error.md index d2f16eec..c1315e41 100644 --- a/vm/module_error.md +++ b/vm/module_error.md @@ -8,6 +8,6 @@ accessing this property will result in a thrown exception. The value `undefined` cannot be used for cases where there is not a thrown exception due to possible ambiguity with `throw undefined;`. -Corresponds to the `[[EvaluationError]]` field of [Source Text Module Record][]s +Corresponds to the `[[EvaluationError]]` field of [Cyclic Module Record][]s in the ECMAScript specification. diff --git a/vm/module_evaluate_options.md b/vm/module_evaluate_options.md index 3368e662..ce72fb03 100644 --- a/vm/module_evaluate_options.md +++ b/vm/module_evaluate_options.md @@ -24,6 +24,6 @@ evaluated, in which case it will do one of the following two things: This method cannot be called while the module is being evaluated (`module.status` is `'evaluating'`) to prevent infinite recursion. -Corresponds to the [Evaluate() concrete method][] field of [Source Text Module +Corresponds to the [Evaluate() concrete method][] field of [Cyclic Module Record][]s in the ECMAScript specification. diff --git a/vm/module_instantiate.md b/vm/module_instantiate.md deleted file mode 100644 index 5f304568..00000000 --- a/vm/module_instantiate.md +++ /dev/null @@ -1,16 +0,0 @@ - -Instantiate the module. This must be called after linking has completed -(`linkingStatus` is `'linked'`); otherwise it will throw an error. It may also -throw an exception if one of the dependencies does not provide an export the -parent module requires. - -However, if this function succeeded, further calls to this function after the -initial instantiation will be no-ops, to be consistent with the ECMAScript -specification. - -Unlike other methods operating on `Module`, this function completes -synchronously and returns nothing. - -Corresponds to the [Instantiate() concrete method][] field of [Source Text -Module Record][]s in the ECMAScript specification. - diff --git a/vm/module_link_linker.md b/vm/module_link_linker.md index 01b43365..95c96d2f 100644 --- a/vm/module_link_linker.md +++ b/vm/module_link_linker.md @@ -7,9 +7,8 @@ // ^^^^^ the module specifier ``` - * `referencingModule` {vm.SourceTextModule} The `Module` object `link()` is - called on. - * Returns: {vm.SourceTextModule|Promise} + * `referencingModule` {vm.Module} The `Module` object `link()` is called on. + * Returns: {vm.Module|Promise} * Returns: {Promise} Link module dependencies. This method must be called before evaluation, and @@ -43,6 +42,6 @@ that point all modules would have been fully linked already, the [HostResolveImportedModule][] implementation is fully synchronous per specification. -Corresponds to the [Link() concrete method][] field of [Source Text Module +Corresponds to the [Link() concrete method][] field of [Cyclic Module Record][]s in the ECMAScript specification. diff --git a/vm/module_linkingstatus.md b/vm/module_linkingstatus.md deleted file mode 100644 index 0eb0e525..00000000 --- a/vm/module_linkingstatus.md +++ /dev/null @@ -1,14 +0,0 @@ - -* {string} - -The current linking status of `module`. It will be one of the following values: - -* `'unlinked'`: `module.link()` has not yet been called. -* `'linking'`: `module.link()` has been called, but not all Promises returned by - the linker function have been resolved yet. -* `'linked'`: `module.link()` has been called, and all its dependencies have - been successfully linked. -* `'errored'`: `module.link()` has been called, but at least one of its - dependencies failed to link, either because the callback returned a `Promise` - that is rejected, or because the `Module` the callback returned is invalid. - diff --git a/vm/module_status.md b/vm/module_status.md index 96b7a5f3..5c81bc25 100644 --- a/vm/module_status.md +++ b/vm/module_status.md @@ -19,7 +19,7 @@ The current status of the module. Will be one of: * `'errored'`: The module has been evaluated, but an exception was thrown. Other than `'errored'`, this status string corresponds to the specification's -[Source Text Module Record][]'s `[[Status]]` field. `'errored'` corresponds to +[Cyclic Module Record][]'s `[[Status]]` field. `'errored'` corresponds to `'evaluated'` in the specification, but with `[[EvaluationError]]` set to a value that is not `undefined`. diff --git a/vm/module_url.md b/vm/module_url.md deleted file mode 100644 index a38c2a05..00000000 --- a/vm/module_url.md +++ /dev/null @@ -1,5 +0,0 @@ - -* {string} - -The URL of the current module, as set in the constructor. - diff --git a/vm/script_runincontext_contextifiedobject_options.md b/vm/script_runincontext_contextifiedobject_options.md new file mode 100644 index 00000000..c231c8d3 --- /dev/null +++ b/vm/script_runincontext_contextifiedobject_options.md @@ -0,0 +1,42 @@ + + +* `contextifiedObject` {Object} 由 `vm.createContext()` 返回的[上下文隔离化][contextified]的对象。 +* `options` {Object} + * `displayErrors` {boolean} 当值为 `true` 的时候,假如在解析代码的时候发生错误 [`Error`][],引起错误的行将会被加入堆栈跟踪信息。**默认值:** `true`。 + * `timeout` {integer} 定义在被终止执行之前此 `code` 被允许执行的最大毫秒数。假如执行被终止,将会抛出一个错误 [`Error`][]。该值必须是严格正整数。 + * `breakOnSigint` {boolean} 若值为 `true`,当收到 `SIGINT` (Ctrl+C)事件时,代码会被终止执行。 + 此外,通过 `process.on('SIGINT')` 方法所设置的消息响应机制在代码被执行时会被屏蔽,但代码被终止后会被恢复。如果执行被终止,一个错误 [`Error`][] 会被抛出。**默认值:** `false`。 +* 返回: {any} 脚本中执行的最后一个语句的结果。 + +在指定的 `contextifiedObject` 中执行 `vm.Script` 对象中被编译后的代码并返回其结果。被执行的代码无法获取本地作用域。 + +以下的例子会编译一段代码,该代码会递增一个全局变量,给另外一个全局变量赋值。同时该代码被编译后会被多次执行。全局变量会被置于 `context` 对象内。 + +```js +const util = require('util'); +const vm = require('vm'); + +const context = { + animal: 'cat', + count: 2 +}; + +const script = new vm.Script('count += 1; name = "kitty";'); + +vm.createContext(context); +for (let i = 0; i < 10; ++i) { + script.runInContext(context); +} + +console.log(util.inspect(context)); + +// { animal: 'cat', count: 12, name: 'kitty' } +``` + +使用 `timeout` 或者 `breakOnSigint` 选项会导致若干新的事件循环以及对应的线程,这有一个非零的性能消耗。 diff --git a/vm/script_runinnewcontext_contextobject_options.md b/vm/script_runinnewcontext_contextobject_options.md new file mode 100644 index 00000000..8c3ca38e --- /dev/null +++ b/vm/script_runinnewcontext_contextobject_options.md @@ -0,0 +1,45 @@ + + +* `contextObject` {Object} 一个将会被[上下文隔离化][contextified]的对象。如果是 `undefined`, 则会生成一个新的对象。 +* `options` {Object} + * `displayErrors` {boolean} 当值为 `true` 的时候,假如在解析代码的时候发生错误 [`Error`][],引起错误的行将会被加入堆栈跟踪信息。**默认值:** `true`。 + * `timeout` {integer} 定义在被终止执行之前此 `code` 被允许执行的最大毫秒数。假如执行被终止,将会抛出一个错误 [`Error`][]。该值必须是严格正整数。 + * `breakOnSigint` {boolean} 若值为 `true`,当收到 `SIGINT` (Ctrl+C)事件时,代码会被终止执行。 + 此外,通过 `process.on('SIGINT')` 方法所设置的消息响应机制在代码被执行时会被屏蔽,但代码被终止后会被恢复。如果执行被终止,一个错误 [`Error`][] 会被抛出。**默认值:** `false`。 + * `contextName` {string} 新创建的上下文的人类可读名称。 **默认值:** `'VM Context i'`,其中 `i` 是创建的上下文的升序数字索引。 + * `contextOrigin` {string} 对应于新创建用于显示目的的上下文的[原点][origin]。 + 原点应格式化为类似一个 URL,但只包含协议,主机和端口(如果需要),例如 [`URL`] 对象的 [`url.origin`] 属性的值。 最值得注意的是,此字符串应省略尾部斜杠,因为它表示路径。 **默认值:** `''`。 + * `contextCodeGeneration` {Object} + * `strings` {boolean} 如果设置为 `false`,则对 `eval` 或函数构造函数(`Function`、`GeneratorFunction` 等)的任何调用都将抛出 `EvalError`。**默认值:** `true`。 + * `wasm` {boolean} 如果设置为 `false`,则任何编译 WebAssembly 模块的尝试都将抛出 `WebAssembly.CompileError`。**默认值:** `true`。 +* 返回: {any} 脚本中执行的最后一个语句的结果。 + +首先给指定的 `contextObject` 提供一个隔离的上下文, 再在此上下文中执行 `vm.Script` 中被编译的代码,最后返回结果。运行中的代码无法获取本地作用域。 + +以下的例子会编译一段代码,该代码会递增一个全局变量,给另外一个全局变量赋值。同时该代码被编译后会被多次执行。全局变量会被置于各个独立的 `context` 对象内。 + +```js +const util = require('util'); +const vm = require('vm'); + +const script = new vm.Script('globalVar = "set"'); + +const contexts = [{}, {}, {}]; +contexts.forEach((context) => { + script.runInNewContext(context); +}); + +console.log(util.inspect(contexts)); + +// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }] +``` + diff --git a/vm/syntheticmodule_setexport_name_value.md b/vm/syntheticmodule_setexport_name_value.md new file mode 100644 index 00000000..8ca3d908 --- /dev/null +++ b/vm/syntheticmodule_setexport_name_value.md @@ -0,0 +1,26 @@ + + +* `name` {string} Name of the export to set. +* `value` {any} The value to set the export to. + +This method is used after the module is linked to set the values of exports. If +it is called before the module is linked, an [`ERR_VM_MODULE_STATUS`][] error +will be thrown. + +```js +const vm = require('vm'); + +(async () => { + const m = new vm.SyntheticModule(['x'], () => { + m.setExport('x', 1); + }); + + await m.link(() => {}); + await m.evaluate(); + + assert.strictEqual(m.namespace.x, 1); +})(); +``` + diff --git a/vm/vm_compilefunction_code_params_options.md b/vm/vm_compilefunction_code_params_options.md index 9a12cde9..99b2d53e 100644 --- a/vm/vm_compilefunction_code_params_options.md +++ b/vm/vm_compilefunction_code_params_options.md @@ -9,8 +9,8 @@ added: v10.10.0 * `columnOffset` {number} 定义此脚本生成的堆栈跟踪中显示的列偏移量。 **默认值:** `0`。 * `cachedData` {Buffer|TypedArray|DataView} 为源码提供一个 `Buffer`、`TypedArray` 或 `DataView` 格式的 V8 代码缓存。 * `produceCachedData` {boolean} 定义是否需要生成新的缓存数据。**默认值:** `false`。 - * `parsingContext` {Object} 编译函数的[上下文隔离化][contextified]的沙箱。 + * `parsingContext` {Object} 编译函数的[上下文隔离化][contextified]的对象。 * `contextExtensions` {Object[]} 包含要在编译时应用的上下文扩展(包装当前范围的对象)的集合的数组。**默认值:** `[]`。 * 返回: {Function} -将给定的代码编译到提供的上下文/沙箱中(如果没有提供上下文,则使用当前上下文),并返回包装了给定 `params` 的函数。 +将给定的代码编译到提供的上下文中(如果没有提供上下文,则使用当前上下文),并返回包装了给定 `params` 的函数。 diff --git a/vm/vm_createcontext_contextobject_options.md b/vm/vm_createcontext_contextobject_options.md new file mode 100644 index 00000000..9ec4ef4c --- /dev/null +++ b/vm/vm_createcontext_contextobject_options.md @@ -0,0 +1,49 @@ + + +* `contextObject` {Object} +* `options` {Object} + * `name` {string} 新创建的上下文的人类可读名称。 **默认值:** `'VM Context i'`,其中 `i` 是创建的上下文的升序数字索引。 + * `origin` {string} 对应于新创建用于显示目的的上下文的[原点][origin]。 + 原点应格式化为类似一个 URL,但只包含协议,主机和端口(如果需要),例如 [`URL`] 对象的 [`url.origin`] 属性的值。 最值得注意的是,此字符串应省略尾部斜杠,因为它表示路径。 **默认值:** `''`。 + * `codeGeneration` {Object} + * `strings` {boolean} 如果设置为 `false`,则对 `eval` 或函数构造函数(`Function`、`GeneratorFunction` 等)的任何调用都将抛出 `EvalError`。**默认值:** `true`。 + * `wasm` {boolean} 如果设置为 `false`,则任何编译 WebAssembly 模块的尝试都将抛出 `WebAssembly.CompileError`。**默认值:** `true`。 +* 返回: {Object} 上下文隔离化的沙盒。 + +给定一个 `contextObject` 对象,`vm.createContext()` 会[设置此沙盒][contextified],从而让它具备在 [`vm.runInContext()`][] 或者 [`script.runInContext()`][] 中被使用的能力。 +在此类脚本中,`contextObject` 将会是全局对象,保留其所有现有属性,但还具有任何标准的[全局对象][global object]具有的内置对象和函数。 +在 `vm` 模块运行的脚本之外,全局变量将会保持不变。 + + +```js +const util = require('util'); +const vm = require('vm'); + +global.globalVar = 3; + +const context = { globalVar: 1 }; +vm.createContext(context); + +vm.runInContext('globalVar *= 2;', context); + +console.log(util.inspect(context)); // { globalVar: 2 } + +console.log(util.inspect(globalVar)); // 3 +``` + +如果未提供 `contextObject`(或者传入`undefined`),那么会返回一个全新的空的[上下文隔离化][contextified]对象。 + +`vm.createContext()` 主要是用于创建一个能运行多个脚本的上下文。 +比如说,在模拟一个网页浏览器时,此方法可以被用于创建一个单独的上下文来代表一个窗口的全局对象,然后所有的 `