Skip to content

Commit

Permalink
v12.16.0
Browse files Browse the repository at this point in the history
  • Loading branch information
h7lin committed Feb 16, 2020
1 parent 8816a86 commit bac422f
Show file tree
Hide file tree
Showing 330 changed files with 3,165 additions and 1,644 deletions.
5 changes: 3 additions & 2 deletions addons/c_addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
<!--introduced_in=v0.10.0-->
<!-- type=misc -->

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。
Expand Down
14 changes: 3 additions & 11 deletions addons/context_aware_addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ NODE_MODULE_INITIALIZER(Local<Object> exports,

可以通过执行以下步骤来构造上下文感知的插件以避免全局静态数据:

* 定义一个持有每个插件实例数据的类。这样的类应该包含一个 `v8::Persistent<v8::Object>` 持有 `exports` 对象的弱引用。与该弱引用关联的回调函数将会破坏该类的实例。
* 在插件实例化过程中构造这个类的实例,把`v8::Persistent<v8::Object>` 挂到 `exports` 对象上去。
* 定义一个持有每个插件实例数据的类。这样的类应该包含一个 `v8::Global<v8::Object>` 持有 `exports` 对象的弱引用。与该弱引用关联的回调函数将会破坏该类的实例。
* 在插件实例化过程中构造这个类的实例,把`v8::Global<v8::Object>` 挂到 `exports` 对象上去。
* `v8::External` 中保存这个类的实例。
* 通过将 `v8::External` 传给 `v8::FunctionTemplate` 构造函数,该函数会创建本地支持的 JavaScript 函数,把 `v8::External` 传递给所有暴露给 JavaScript 的方法。
`v8::FunctionTemplate` 构造函数的第三个参数接受 `v8::External`
Expand All @@ -56,14 +56,6 @@ class AddonData {
exports_.SetWeak(this, DeleteMe, WeakCallbackType::kParameter);
}
~AddonData() {
if (!exports_.IsEmpty()) {
// 重新设置引用以避免数据泄露。
exports_.ClearWeak();
exports_.Reset();
}
}
// 每个插件的数据。
int call_count;
Expand All @@ -74,7 +66,7 @@ class AddonData {
}
// 导出对象弱句柄。该类的实例将与其若绑定的 exports 对象一起销毁。
v8::Persistent<v8::Object> exports_;
v8::Global<v8::Object> exports_;
};
static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
Expand Down
12 changes: 9 additions & 3 deletions addons/factory_of_wrapped_objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class MyObject : public node::ObjectWrap {
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
static v8::Global<v8::Function> constructor;
double value_;
};
Expand All @@ -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<Function> MyObject::constructor;
// 注意!这不是线程安全的,此插件不能用于工作线程。
Global<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
Expand All @@ -113,6 +115,10 @@ void MyObject::Init(Isolate* isolate) {
Local<Context> context = isolate->GetCurrentContext();
constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
AddEnvironmentCleanupHook(isolate, [](void*) {
constructor.Reset();
}, nullptr);
}
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
Expand Down
12 changes: 9 additions & 3 deletions addons/passing_wrapped_objects_around.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class MyObject : public node::ObjectWrap {
~MyObject();
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
static v8::Global<v8::Function> constructor;
double value_;
};
Expand All @@ -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<Function> MyObject::constructor;
// 注意!这不是线程安全的,此插件不能用于工作线程。
Global<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
Expand All @@ -118,6 +120,10 @@ void MyObject::Init(Isolate* isolate) {
Local<Context> context = isolate->GetCurrentContext();
constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
AddEnvironmentCleanupHook(isolate, [](void*) {
constructor.Reset();
}, nullptr);
}
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
Expand Down
65 changes: 62 additions & 3 deletions addons/worker_support.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

为了从多个 Node.js 环境加载,例如主线程和工作线程,插件还需要:

* 是一个 N-API 插件,或
* 如上所述,使用 `NODE_MODULE_INIT()` 声明为上下文感知。

为了支持 [`Worker`] 线程,插件需要清理可能分配的任何资源(当存在这样的线程时)。
这可以通过使用 `AddEnvironmentCleanupHook()` 函数来实现:

Expand All @@ -10,8 +15,62 @@ void AddEnvironmentCleanupHook(v8::Isolate* isolate,

此函数添加了一个钩子,该钩子将在给定的 Node.js 实例关闭之前运行。
如有必要,可以在运行之前使用 `RemoveEnvironmentCleanupHook()` 删除此类挂钩,它们具有相同的签名。
回调以后进先出的顺序运行。

以下的 `addon.cc` 使用 `AddEnvironmentCleanupHook`

```cpp
// addon.cc
#include <assert.h>
#include <stdlib.h>
#include <node.h>
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<Isolate*>(arg);
HandleScope scope(isolate);
Local<Object> obj = Object::New(isolate);
assert(!obj.IsEmpty()); // 断言 VM 仍然存在。
assert(obj->IsObject());
cleanup_cb1_called++;
}
static void cleanup_cb2(void* arg) {
assert(arg == static_cast<void*>(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()` 声明为上下文感知。

23 changes: 14 additions & 9 deletions addons/wrapping_c_objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class MyObject : public node::ObjectWrap {
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
Expand Down Expand Up @@ -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<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
Expand All @@ -84,21 +82,27 @@ MyObject::~MyObject() {
void MyObject::Init(Local<Object> exports) {
Isolate* isolate = exports->GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
Local<ObjectTemplate> addon_data_tpl = ObjectTemplate::New(isolate);
addon_data_tpl->SetInternalFieldCount(1); // MyObject::New() 的一个字段。
Local<Object> addon_data =
addon_data_tpl->NewInstance(context).ToLocalChecked();
// 准备构造函数模版
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New, addon_data);
tpl->SetClassName(String::NewFromUtf8(
isolate, "MyObject", NewStringType::kNormal).ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// 原型
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
Local<Context> context = isolate->GetCurrentContext();
constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
Local<Function> 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<Value>& args) {
Expand All @@ -116,7 +120,8 @@ void MyObject::New(const FunctionCallbackInfo<Value>& args) {
// 像普通方法 `MyObject(...)` 一样调用,转为构造调用。
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
Local<Function> cons = Local<Function>::New(isolate, constructor);
Local<Function> cons =
args.Data().As<Object>()->GetInternalField(0).As<Function>();
Local<Object> result =
cons->NewInstance(context, argc, argv).ToLocalChecked();
args.GetReturnValue().Set(result);
Expand Down
35 changes: 35 additions & 0 deletions assert/assert_doesnotmatch_string_regexp_message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!-- YAML
added: v12.16.0
-->

* `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`][].

7 changes: 4 additions & 3 deletions assert/assert_doesnotthrow_fn_error_message.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -19,7 +20,7 @@ changes:

当调用 `assert.doesNotThrow()` 时,它将立即调用 `fn` 函数。

如果抛出错误并且它与 `error` 参数指定的类型相同,则抛出 `AssertionError`
如果抛出错误并且它与 `error` 参数指定的类型相同,则抛出 [`AssertionError`]
如果错误的类型不同,或者 `error` 参数未定义,则错误将传播回调用方。

如果指定,则 `error` 可以是 [`Class`][`RegExp`] 或验证函数。
Expand All @@ -38,7 +39,7 @@ assert.doesNotThrow(
);
```

以下示例将导致 `AssertionError`,并显示消息 'Got unwanted exception...'
以下示例将导致 [`AssertionError`],并显示消息 'Got unwanted exception...'

<!-- eslint-disable no-restricted-syntax -->
```js
Expand All @@ -50,7 +51,7 @@ assert.doesNotThrow(
);
```

如果抛出 `AssertionError` 并为 `message` 参数提供了值,则 `message` 的值将附加到 `AssertionError` 消息:
如果抛出 [`AssertionError`] 并为 `message` 参数提供了值,则 `message` 的值将附加到 `AssertionError` 消息:

<!-- eslint-disable no-restricted-syntax -->
```js
Expand Down
2 changes: 1 addition & 1 deletion assert/assert_equal_actual_expected_message.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions assert/assert_fail_message.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ added: v0.1.21
-->
* `message` {string|Error} **默认值:** `'Failed'`

使用提供的错误消息或默认错误消息抛出 `AssertionError`
如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 `AssertionError`
使用提供的错误消息或默认错误消息抛出 [`AssertionError`]
如果 `message` 参数是 [`Error`] 的实例,则它将被抛出而不是 [`AssertionError`]


```js
Expand Down
3 changes: 2 additions & 1 deletion assert/assert_iferror_value.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
Loading

0 comments on commit bac422f

Please sign in to comment.