| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f378256 commit 77f7200
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -733,13 +733,13 @@ napiVersion: 8 | |||
| 733 | 733 | --> | |
| 734 | 734 | ||
| 735 | 735 | A 128-bit value stored as two unsigned 64-bit integers. It serves as a UUID | |
| 736 | - with which JavaScript objects can be "tagged" in order to ensure that they are | ||
| 737 | - of a certain type. This is a stronger check than [`napi_instanceof`][], because | ||
| 738 | - the latter can report a false positive if the object's prototype has been | ||
| 739 | - manipulated. Type-tagging is most useful in conjunction with [`napi_wrap`][] | ||
| 740 | - because it ensures that the pointer retrieved from a wrapped object can be | ||
| 741 | - safely cast to the native type corresponding to the type tag that had been | ||
| 742 | - previously applied to the JavaScript object. | ||
| 736 | + with which JavaScript objects or [externals][] can be "tagged" in order to | ||
| 737 | + ensure that they are of a certain type. This is a stronger check than | ||
| 738 | + [`napi_instanceof`][], because the latter can report a false positive if the | ||
| 739 | + object's prototype has been manipulated. Type-tagging is most useful in | ||
| 740 | + conjunction with [`napi_wrap`][] because it ensures that the pointer retrieved | ||
| 741 | + from a wrapped object can be safely cast to the native type corresponding to the | ||
| 742 | + type tag that had been previously applied to the JavaScript object. | ||
| 743 | 743 | ||
| 744 | 744 | ```c | |
| 745 | 745 | typedef struct { | |
@@ -4967,7 +4967,7 @@ To this end, Node-API provides type-tagging capabilities. | |||
| 4967 | 4967 | ||
| 4968 | 4968 | A type tag is a 128-bit integer unique to the addon. Node-API provides the | |
| 4969 | 4969 | `napi_type_tag` structure for storing a type tag. When such a value is passed | |
| 4970 | - along with a JavaScript object stored in a `napi_value` to | ||
| 4970 | + along with a JavaScript object or [external][] stored in a `napi_value` to | ||
| 4971 | 4971 | `napi_type_tag_object()`, the JavaScript object will be "marked" with the | |
| 4972 | 4972 | type tag. The "mark" is invisible on the JavaScript side. When a JavaScript | |
| 4973 | 4973 | object arrives into a native binding, `napi_check_object_type_tag()` can be used | |
@@ -5253,15 +5253,15 @@ napi_status napi_type_tag_object(napi_env env, | |||
| 5253 | 5253 | ``` | |
| 5254 | 5254 | ||
| 5255 | 5255 | * `[in] env`: The environment that the API is invoked under. | |
| 5256 | - * `[in] js_object`: The JavaScript object to be marked. | ||
| 5256 | + * `[in] js_object`: The JavaScript object or [external][] to be marked. | ||
| 5257 | 5257 | * `[in] type_tag`: The tag with which the object is to be marked. | |
| 5258 | 5258 | ||
| 5259 | 5259 | Returns `napi_ok` if the API succeeded. | |
| 5260 | 5260 | ||
| 5261 | - Associates the value of the `type_tag` pointer with the JavaScript object. | ||
| 5262 | - `napi_check_object_type_tag()` can then be used to compare the tag that was | ||
| 5263 | - attached to the object with one owned by the addon to ensure that the object | ||
| 5264 | - has the right type. | ||
| 5261 | + Associates the value of the `type_tag` pointer with the JavaScript object or | ||
| 5262 | + [external][]. `napi_check_object_type_tag()` can then be used to compare the tag | ||
| 5263 | + that was attached to the object with one owned by the addon to ensure that the | ||
| 5264 | + object has the right type. | ||
| 5265 | 5265 | ||
| 5266 | 5266 | If the object already has an associated type tag, this API will return | |
| 5267 | 5267 | `napi_invalid_arg`. | |
@@ -5283,7 +5283,8 @@ napi_status napi_check_object_type_tag(napi_env env, | |||
| 5283 | 5283 | ``` | |
| 5284 | 5284 | ||
| 5285 | 5285 | * `[in] env`: The environment that the API is invoked under. | |
| 5286 | - * `[in] js_object`: The JavaScript object whose type tag to examine. | ||
| 5286 | + * `[in] js_object`: The JavaScript object or [external][] whose type tag to | ||
| 5287 | + examine. | ||
| 5287 | 5288 | * `[in] type_tag`: The tag with which to compare any tag found on the object. | |
| 5288 | 5289 | * `[out] result`: Whether the type tag given matched the type tag on the | |
| 5289 | 5290 | object. `false` is also returned if no type tag was found on the object. | |
@@ -6453,6 +6454,8 @@ the add-on's file name during loading. | |||
| 6453 | 6454 | [async_hooks `type`]: async_hooks.md#type | |
| 6454 | 6455 | [context-aware addons]: addons.md#context-aware-addons | |
| 6455 | 6456 | [docs]: https://github.com/nodejs/node-addon-api#api-documentation | |
| 6457 | + [external]: #napi_create_external | ||
| 6458 | + [externals]: #napi_create_external | ||
| 6456 | 6459 | [global scope]: globals.md | |
| 6457 | 6460 | [gyp-next]: https://github.com/nodejs/gyp-next | |
| 6458 | 6461 | [module scope]: modules.md#the-module-scope | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -165,12 +165,26 @@ assert.strictEqual(newObject.test_string, 'test string'); | |||
| 165 | 165 | const obj2 = test_object.TypeTaggedInstance(1); | |
| 166 | 166 | const obj3 = test_object.TypeTaggedInstance(2); | |
| 167 | 167 | const obj4 = test_object.TypeTaggedInstance(3); | |
| 168 | + const external = test_object.TypeTaggedExternal(2); | ||
| 169 | + const plainExternal = test_object.PlainExternal(); | ||
| 170 | + | ||
| 171 | + // Verify that we do not allow type tag indices greater than the largest | ||
| 172 | + // available index. | ||
| 173 | + assert.throws(() => test_object.TypeTaggedInstance(39), { | ||
| 174 | + name: 'RangeError', | ||
| 175 | + message: 'Invalid type index', | ||
| 176 | + }); | ||
| 177 | + assert.throws(() => test_object.TypeTaggedExternal(39), { | ||
| 178 | + name: 'RangeError', | ||
| 179 | + message: 'Invalid type index', | ||
| 180 | + }); | ||
| 168 | 181 | ||
| 169 | 182 | // Verify that type tags are correctly accepted. | |
| 170 | 183 | assert.strictEqual(test_object.CheckTypeTag(0, obj1), true); | |
| 171 | 184 | assert.strictEqual(test_object.CheckTypeTag(1, obj2), true); | |
| 172 | 185 | assert.strictEqual(test_object.CheckTypeTag(2, obj3), true); | |
| 173 | 186 | assert.strictEqual(test_object.CheckTypeTag(3, obj4), true); | |
| 187 | + assert.strictEqual(test_object.CheckTypeTag(2, external), true); | ||
| 174 | 188 | ||
| 175 | 189 | // Verify that wrongly tagged objects are rejected. | |
| 176 | 190 | assert.strictEqual(test_object.CheckTypeTag(0, obj2), false); | |
@@ -180,10 +194,19 @@ assert.strictEqual(newObject.test_string, 'test string'); | |||
| 180 | 194 | assert.strictEqual(test_object.CheckTypeTag(2, obj4), false); | |
| 181 | 195 | assert.strictEqual(test_object.CheckTypeTag(3, obj3), false); | |
| 182 | 196 | assert.strictEqual(test_object.CheckTypeTag(4, obj3), false); | |
| 197 | + assert.strictEqual(test_object.CheckTypeTag(0, external), false); | ||
| 198 | + assert.strictEqual(test_object.CheckTypeTag(1, external), false); | ||
| 199 | + assert.strictEqual(test_object.CheckTypeTag(3, external), false); | ||
| 200 | + assert.strictEqual(test_object.CheckTypeTag(4, external), false); | ||
| 183 | 201 | ||
| 184 | 202 | // Verify that untagged objects are rejected. | |
| 185 | 203 | assert.strictEqual(test_object.CheckTypeTag(0, {}), false); | |
| 186 | 204 | assert.strictEqual(test_object.CheckTypeTag(1, {}), false); | |
| 205 | + assert.strictEqual(test_object.CheckTypeTag(0, plainExternal), false); | ||
| 206 | + assert.strictEqual(test_object.CheckTypeTag(1, plainExternal), false); | ||
| 207 | + assert.strictEqual(test_object.CheckTypeTag(2, plainExternal), false); | ||
| 208 | + assert.strictEqual(test_object.CheckTypeTag(3, plainExternal), false); | ||
| 209 | + assert.strictEqual(test_object.CheckTypeTag(4, plainExternal), false); | ||
| 187 | 210 | } | |
| 188 | 211 | ||
| 189 | 212 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -605,13 +605,23 @@ static napi_value TestSeal(napi_env env, | |||
| 605 | 605 | } | |
| 606 | 606 | ||
| 607 | 607 | // We create two type tags. They are basically 128-bit UUIDs. | |
| 608 | - static const napi_type_tag type_tags[5] = { | ||
| 609 | - { 0xdaf987b3cc62481a, 0xb745b0497f299531 }, | ||
| 610 | - { 0xbb7936c374084d9b, 0xa9548d0762eeedb9 }, | ||
| 611 | - { 0xa5ed9ce2e4c00c38, 0 }, | ||
| 612 | - { 0, 0 }, | ||
| 613 | - { 0xa5ed9ce2e4c00c38, 0xdaf987b3cc62481a }, | ||
| 608 | + #define TYPE_TAG_COUNT 5 | ||
| 609 | + static const napi_type_tag type_tags[TYPE_TAG_COUNT] = { | ||
| 610 | + {0xdaf987b3cc62481a, 0xb745b0497f299531}, | ||
| 611 | + {0xbb7936c374084d9b, 0xa9548d0762eeedb9}, | ||
| 612 | + {0xa5ed9ce2e4c00c38, 0}, | ||
| 613 | + {0, 0}, | ||
| 614 | + {0xa5ed9ce2e4c00c38, 0xdaf987b3cc62481a}, | ||
| 614 | 615 | }; | |
| 616 | + #define VALIDATE_TYPE_INDEX(env, type_index) \ | ||
| 617 | + do { \ | ||
| 618 | + if ((type_index) >= TYPE_TAG_COUNT) { \ | ||
| 619 | + NODE_API_CALL((env), \ | ||
| 620 | + napi_throw_range_error((env), \ | ||
| 621 | + "NODE_API_TEST_INVALID_TYPE_INDEX", \ | ||
| 622 | + "Invalid type index")); \ | ||
| 623 | + } \ | ||
| 624 | + } while (0) | ||
| 615 | 625 | ||
| 616 | 626 | static napi_value | |
| 617 | 627 | TypeTaggedInstance(napi_env env, napi_callback_info info) { | |
@@ -621,12 +631,42 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { | |||
| 621 | 631 | ||
| 622 | 632 | NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); | |
| 623 | 633 | NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); | |
| 634 | + VALIDATE_TYPE_INDEX(env, type_index); | ||
| 624 | 635 | NODE_API_CALL(env, napi_create_object(env, &instance)); | |
| 625 | 636 | NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); | |
| 626 | 637 | ||
| 627 | 638 | return instance; | |
| 628 | 639 | } | |
| 629 | 640 | ||
| 641 | + // V8 will not allowe us to construct an external with a NULL data value. | ||
| 642 | + #define IN_LIEU_OF_NULL ((void*)0x1) | ||
| 643 | + | ||
| 644 | + static napi_value PlainExternal(napi_env env, napi_callback_info info) { | ||
| 645 | + napi_value instance; | ||
| 646 | + | ||
| 647 | + NODE_API_CALL( | ||
| 648 | + env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance)); | ||
| 649 | + | ||
| 650 | + return instance; | ||
| 651 | + } | ||
| 652 | + | ||
| 653 | + static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) { | ||
| 654 | + size_t argc = 1; | ||
| 655 | + uint32_t type_index; | ||
| 656 | + napi_value instance, which_type; | ||
| 657 | + | ||
| 658 | + NODE_API_CALL(env, | ||
| 659 | + napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); | ||
| 660 | + NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); | ||
| 661 | + VALIDATE_TYPE_INDEX(env, type_index); | ||
| 662 | + NODE_API_CALL( | ||
| 663 | + env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance)); | ||
| 664 | + NODE_API_CALL(env, | ||
| 665 | + napi_type_tag_object(env, instance, &type_tags[type_index])); | ||
| 666 | + | ||
| 667 | + return instance; | ||
| 668 | + } | ||
| 669 | + | ||
| 630 | 670 | static napi_value | |
| 631 | 671 | CheckTypeTag(napi_env env, napi_callback_info info) { | |
| 632 | 672 | size_t argc = 2; | |
@@ -636,6 +676,7 @@ CheckTypeTag(napi_env env, napi_callback_info info) { | |||
| 636 | 676 | ||
| 637 | 677 | NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); | |
| 638 | 678 | NODE_API_CALL(env, napi_get_value_uint32(env, argv[0], &type_index)); | |
| 679 | + VALIDATE_TYPE_INDEX(env, type_index); | ||
| 639 | 680 | NODE_API_CALL(env, napi_check_object_type_tag(env, | |
| 640 | 681 | argv[1], | |
| 641 | 682 | &type_tags[type_index], | |
@@ -648,31 +689,36 @@ CheckTypeTag(napi_env env, napi_callback_info info) { | |||
| 648 | 689 | EXTERN_C_START | |
| 649 | 690 | napi_value Init(napi_env env, napi_value exports) { | |
| 650 | 691 | napi_property_descriptor descriptors[] = { | |
| 651 | - DECLARE_NODE_API_PROPERTY("Get", Get), | ||
| 652 | - DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), | ||
| 653 | - DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), | ||
| 654 | - DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), | ||
| 655 | - DECLARE_NODE_API_PROPERTY("GetEnumerableWritableNames", GetEnumerableWritableNames), | ||
| 656 | - DECLARE_NODE_API_PROPERTY("GetOwnWritableNames", GetOwnWritableNames), | ||
| 657 | - DECLARE_NODE_API_PROPERTY("GetEnumerableConfigurableNames", GetEnumerableConfigurableNames), | ||
| 658 | - DECLARE_NODE_API_PROPERTY("GetOwnConfigurableNames", GetOwnConfigurableNames), | ||
| 659 | - DECLARE_NODE_API_PROPERTY("Set", Set), | ||
| 660 | - DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), | ||
| 661 | - DECLARE_NODE_API_PROPERTY("Has", Has), | ||
| 662 | - DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed), | ||
| 663 | - DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn), | ||
| 664 | - DECLARE_NODE_API_PROPERTY("Delete", Delete), | ||
| 665 | - DECLARE_NODE_API_PROPERTY("New", New), | ||
| 666 | - DECLARE_NODE_API_PROPERTY("Inflate", Inflate), | ||
| 667 | - DECLARE_NODE_API_PROPERTY("Wrap", Wrap), | ||
| 668 | - DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap), | ||
| 669 | - DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), | ||
| 670 | - DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), | ||
| 671 | - DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), | ||
| 672 | - DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), | ||
| 673 | - DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), | ||
| 674 | - DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), | ||
| 675 | - DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal), | ||
| 692 | + DECLARE_NODE_API_PROPERTY("Get", Get), | ||
| 693 | + DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), | ||
| 694 | + DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), | ||
| 695 | + DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), | ||
| 696 | + DECLARE_NODE_API_PROPERTY("GetEnumerableWritableNames", | ||
| 697 | + GetEnumerableWritableNames), | ||
| 698 | + DECLARE_NODE_API_PROPERTY("GetOwnWritableNames", GetOwnWritableNames), | ||
| 699 | + DECLARE_NODE_API_PROPERTY("GetEnumerableConfigurableNames", | ||
| 700 | + GetEnumerableConfigurableNames), | ||
| 701 | + DECLARE_NODE_API_PROPERTY("GetOwnConfigurableNames", | ||
| 702 | + GetOwnConfigurableNames), | ||
| 703 | + DECLARE_NODE_API_PROPERTY("Set", Set), | ||
| 704 | + DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), | ||
| 705 | + DECLARE_NODE_API_PROPERTY("Has", Has), | ||
| 706 | + DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed), | ||
| 707 | + DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn), | ||
| 708 | + DECLARE_NODE_API_PROPERTY("Delete", Delete), | ||
| 709 | + DECLARE_NODE_API_PROPERTY("New", New), | ||
| 710 | + DECLARE_NODE_API_PROPERTY("Inflate", Inflate), | ||
| 711 | + DECLARE_NODE_API_PROPERTY("Wrap", Wrap), | ||
| 712 | + DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap), | ||
| 713 | + DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), | ||
| 714 | + DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), | ||
| 715 | + DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), | ||
| 716 | + DECLARE_NODE_API_PROPERTY("TypeTaggedExternal", TypeTaggedExternal), | ||
| 717 | + DECLARE_NODE_API_PROPERTY("PlainExternal", PlainExternal), | ||
| 718 | + DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), | ||
| 719 | + DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), | ||
| 720 | + DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), | ||
| 721 | + DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal), | ||
| 676 | 722 | }; | |
| 677 | 723 | ||
| 678 | 724 | init_test_null(env, exports); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments